Números maias de arte ASCII

14

Esse desafio é simples. Dado um número, imprima uma representação artística do número, usando o sistema numérico maia da Base-20.

O que é o sistema maia?

Os maias usavam a base 20 para armazenar números, então a primeira posição era a 1 lugar s, a próxima o 20lugar s, depois o 400s, etc.

Então, o número maia 1está 1na base 10, mas na 10verdade é 20na base 10,207 está 807na base 10, etc.

E eles representavam seus números como pictogramas, com um símbolo especial para 0.

 -------------------
|    |    |    |    |
|    |    |    |    |
|-------------------|
|                   |
|                   |
 ------------------- 

Esse foi o zero deles. (pelo menos a metade picascii metade minha artistica ascii art version)

Isso é real imagem do símbolo maia zero. 1

Estes eram os cinco deles:

--------------------------------
|                              |
--------------------------------

E um 4:

 ----   ----   ----   ----  
|    | |    | |    | |    | 
|    | |    | |    | |    | 
 ----   ----   ----   ----  

Finalmente, para montar:

 ----   ----   ----  
|    | |    | |    | 
|    | |    | |    | 
 ----   ----   ----  
--------------------------------
|                              |
--------------------------------
--------------------------------
|                              |
--------------------------------

Então eles têm x//5barras e x%5pontos em cima das barras. E se x=0, eles usam o shell / pão em vez de um espaço em branco.

Para mais imagens, tente a página Wikimedia Commons de imagens numéricas do Maya .

Mas isso é apenas para números de até 19. Não podemos ter mais do que 4barras e 4pontos em uma única 'história' ... Então, subimos!

A saída para 20 é:

 ----
|    |
|    |
 ----



 -------------------
|    |    |    |    |
|    |    |    |    |
|-------------------|
|                   |
|                   |
 ------------------- 

Observe que isso normalmente seria inválido, pois possui a 1e 0a ao mesmo tempo. Mas 3(observe que, sua resposta precisa de pelo menos 3) novas linhas antes da 0média de um novo valor de local.

A história inferior tem pontos, significado 1e significado de barras 5. Mas na verdade tem significado de pontos 20^0e significado de barras 20^0 * 5.

Cada história sobe um poder. Os pontos da segunda história significam 20( 20^1) e 100( 20^1 * 5).

Portanto, o número 506pode ser representado como:

 ----  
|    | 
|    | 
 ----  




--------------------------------
|                              |
--------------------------------




 ----  
|    | 
|    | 
 ----  
--------------------------------
|                              |
--------------------------------

Isto é (20^0) * 1 + (20^0 * 5) * 1 + (20^1 * 5) * 1 + (20^2) * 1 = 1 + 5 + 100 + 400 = 506 .

Sua missão, caso você escolha ou não (não importa), é produzir uma representação artística do número da base 10.

Outras regras:

  • O espaço à esquerda / à direita é bom, desde que os pontos, barras e conchas estejam intactos.
  • As barras, pontos e conchas devem ser exatamente o que os casos de teste possuem. Sem redimensionamento.
  • Os principais 0 são bons. (conchas principais na saída)
  • Você não precisa ter exatamente três novas linhas entre cada valor de lugar ou história, apenas pelo menos três.

Casos de teste:

15

--------------------------------
|                              |
--------------------------------
--------------------------------
|                              |
--------------------------------
--------------------------------
|                              |
--------------------------------  

12

 ----   ----  
|    | |    | 
|    | |    | 
 ----   ----  
--------------------------------
|                              |
--------------------------------
--------------------------------
|                              |
--------------------------------



4

 ----   ----   ----   ----  
|    | |    | |    | |    | 
|    | |    | |    | |    | 
 ----   ----   ----   ----  


0

 -------------------
|    |    |    |    |
|    |    |    |    |
|-------------------|
|                   |
|                   |
 ------------------- 


24

 ----  
|    | 
|    | 
 ----  




 ----   ----   ----   ----  
|    | |    | |    | |    | 
|    | |    | |    | |    | 
 ----   ----   ----   ----  



33



 ----  
|    |  
|    | 
 ----  




 ----   ----   ----  
|    | |    | |    | 
|    | |    | |    | 
 ----   ----   ----  
--------------------------------
|                              |
--------------------------------
--------------------------------
|                              |
--------------------------------



20



 ----  
|    | 
|    | 
 ----  




 -------------------
|    |    |    |    |
|    |    |    |    |
|-------------------| 
|                   |
|                   |
 -------------------  

1: Eles também usaram as cabeças de deuses para os símbolos, mas para esse desafio o baú de casca / pão / zelda será usado.

Rɪᴋᴇʀ
fonte
but for this challenge the shell/bread will be used.. Nem casca, nem pão. Link LOZ para o baú passado.
amigos estão
@epicTCK .... que é realmente muito parecido com isso ...
Rɪᴋᴇʀ
1
Relacionado.
Martin Ender

Respostas:

4

Ruby, 223 180 177 179 bytes

Função anônima, retorna uma sequência de linhas múltiplas.

Esqueceu-se de adicionar algum espaçamento extra necessário e também a recursão. Também jogou um pouco mais ao mudar as coisas.

f=->n{s=?|;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="|    | "*r,m,t]:[])+[a=?-*32,s+e*30+s,a]*(n/5))*$/:f[n/20]+$/*5+f[n%20]}
Value Ink
fonte
Você é o golfista. Parabéns!
Rɪᴋᴇʀ
6

Python 3.5, 404 400 392 312 311 308 290 281 285 281 bytes:

( Agradecemos a Adnan por uma dica sobre como salvar 9 bytes ( 290->281) e Neil por uma dica para salvar 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]]

Experimente online! (Ideona)

Análise

Para os fins desta análise, usaremos o conjunto de caracteres 0123456789ABCDEFGHIJpara representar cada dígito na base 20.

Então, eu poderia ter convertido a base 10 na base 20 usando um dos dois algoritmos que tenho. O primeiro algoritmo que pensei em usar é o que chamo de algoritmo de potências . Este não é o que eu usei no código, pois ele teria feito muito mais tempo do que deveria, então não vou falar sobre esse. No entanto, criei um script python que converte qualquer número inteiro na base 10 em qualquer outra base fornecida usando esse método, que você pode usar aqui em repl.it. O que eu usei para esse desafio é o que chamo de algoritmo de divisão , que eu acho que é explicado aqui muito bem. Mas basicamente o que acontece é que ele pega o número da base 10 fornecido e o divide pela base para a qual precisa converter o número, que neste caso é 20, até o restante ser 0 ou 1. Em seguida, pega o quociente e o restante , nessa ordem, da última operação de divisão e, em seguida, todos os outros restos das outras operações de divisão na ordem do último ao primeiro. Todos esses dígitos são então unidos, e essa sequência unida invertida é o seu número 10 na base 20! Para ilustrar isso, suponha que você deseje converter o número da base 10 431em base 20. Então, o que faríamos é o seguinte:

[]=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]

Então, finalmente, pegaremos a lista que temos, que neste caso contém B11, e a reverteremos para a que temos agora 11B. Ao fazer isso, finalmente conseguimos nossa resposta final! 431 na base 10 convertida para a base 20 é 11B, o que pode ser confirmado usando meu script Python que usa o algoritmo de poderes com o qual eu já compartilhei um link acima, mas farei isso novamente aqui . Aqui está um que também usa o algoritmo de divisão descrito nesta resposta e retorna a mesma resposta que a das potências.

Todo esse processo é essencialmente o que acontece no meu script neste whileloop: while not p or z:p+=[z%20];z=z//20. A única diferença é que os números não>9 são representados como letras, mas como eles mesmos.

Continuando, depois que o número da base 10 tiver sido convertido para a base 20, para cada dígito no número inteiro da base 20, que chamaremos de g, os g mod 5pontos serão impressos e as g//5barras serão impressas. Em seguida, o programa imprime 3 linhas em branco e passa para o próximo dígito. No entanto, se o dígito for 0, um único "pedaço" será impresso, seguido de 3 novas linhas e o programa passará para o próximo dígito. Então, pegando o número da base 20 11B, vamos para o primeiro dígito. O primeiro dígito é 1e, portanto, imprimiria 0 barras desde então 1//5=0e 1 ponto desde então 1%5=1. Então, primeiro obteríamos isso:

 ---- 
|    |
|    |
 ---- 

e depois 3 novas linhas. Passando para o segundo dígito, também vemos que ele é 1, portanto, seria a mesma coisa:

 ---- 
|    |
|    |
 ---- 

e também 3 novas linhas. Finalmente, passando para o último dígito, vemos que é um B. Como B=11na base 20, o programa produziria 1 ponto desde 11%5=1e 2 barras desde 11//5=2. Então agora temos o seguinte:

 ---- 
|    |
|    |
 ---- 
--------------------------------
|                              |
--------------------------------
--------------------------------
|                              |
--------------------------------

Finalmente, juntando tudo isso, obtemos o seguinte:

 ---- 
|    |
|    |
 ---- 




 ---- 
|    |
|    |
 ---- 




 ---- 
|    |
|    |
 ---- 
--------------------------------
|                              |
--------------------------------
--------------------------------
|                              |
--------------------------------

E esse é o numeral maia para 431! Você finalmente tem seu número base 10 representado nos números maias da base 20.

Nota: Você pode ou não ter notado essa lambdafunção no meu código. Independentemente disso, essa função é usada para a criação dos pontos, pois vários pontos devem ser exibidos próximos um do outro.

R. Kap
fonte
Não tenho certeza se é possível, mas você pode fazer em S,N,M,X=' -|\n'vez de S,N,M,X=' ','-','|','\n'?
31416 Adnan
@ Adnan isso é possível.
Rɪᴋᴇʀ
@Adnan Realmente? Uau, eu não sabia disso. Obrigado!
R. Kap
401contém um zero interno.
Neil
@ Neil Oh, certo. Obrigado pelo aviso. Está consertado agora.
R. Kap
3

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)

Discussão

n//20and m(n//20)chama m()recursivamente se houver potências maiores de 20 a serem manipuladas. A recursão é feita antes da impressão do valor atual, para que as potências mais altas sejam impressas primeiro.

Se o valor atual do local for diferente de zero (r! = 0), o for a,b,floop imprime as unidades e depois os cinco. aé a primeira / quarta linha e bé a segunda / terceira linha. O truque está no print(*((a,b,b,a)*f),sep=x). Para as unidades, f = 1 resultando em print(*(a,b,b,a),sep=x), que imprime as 4 linhas que compõem os símbolos das unidades (x é um '\ n'). Para os cinco, f = o número de cinco a imprimir (r // 5), de modo que a tupla (a, b, b, a) é multiplicada (ou seja, repetida) pelo número de cinco a serem impressos. Se f = 2, obtemos print(*(a,b,b,a,a,b,b,a),sep=x), que imprime dois símbolos para cinco.

Se o valor atual do local for 0, o símbolo zero será impresso.

RootTwo
fonte
Eu tive que recompensar a recompensa a R. Kap, mas isso pode merecer sua própria recompensa! Bom trabalho!
Rɪᴋᴇʀ
2

Python, 411 bytes

w,m=input(),[]
for i in[20**i for i in range(int(w**0.25))][::-1]:m.append(w/i);w=w%i
for i in m or[0]:print(lambda x,y='\n',w=' ----  ',z='|    | ':w*(x%5)+y+z*(x%5)+y+z*(x%5)+y+w*(x%5)+y+('-'*32+'\n|'+' '*30+'|\n'+'-'*32+y)*(x/5)if x else''' -------------------
|    |    |    |    |
|    |    |    |    |
|-------------------|
|                   |
|                   |
 ------------------- ''')(i),'\n\n\n'

Eu criei isso para gerar casos de teste, você pode usá-lo como referência. Sorta jogou golfe.

Rɪᴋᴇʀ
fonte
Você poderia tirar 26 bytes através da remoção de espaços em branco, e outros 4 fazendo s=math.sqrte chamando s(s(w))em vez demath.sqrt(math.sqrt(w))
DJMcMayhem
@DrGreenEggsandHamDJ thanks. Acho que não tenho 26 bytes de espaço em branco?
Rɪᴋᴇʀ
Oh, desculpe, contando erro, eu quis dizer 25. Além disso, w**0.25é ainda melhor do que s(s(w)). Embora tenha ficado mais tempo?
DJMcMayhem
@DrGreenEggsandHamDJ sim, de alguma forma perdi a string do shell zero em trânsito do arquivo para a resposta.
Rɪᴋᴇʀ
2

JavaScript (ES6), 254 bytes

f=(n,r=(s,n=19)=>s.repeat(n))=>(n>19?f(n/5>>2)+`


`:``)+(n%5?`${r(s=` ----  `,n%5)}
${t=r(`|    | `,n%5)}
${t}
${s}
`:``)+r(`${s=r(`-`,32)}
|${r(` `,30)}|
${s}
`,n/5&3)+(n%20?``:` ${s=r(`-`)}
${t=r(`|    `,4)}|
${t}|
|${s}|
|${t=r(` `)}|
|${t}|
 ${s}
`)
Neil
fonte
Não consigo fazer isso funcionar? Ele com erros Missing } in template expression. Eu não sei muito js, ​​como posso consertar?
Rɪᴋᴇʀ
@ EᴀsᴛᴇʀʟʏIʀᴋ Meu mal, mudei algum código e colei acidentalmente no lugar errado. Está consertado agora.
29516 Neil
1

Python 3, 213 bytes

Criamos uma versão ainda mais curta usando uma abordagem diferente:

s,v,h,x=' |-\n'
t=s+h*19+s
k=4*s+v
w=v+4*k
y=v+s*19+v
a=' ----  '
b=v+k+s
c=h*32
d=v+s*30+v
m=lambda n:m(n//20)+([n%5*a,n%5*b,n%5*b,n%5*a][:n%5*4]+n%20//5*[c,d,d,c]if n%20else[t,w,w,v+h*19+v,y,y,t])+[x,x]if n else[]

explicação

As primeiras 9 linhas, mais ou menos, constroem seqüências usadas para criar os símbolos

s,v,h,x = ' |-\n'
k = '    |'

    # parts for a unit
a = ' ----  '
b = '|    | '

    # parts for a five
c = '--------------------------------'
d = '|                              |'

    # parts for a zero
t = ' ------------------- '
w = '|    |    |    |    |'
y = '|                   |'

O núcleo da solução é a função recursiva m, que cria uma lista de cadeias, uma cadeia para cada linha na saída. Esquematicamente, mparece com:

m(n//20) + (ones + fives if n%20 else zero) + [x,x] if n else []

m pode ser reescrito como:

def m(n):
  if n:
    ans = m(n//20)                             # process high digits first

    if n%20:                                   # if there is a base-20 digit
      ans += [n%5*a,n%5*b,n%5*b,n%5*a][:n%5*4] # add strings for the 'ones' if any
      ans += n%20//5 * [c, d, d, c]            # add strings for the 'fives' if any

    else:
      ans += [t,w,w,v+h*19+v,y,y,t]            # otherwise, add strings for a `zero`

    ans += [x,x]                               # blank lines between digit groups

  else:
    ans = []                                   # base case

  return ans

A chamada recursiva m(n//20)vem primeiro, para que os dígitos mais significativos sejam feitos primeiro.

[n%5*a,n%5*b,n%5*b,n%5*a]são a string para os símbolos. aé a linha superior de um único símbolo. n%5é o número de um símbolo para esse dígito. Portanto, n%5*aé uma string para a linha superior (e inferior) de uma n%5. Da mesma forma, 'n% 5 * b` é uma string para a segunda (e terceira) linha.

A expressão [:n%5*4]age como um ifpara evitar linhas em branco extras na saída, se não houver nenhuma 'saída'. Não é necessário, mas faz com que a saída pareça melhor.

n%20//5é o número de símbolos para cinco necessários. [c,d,d,c]são as cordas para formar um símbolo para cinco.

[t,w,w,v+h*19+v,y,y,t] são as cordas para fazer o símbolo zero

[x,x] coloca pelo menos três linhas em branco entre grupos de dígitos maias

RootTwo
fonte
Você pode dar uma explicação sobre como isso funciona?
Rɪᴋᴇʀ