Números ASCII Maya

21

Escreva um programa ou função que, dado um número inteiro positivo como entrada, produza a representação desse número inteiro em números maias .

Números maias

Os números maias são um sistema vigesimal (base 20) usando apenas três símbolos:

  • < >para zero (o símbolo correto é algum tipo de shell que não pode ser facilmente representado usando ASCII).
  • .para um
  • ----para cinco

Os números são escritos verticalmente em potências de 20, e os números entre 0 e 19 são escritas como pilhas de cincos e aqueles . Você deve consultar o artigo da Wikipedia para obter mais detalhes.

Como exemplo, aqui estão os números entre 0 e 25, separados por vírgulas:

                                                                                 .    ..  ...  ....
                                                        .    ..  ...  .... ---- ---- ---- ---- ----  .    .    .    .    .    .
                               .    ..  ...  .... ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
<  >, .  , .. ,... ,....,----,----,----,----,----,----,----,----,----,----,----,----,----,----,----,<  >, .  , .. ,... ,....,----

Entradas

  • As entradas sempre são números inteiros positivos entre 0 e 2147483647 (2 ^ 31 - 1).
  • Você pode pegar a entrada do STDIN, como um argumento de linha de comando, parâmetro de função ou qualquer coisa semelhante.

Saídas

  • Cada linha tem no máximo 4 caracteres. < >e ----sempre deve ser impresso como indicado aqui (4 caracteres cada).
  • Uns ( .) devem estar centralizados na linha. Se houver 1 ou 3 ., como o alinhamento horizontal perfeito é impossível, não importa se são uma coluna à esquerda ou uma coluna à direita ou ao centro.
  • Deve haver exatamente uma linha vazia entre diferentes potências de 20, independentemente da altura das pilhas na potência de 20s. Por exemplo, a saída correta para 25 e 30 é:

            .
     .
           ----
    ----   ----
    
  • Não são permitidas linhas iniciais ou finais.

  • As saídas devem ser impressas exatamente como estão nos exemplos fornecidos.

Casos de teste

  • Cada número individual entre 0 e 25 é dado como exemplo acima.

  • Entrada: 42

Saída:

 .. 

 .. 
  • Entrada: 8000

Saída:

 .  

<  >

<  >

<  >
  • Entrada: 8080

Saída:

 .  

<  >

....

<  >
  • entrada: 123456789

Saída:

 .  

... 
----
----
----

 .  
----
----

 .. 
----
----

 .  

....
----
----
----

....
----
  • Entrada: 31415

Saída:

... 

... 
----
----
----

----
----

----
----
----
  • Entrada: 2147483647

Saída:

 .  

... 
----
----

 .  
----
----

 .  

----
----
----

....
----

 .. 

 .. 
----

Pontuação

Isso é , então o código mais curto em bytes vence.

Fatalizar
fonte
15 e 20 parecem ser idênticos.
Isaacg
@isaacg Obrigado, na verdade, eu tinha 15 aparecendo no lugar certo e também entre 19 e 20. Fixo.
Fatalize 4/08/15
@Fatalize A saída precisa ser impressa (ou seja, STDOUT) ou minha função pode retornar a saída?
precisa saber é o seguinte
@ rink.attendant.6 Deve ser impresso exatamente como está no post.
Fatalize 4/08/15
Tudo bem se 1 for uma coluna à direita, mas 3 for uma coluna à esquerda?
Aragaer # 6/15

Respostas:

3

Pitão, 41 bytes

j+bbm|jb_m.[\ 4kc:*d\.*5\.*4\-4"<  >"jQ20

Experimente online: Demonstração

Explicação:

                                     jQ20   convert input to base 20
    m                                       map each value d to:
                  *d\.                         string of d points
                 :    *5\.*4\-                 replace 5 points by 4 -s
                c             4                split into groups of 4
         m.[\ 4k                               center each group
        _                                      invert order
      jb                                       join by newlines
     |                         "<  >"          or if 0 use "<  >"
j+bb                                        join by double newlines
Jakube
fonte
5

Perl, 125 117 bytes

$-=<>;{$_=($-%20?(""," .
"," ..
","...
","....
")[$-%5]."----
"x($-/5&3):"<  >
").$_;($-/=20)&&($_=$/.$_,redo)}print

Agradeço a Dom Hastings por me ajudar a economizar 8 bytes.

samgak
fonte
11
Olá samgak, mais algumas alterações de economia de bytes, em vez de redo,if(int($i/=20))você poder usar ~~($i/=20)&&redo. ~~converte para int - você também pode usar 0|no início (ou |0no final). Também substituir substr(".... ... .. . ",20-$i%5*5,5)por (' .', ' ..','...','.'x4)[$i%5-1].$/parece funcionar bem, mas eu não testei todos os casos de teste ... Se esses funcionarem, você está com 114 ... Se eu pensar em mais alguma coisa para compartilhar, avisarei!
Dom Hastings
11
Pensando nisso, se você quiser apenas ter um número inteiro e ignorar o restante, pode usar a variável mágica $-que sempre truncará para um int ... pode economizar um pouco mais!
Dom Hastings
11
@DomHastings obrigado, o truque de conversão int economiza alguns bytes, e se livrar do substr economiza outro 4. As novas linhas precisam entrar nas constantes da cadeia de caracteres, porque não deve haver nenhuma nova linha no caso em que não há pontos.
Samgak 5/08/15
11
@DomHastings de fato, obrigado novamente! Acho que isso significa que eu tenho que me livrar do meu final da piada mundo
samgak
4

JavaScript ES6, 143 bytes

Cargas de bytes adicionadas, porque precisam console.log, poderiam salvar outros 23 bytes sem ela.

n=>console.log((d=(x,s='',l=1,j=x/l|0)=>s+(j>19?d(x,s,l*20)+`

`:'')+((j=j%20)?(' '+`.`.repeat(j%5)).slice(-4)+`
----`.repeat(j/5):'<  >'))(n))
George Reith
fonte
4

Mathematica 185 182 171 153

Com 18 bytes salvos, graças à sugestão de Arcinde de usar funções anônimas,

c=Column;c[If[#>0,{q,r}=#~QuotientRemainder~5;c@{{""," ."," .."," ...","...."}[[r+1]],c@{{""},{d="----"},{d,d},{d,d,d}}[[q+1]]},"< >"]&/@#~IntegerDigits~20]&

Exemplo

c[If[# > 0, {q, r} = #~QuotientRemainder~5; c@{{"", " .", " ..", " ...", "...."}[[r + 1]], c@{{""}, {d = "----"}, {d, d}, {d, d, d}}[[q + 1]]}, "< >"] & /@ #~IntegerDigits~20] &[31415]

saída


Verificando

O número decimal, 31415, expresso na base 20. O Mathematica emprega letras minúsculas para isso.

BaseForm[31415, 20]

base 20


Os dígitos decimais correspondentes ao número da base 20 acima.

IntegerDigits[31415,20]

{3, 18, 10, 15}


Outro exemplo

IntegerDigits[2147483607, 20]

{1, 13, 11, 1, 15, 9, 0, 7}

c[If[# > 0, {q, r} = #~QuotientRemainder~5;c@{{"", " .", " ..", " ...","...."}[[r + 1]], c@{{""}, {d = "----"}, {d, d}, {d, d, d}}[[q + 1]]},"< >"] & /@ #~IntegerDigits~20] &[2147483607]

ex2

DavidC
fonte
c=Column;c[If[#>0,{q,r}=#~QuotientRemainder~5;c@{{""," ."," .."," ...","...."}[[r+1]],c@{{""},{d="----"},{d,d},{d,d,d}}[[q+1]]},"< >"]&/@#~IntegerDigits~20]&usando funções anônimas.
jcai
@ Arcinde, Obrigado. Boas funções anônimas antigas.
DavidC
3

JavaScript (ES6), 157 bytes

As novas linhas são significativas e são contadas como 1 byte cada. Como a impressão em STDOUT é necessária, console.logme custam alguns bytes lá.

f=i=>console.log([...i.toString(20)].map(j=>(!(j=parseInt(j,20))||j%5?[`<  >`,` .`,` ..`,`...`,`....`][j%5]+`
`:'')+`----
`.repeat(j/5)).join`
`.slice(0,-1))

Demo

Para fins de demonstração, escreverei uma versão ES5 para que funcione em todos os navegadores:

// Snippet stuff
console.log = function(x) {
  O.innerHTML = x;
}
document.getElementById('I').addEventListener('change', function() {
  f(this.valueAsNumber);
}, false);

// Actual function
f = function(i) {
  console.log(i.toString(20).split('').map(function(j) {
    return (! (j = parseInt(j, 20)) || j % 5 ? ['<  >', ' .', ' ..', '...', '....'][j % 5] + '\n' : '') + '----\n'.repeat(j / 5);
  }).join('\n').slice(0,-1));
}
<input type=number min=0 max=2147483647 value=0 id=I>

<pre><output id=O></output></pre>

rink.attendant.6
fonte
O último .joinprecisa de parênteses?
Downgoat
137 bytes: pastebin.com/3Zgg4qtX
Downgoat
@vihan Isso não produz nada, apenas retorna.
precisa saber é o seguinte
não sabia que era um requisito, pois a entrada pode ser por meio de uma função. pastebin.com/0pS0XtJa é de 3 bytes mais curto
Downgoat
2

Python 2.x, 142 bytes:

def m(n):
 h=[[""," "*(2-n%5/2)+"."*(n%5)+"\n"][n%5!=0]+"----\n"*(n%20/5),"<  >\n"][n%20==0]
 n/=20
 if n>0:
  h=m(n)+"\n\n"+h
 return h[:-1]

Exemplo:

>>> print m(2012)
----

<  >

 ..
----
----
>>> 

Editar: linha à direita ...

Locoluis
fonte
Eu tenho algumas melhorias para sugerir. Primeiro, mude [n%20==0]para [n%20<1]. Segundo, mude [[""," "*(2-n%5/2)+"."*(n%5)+"\n"][n%5!=0]para h=[(" "*(2-a/2)+"."*a+"\n")*(a>0)+"----\n"*(n%20/5),"< >\n"][n%20<1]with a=n%5, que move todos os n%5s para fora, e altera o condicional ao *(a>0)qual retorna uma string vazia a==0para o mesmo efeito.
Sherlock9
Finalmente, colocar a, he, nem uma linha, assim: a=n%5;h=[(" "*(2-a/2)+"."*a+"\n")*(a>0)+"----\n"*(n%20/5),"< >\n"][n%20<1];n/=20. Tudo isso deve deixar você com 131 bytes.
Sherlock9
2

CJam, 82 76 bytes

li{_K%[""" .
"" ..
""...
""....
"]1$5%='-4*N+2$5/3&*+"<  >
"?N+L+:L;K/}h;L);

Meu primeiro programa CJam, basicamente apenas uma transliteração da minha resposta Perl para o CJam.

Experimente on-line

Multilinhas com comentários:

li            # read input
{             # start of do-while loop
  _K%         # check if this base-20 digit is a zero
    [""" .
    "" ..
    ""...
    ""....
    "]1$5%=   # push dots for 1s onto stack
    '-4*N+2$5/3&*+    # push lines for 5s onto stack

    "<  >
    "         # push zero on stack
  ?           # ternary if test (for digit equals zero)
  N+L+:L;     # pre-concatenate string with output plus newline
  K/          # divide by 20
}h            # end of do while loop
;L);          # push output string on stack, chop off trailing newline
samgak
fonte
1

PHP, 220 bytes

A mesma abordagem da minha resposta JavaScript. O PHP possui funções embutidas para tudo.

Recebe 1 entrada da linha de comando (ou seja, STDIN), como visto em $argv[1]:

<?=rtrim(implode("\n",array_map(function($j){return(!($j=base_convert($j,20,10))||$j%5?['<  >', ' .', ' ..', '...', '....'][$j%5]."\n":'').str_repeat("----\n",$j/5);},str_split(base_convert($argv[1],10,20)))));
rink.attendant.6
fonte
1

C - 149

f(v){v/20&&(f(v/20),puts("\n"));if(v%=20)for(v%5&&printf("%3s%s","...."+4-v%5,v/5?"\n":""),v/=5;v--;v&&puts(""))printf("----");else printf("<  >");}

Usa recursão para imprimir os números mais significativos primeiro. Em seguida, imprime zero ou imprime todos os pontos com um inteligente printf e todos os cinco em um loop. Não tenho certeza se posso evitar o uso de if-else aqui.

A desvantagem do printf inteligente é que 1 e 3 não estão alinhados um ao outro:

O resultado para 23 é:

  .

...

119 solução incorreta - nova linha final

f(v){v/20&&(f(v/20),puts(""));if(v%=20)for(v%5&&printf("%3s\n","...."+4-v%5),v/=5;v--;)puts("----");else puts("<  >");}
aragaer
fonte
146 bytes .
Jonathan Frech
1

PHP, 202 192 bytes

function m($n){return(($c=($n-($r=$n%20))/20)?m($c)."\n":"").
($r?(($q=$r%5)?substr(" .   .. ... ....",$q*4-4,4)."\n":"").
str_repeat("----\n",($r-$q)/5):"<  >\n");}
echo rtrim(m($argv[1]),"\n");

Ele obtém a entrada do primeiro argumento da linha de comando.

O código fonte completo, com comentários e testes, está disponível no github .

axiac
fonte
\ntem dois caracteres - mas uma nova linha no meio de uma sequência é apenas um.
fisharebest
1

Python 2, 114 bytes

Esta resposta é baseada nas respostas Pyth de Jakube e Python 2 de Locoluis.

def f(n):d,m=divmod(n%20,5);h=[" "*(2-m/2)+"."*m+"\n----"*d,"<  >"][n%20<1];n/=20;return(f(n)+"\n\n"if n else"")+h
Sherlock9
fonte
0

Geléia , 50 49 47 bytes

b5µṪ”.x⁶;$L<3Ɗ¡ṭ⁾--;UW¤ẋ$Ẏ$L¡Ṛø“<  >”WµẸ?
b20Ç€

Experimente online!

... agora fica alinhado graças ao ponto de user202729.

Quando você se engana, o pensamento < >é um palíndromo ...

dylnan
fonte
Por que você alinhar à direita ......
user202729
@ user202729 Para .e ..precisa haver um espaço, então eu também o coloquei .... Existe um caminho mais curto?
dylnan
Penso que, de acordo com o desafio, as especificações ...não devem estar alinhadas à direita. Apenas mudar <4para <3?
usar o seguinte comando
@ user202729 Você está certo, acho que interpretei errado as especificações. Eu não acho que especifique para ... mas eu posso alterá-lo para <2
dylnan