Posteriormente a investigar con expertos en esta materia, programadores de diversas ramas y profesores hemos dado con la solución al dilema y la compartimos en este post.
Solución:
Python 3.5, 404400392312311308290281285 281 bytes:
(Gracias a Adnan por un consejo sobre cómo ahorrar 9 bytes (290->281
) y Neil por un consejo sobre cómo ahorrar 4 bytes (285->281
)!)
def u(z):
p=[];P=print;S,N,M,X=' -|n'
while not p or z:p+=[z%20];z=z//20
E=lambda i:(S+N*4+S)*i+X+((M+S*4+M)*i+X)*2+(S+N*4+S)*i+X;F=N*32+X+M+S*30+M+X+N*32+X;[P(S+N*19+S+X+M+((S*4+M)*4+X+M)*2+N*19+M+X+(M+S*19+M+X)*2+S+N*19+S+X*3)if y<1else P(E(y%5)+F*(y//5)+X*3)for y in p[::-1]]
¡Pruébelo en línea! (Ideone)
Análisis
Para los propósitos de este análisis, usaremos el juego de caracteres 0123456789ABCDEFGHIJ
para representar cada dígito en base 20.
Entonces, podría haber convertido la base 10 en base 20 usando uno de los dos algoritmos que tengo. El primer algoritmo que pensé en usar es lo que llamo el algoritmo de poderes. Sin embargo, este no es el que usé en el código, ya que lo habría hecho mucho más largo de lo que debería haber sido, así que no voy a hablar de este. Sin embargo, creé un script de Python que convierte cualquier número entero en base 10 en cualquier otra base proporcionada usando este método, que puede usar aquí en repl.it. El que usé en cambio para este desafío es lo que llamo el algoritmo de división, que creo que se explica bastante bien aquí. Pero básicamente lo que sucede es que toma el número de base 10 proporcionado y lo divide por la base a la que necesita convertir el número, que en este caso es 20, hasta que el resto sea 0 o 1. Luego toma el cociente y el resto , en ese orden, desde el último operación de división, y luego todos los demás restos de las otras operaciones de división en el orden de la última a la primera. Luego, todos estos dígitos se unen, y esa secuencia unida invertido es su número de base 10 en base 20! Para ilustrar esto, suponga que desea convertir el número de base 10 431
a la base 20. Entonces, lo que haríamos es esto:
[]=list we will put all remainders and the last quotient in
R = Remainder
1. 431/20 = 21 R11 [B (B=11 in base 20)]
2. 21/20 = 1 R1 [Add the remainder and quotient: B11]
Luego, finalmente tomaríamos la lista que tenemos, que en este caso contiene B11
, y marcha atrás es para que ahora tengamos 11B
. Al hacer esto, ¡finalmente obtuvimos nuestra respuesta final! 431 en base 10 convertido a base 20 es 11B
, que se puede confirmar usando mi script de Python que usa el algoritmo de poderes con el que ya compartí un enlace arriba, pero lo haré nuevamente aquí. Aquí hay uno que también usa el algoritmo de división descrito en esta respuesta y devuelve la misma respuesta que la potencia uno.
Todo este proceso es esencialmente lo que sucede en mi script en este while
círculo: while not p or z:p+=[z%20];z=z//20
. La única diferencia es que los números >9
están no representados como letras, sino como ellos mismos.
Continuando, después de que el número de base 10 se haya convertido a base 20, para cada dígito en el entero de base 20, que llamaremos g
, g mod 5
los puntos se imprimen y luego g//5
se imprimen las barras. Luego, el programa imprime 3 líneas en blanco y pasa al siguiente dígito. Sin embargo, si el dígito es 0
, luego se imprime una sola "barra" seguida de 3 nuevas líneas, y luego el programa pasa al siguiente dígito. Entonces, tomando el número base 20 11B
, pasamos al primer dígito. El primer dígito es 1
, y por lo tanto imprimiría 0 barras ya que 1//5=0
y 1 punto desde 1%5=1
. Entonces, primero obtendríamos esto:
----
| |
| |
----
y luego 3 nuevas líneas. Pasando al segundo dígito, también vemos que es 1, por lo que generaría lo mismo:
----
| |
| |
----
y también 3 nuevas líneas. Finalmente, pasando al último dígito, vemos que es un B
. Ya que B=11
en base 20, el programa generaría 1 punto ya que 11%5=1
y 2 barras desde 11//5=2
. Entonces ahora, obtenemos esto:
----
| |
| |
----
--------------------------------
| |
--------------------------------
--------------------------------
| |
--------------------------------
Finalmente, juntando todo esto, obtenemos esto:
----
| |
| |
----
----
| |
| |
----
----
| |
| |
----
--------------------------------
| |
--------------------------------
--------------------------------
| |
--------------------------------
¡Y ese es el número maya para 431! Finalmente tienes tu número de base 10 representado en números mayas de base 20.
Nota: Puede que hayas notado o no que lambda
función en mi código. Independientemente, esta función se utiliza para la creación de puntos, ya que se deben generar varios puntos uno al lado del otro.
Rubí, 223180177 179 bytes
Función anónima, devuelve una multilínea string.
Olvidé agregar un espacio adicional que se necesitaba, y también la recursividad. También jugué un poco más cambiando las cosas.
f=->n;e=' ';n<20?(n<1?[t=e+d=?-*19,a=s+(e*4+s)*4,a,s+d+s,b=s+e*19+s,b,t]:((r=n%5)>0?[t=" ---- "*r,m="
Python 3, 243 bytes
s,v,h,x=' |-n';P=print
t=s+h*19+s+x
def m(n):
n//20and m(n//20);r=n%20
if r:
for a,b,f in[(r%5*' ---- ',r%5*'| | ',1),('-'*32,'|'+' '*30+'|',r//5)]:P(*((a,b,b,a)*f),sep=x)
else:P(t+2*(v+(4*s+v)*4+x)+v+h*19+v+x+2*(v+s*19+v+x)+t)
P(x)
Discusión
n//20and m(n//20)
llamadas m()
de forma recursiva si hay potencias superiores a 20 para manejar. La recursividad se realiza antes de imprimir el valor posicional actual, de modo que las potencias superiores se impriman primero.
Si el valor posicional actual es distinto de cero (r! = 0), el for a,b,f
-loop imprime las unidades y luego los cincos. a
es la primera / cuarta fila y b
es la segunda / tercera fila. El truco está en el print(*((a,b,b,a)*f),sep=x)
. Para las unidades, f = 1 resultando en print(*(a,b,b,a),sep=x)
, que imprime las 4 filas que componen los símbolos de las unidades (x es un ' n'). Para los cinco, f = el número de cinco para imprimir (r // 5), por lo que la tupla (a, b, b, a) se multiplica (es decir, se repite) por el número de cinco para imprimir. Si f = 2, obtenemos print(*(a,b,b,a,a,b,b,a),sep=x)
, que imprime dos símbolos por cinco.
Si el valor posicional actual es 0, se imprime el símbolo cero.