El conteo de la rosa

Estando ya al final de mi vida de pecador, esperando que mi enfermo y pesado cuerpo libere mi alma para poder enfrentarme al Príncipe de los Apóstoles, vienen a mi memoria lejanos recuerdos que aún conservo pese a que, al mismo tiempo, no me sea posible, cual hechizo del Anticristo, recordar lo que desayuné tras mis rezos de Maitines.

Siendo apenas un novicio, desconocedor de la Santa y férrea disciplina del monasterio, me enfrenté con el abad, cuyo nombre prefiero ahora cubrir con un piadoso manto de silencio, por lo que mi joven entendimiento consideró una afrenta del bibliotecario mayor. Éste nos encargó a Adso, otro novicio que a la par llegaría a ser sabio franciscano, y a mí que numeráramos las 200 páginas de una nueva edición de la Poética de Aristóteles que varios monjes habían estado copiando durante meses atrás. El bibliotecario, que Dios tenga en Su Gloria, le asignó a Adso la numeración de las 100 primeras páginas del manuscrito, de la 1 a la 100, mientras que a mí me fueron asignadas las 100 siguientes, de la 101 a la 200. Yo, que había oído preocupantes rumores sobre una maldición que mataba a todo aquél que se acercaba a ese libro, caí en la cuenta de que me vería obligado a transcribir muchos más dígitos, que no páginas, que mi compañero de celda, razón que me llevó a mi enfrentamiento con el abad.

Éste, que consideró una mera lujuria del conocimiento que me hubiera planteado ni siquiera semejante hecho, me forzó a rezar en Laudes, Tercia y Vísperas durante todo un año el Salmo 30 para pedir protección contra las injusticias. Aun así, algo debió ver en mis ojos brillantes de muchacho, que concedió darme la bula de su castigo si le decía hasta qué página debía numerar Adso, y a partir de cuál debía numerar yo para que el reparto fuera justo, de forma que si Adso numerara una página más ya tendría que escribir más dígitos que yo.

En el pecado llevé mi penitencia, porque me tembló el entendimiento y ni siquiera hoy el Señor me ha concedido la gracia de descubrir la respuesta.

Entrada

La entrada consta de una serie de casos de prueba. Cada caso son dos números, el primero indica la página inicial a numerar y el segundo la página final. Se garantiza que 1 ≤ p1 < p2 ≤ 1.000.000. La entrada termina con dos valores a cero.

Salida

Para cada caso de prueba se indicará la última página que debería escribir Adso, el primer monje, de tal forma que ambos escriban la misma cantidad de dígitos. Si esto resulta imposible, Adso deberá numerar la mayor cantidad posible de páginas siempre que escriba menos dígitos que el segundo monje.

Entrada de ejemplo

1 200
99 100
99 101
97 103
0 0

Salida de ejemplo

118
99
99
100

Solución propuesta

if __name__ == '__main__':
    inicio, fin = [int(x) for x in input().split(' ')]
    respuestas = []
    while inicio != 0 and fin != 0:
        paginas = range(inicio, fin+1)
        sumatorio = sum([len(str(x)) for x in paginas])
        posicion = 0
        conteo = len(str(paginas[posicion]))
        while conteo + len(str(paginas[posicion])) < sumatorio // 2:
            conteo += len(str(paginas[posicion]))
            posicion += 1
        respuestas.append(paginas[posicion])
        inicio, fin = [int(x) for x in input().split(' ')]
    for x in respuestas:
        print(x)

Para resolver este ejercicio vamos a pensar en cómo lo resolveríamos a mano, no hay que olvidar que cuando programamos lo que hacemos es plasmar nuestro razonamiento. En este caso la forma de resolverlo sería contar todas las cifras y después comprobar hasta qué página tiene que escribir cada uno.

Comenzando con el código, en la variable paginas, almacenamos la lista de las páginas a escribir. Debajo, en la variable sumatorio, la suma de todas las cifras a escribir para ellos hacemos uso de la función sum() que suma la lista de números que le pasemos. Para ello hay que tener en cuenta que si tenemos la lista [99, 100, 101], no hay sumar 99 + 100 + 101, si no, cuántas cifras tiene cada número, por ese motivo, se convierten los número a cadenas de caracteres y se utiliza la función len(), que devuelve la longitud de una cadena de caracteres. De modo que sumaríamos 2 + 3 + 3.

Una vez que hemos realizado estos cálculos, comenzamos la búsqueda de la página, para ello ponemos condición del while la que nos piden, y es que el primer monje siempre escriba la mitad o menos. También hay que tener en cuenta que como la última página que debe escribir el primer monje, puede ser la primera, hemos de calcular a partir de la siguiente, ya que sabemos que al menos uno va a escribir.

Una vez que tenemos la respuesta no debemos más que añadirla a la lista de respuestas y calcular el siguiente caso. Este es un buen ejercicio para practicar condiciones de bucles y manejo de listas, algo básico para cualquier programador.

Enlace del código

Enlace en aceptaelreto.com

Publicado el 7 de agosto de 2017