Quipus é um dispositivo antigo usado pelos incas na era pré-colombiana para registrar números em um sistema posicional de base dez de nós em uma corda, que funciona da seguinte maneira:
Cada aglomerado de nós é um dígito e existem três tipos principais de nós: simples nós de overhand; "nós longos", que consistem em um nó de overhand com uma ou mais voltas adicionais; e figura oito nós.
- Poderes de dez são mostrados pela posição ao longo da corda, e esta posição está alinhada entre as costas sucessivas.
- Os dígitos nas posições de potências 10 e superiores são representados por grupos de nós simples (por exemplo, 40 são quatro nós simples seguidos na posição "dezenas").
- Os dígitos na posição "uns" são representados por nós longos (por exemplo, 4 é um nó com quatro voltas). Devido à maneira como os nós são amarrados, o dígito 1 não pode ser mostrado dessa maneira e é representado nessa posição por um nó de oito dígitos.
- Zero é representado pela ausência de um nó na posição apropriada.
Detalhes
Para esse desafio, cada fio de um quipu representa um único número (embora, como o artigo da Wikipedia declare, você possa representar muitos números em um fio, neste desafio, não o faremos).
Nós
Cada nó será representado por um único caractere ASCII.
.
representa um nó simples:
representa uma volta de um longo nó8
representa um nó de oito|
representa a ausência de um nó e de um delimitador entre os dígitos.
Construindo Quipus
Quipu são construídos seguindo estas regras.
- Os fios passam de cima para baixo em ordem decrescente de posição (como em, o dígito das unidades estará na extremidade inferior de um fio). Os dígitos ao longo de um fio são separados pelo caractere (
|
). - A potência de 10 que um dígito representa é determinada por sua posição ao longo da cadeia, da mesma forma que a potência de 10 de um dígito seria calculada usando seu índice em um número com o nosso sistema de números. Ou seja,
24
com um2
na casa das dezenas e um4
na casa das unidades, será representado por dois nós, um delimitador (|
), depois quatro nós. - Os dígitos na mesma posição estão alinhados na parte inferior do fio. Se um dígito em uma posição tiver menos nós do que outros dígitos de outros números na mesma posição, a ausência desses nós será representada por (
|
). - Nós simples consecutivos (
.
) representam um valor em sua posição. - Cada dígito é representado por pelo menos 1 caractere. Quando um valor de dígitos é 0 para todos os números em um quipu, ele é representado pela ausência de um nó (
|
). - O local das unidades é tratado especialmente. Um no local da unidade é representado por um nó de oito (
8
). Um valor de dois ou mais no local da unidade é representado por nós longos consecutivos (:
). - Quando o dígito das unidades é 0 para todos os números em um quipu, a ausência de um nó não é impressa, mas o delimitador à direita do dígito das dezenas é preservado.
- Não há delimitador após o dígito das unidades.
Regras
- A entrada consistirá em uma lista não vazia de números inteiros não negativos que podem ser recebidos através de qualquer um dos métodos de entrada padrão . Você pode assumir que esses números inteiros são menores ou iguais a
2147483647
ou2^31-1
. Enquanto os casos de teste são delimitados por espaço, seu formato de entrada pode separar as entradas da maneira que for mais conveniente para o seu idioma, seja separado por vírgula, separado por nova linha, em uma matriz e assim por diante. - A saída consiste em um único Quipu construído de acordo com as regras descritas acima. A saída pode ser fornecida através de qualquer um dos métodos de saída padrão .
- Seu código deve ser um programa ou uma função, embora não precise ser uma função nomeada.
- Nós demoramos algum tempo para empatar, para economizar tempo, seu código é o mais curto possível.
Como sempre, se o problema não estiver claro, entre em contato. Boa sorte e bom golfe!
Exemplos
Entrada:
5 3 1 0
Saída:
:|||
:|||
::||
::||
::8|
Entrada:
50 30 10 0
Saída:
.|||
.|||
..||
..||
...|
||||
Entrada:
330
Saída:
.
.
.
|
.
.
.
|
Entrada:
204 1
Saída:
.|
.|
||
||
||
:|
:|
:|
:8
Entrada:
201 0 100 222
Saída:
.||.
.|..
||||
|||.
|||.
||||
|||:
8||:
Entrada:
1073741823 2147483647
Saída:
|.
..
||
|.
||
.|
.|
.|
..
..
..
..
||
|.
|.
|.
|.
..
..
..
||
.|
.|
.|
..
..
..
..
||
|.
|.
|.
|.
..
..
..
..
||
|.
|.
..
||
.|
.|
..
..
..
..
..
..
||
|.
|.
..
..
||
|:
|:
|:
|:
::
::
::
Entrada:
0
Saída:
|
Respostas:
Pitão, 64 bytes
Experimente online!
Como funciona
fonte
8
. De fato, é apenas um8
nó quando o último dígito é 1 (consulte a regra 6). Você está convertendo todos os nós finais e isso não corresponde às especificações. Além disso, seu Try It Online! link tem código diferente do que é postado aqui, aparentementeIlegível ,
31833001 bytesEste foi um desafio divertido para trabalhar, dentro e fora, entre as celebrações de Natal. Obrigado por postar! Jogar golfe foi interessante porque a especificação está cheia de exceções e casos especiais, que exigiam muitas condições. Além disso, embora não tenha sido necessário converter de e para decimal dessa vez, era necessária uma espécie de "max" para determinar o maior número de dígitos em cada número e o maior valor dos dígitos em cada local.
A primeira versão disso era 4844 bytes, apenas para lhe dar uma idéia do quanto eu joguei isso.
O programa espera a entrada como uma lista de números inteiros separados por vírgula . Sem espaços ou novas linhas. Utilizá-los produzirá um comportamento indefinido.
Explicação
Vou mostrar como o programa funciona, mostrando como ele processa a entrada específica
202,100,1
.No começo, construímos alguns valores que precisaremos mais tarde - principalmente os códigos ASCII dos caracteres que serão exibidos.
Como você pode ver,
'8'
e'.'
já está disponível.'|'
, no entanto, é realmente 124, não 14. Usamos um loop while para adicionar o dobro do valor temporário no slot # 1 para obter 124 (que é 14 + 55 × 2, porque o loop while é executado por 56−1 = 55 iterações). Isso economiza alguns bytes porque literais inteiros grandes como 124 são realmente longos. No diagrama a seguir, mostro a localização de todas as variáveis que o programa usa.Em seguida, queremos inserir todos os caracteres e armazená-los na fita, começando na célula # 12 ( p é o ponteiro para isso). Ao mesmo tempo, queremos saber quanto tempo é o número mais longo (quantos dígitos). Para conseguir isso, mantemos um total contínuo em unário indo para a esquerda, começando na célula # -1 (usamos q como ponteiro em execução). Após o primeiro número de entrada (
202
), a fita agora fica assim:Você deve ter notado que os números estão desativados por 4. Bem, quando os inserimos pela primeira vez, eles são seus valores ASCII, então eles estão desativados por 48 e a vírgula é 44. Para cada caractere, copiamos o 46 de
'.'
em ree subtraí-lo com um loop while (que subtrai 45) e depois adicionamos 1. Fazemos isso para que a vírgula (nosso separador) seja 0, para que possamos usar uma condicional para reconhecê-lo.Além disso, você deve ter notado que deixamos a célula nº 11 em 0. Precisamos disso para reconhecer o limite do primeiro número.
O próximo caractere será uma vírgula; portanto, armazenamos um 0 no # 15, mas é claro que desta vez não avançamos q . Em vez disso, colocamos q de volta em 0 e começamos a "substituir" os 1s que já colocamos.
Depois que todos os caracteres restantes são processados, obtemos o seguinte:
Como você pode ver, os 1s escritos por q agora indicam (em unário) o comprimento do número mais longo.
Agora usamos um loop while para mover q para a extrema esquerda e, em seguida, colocamos outro ponteiro lá, que chamarei de r2 . O objetivo de r2 ficará claro mais tarde.
Neste ponto, deixe-me esclarecer a terminologia que usarei ao longo disso.
Agora, de volta à nossa programação regular. O restante do programa é um grande loop que move q para frente até atingir a célula # 0. Cada uma das células ao longo do caminho representa um local, com as localizadas na extrema direita, e q começará no mais significativo. No nosso exemplo, esse é o lugar das centenas.
Prosseguimos incrementando os pontos q da célula em (ou seja, * q ).
Agora estamos no "estágio 2" do lugar das centenas. Nesta etapa, descobriremos qual é o maior dígito entre todos os dígitos na casa das centenas. Utilizamos o mesmo truque de contagem unário para isso, exceto que, desta vez, o ponteiro é chamado reo ponteiro r2 marca sua posição inicial para a qual precisamos redefini-lo toda vez que passamos para o próximo número.
Vamos começar com o primeiro número. Começamos definindo p como 11 (a posição inicial codificada de todos os números). Em seguida, usamos um loop while para encontrar o final do número e configuramos p2 para marcar a posição. Ao mesmo tempo, também definimos q2 como 0:
Não se distraia com o fato de q2 estar apontando para os vars. Não temos um preenchimento de uma célula em branco porque podemos detectar a célula # 0 simplesmente porque é o número zero.
Em seguida, passamos o número atual por decrementing p e Q2 juntos até * p é zero. Em cada local, o valor de * q2 nos diz o que precisamos fazer. 1 significa "não fazer nada", por isso continuamos. Eventualmente, encontramos o 2 na célula # -3. Toda vez que * q2 não é igual a 1, q2 é sempre igual a q .
Como já afirmei, o estágio 2 é "determinar o maior dígito neste local". Então, definimos r como r2 , use um loop while para diminuir * p e mova r para a esquerda e preencha a fita com 1s; em seguida, use outro loop while para mover r de volta para a direita e incrementar * p novamente para restaurar o valor. Lembre-se de que todo loop while é executado por uma iteração a menos do que o valor em que o usamos; por isso, o número de 1s gravados será 3 a mais (em vez de 4 a mais) que o valor do dígito, e o valor final armazenado em * p será 2 a mais. Assim, isso efetivamente diminuiu * p por 2.
Depois disso, definimos p com o valor de p2 e depois fazemos tudo isso novamente. Pela segunda vez, definir q2 a 0, encontrar o final do número, movendo p para a direita, e depois percorrer os dígitos deste número por decrementing p e Q2 em conjunto. Mais uma vez, encontraremos o 2 na célula nº -3 e escreveremos os 1s restantes de * r .
No caso do terceiro número, acabamos não fazendo nada porque não tem um lugar de centenas (portanto, q2 nunca atinge q ), mas tudo bem, porque isso não afeta o cálculo do valor máximo do dígito.
Também definimos a célula * (r - 4) , que marquei com uma seta sem rótulo aqui, como 1 (mesmo que já esteja em 1). Ainda não vou lhe dizer por que, mas talvez você já tenha adivinhado?
O próximo incremento de * q nos leva ao estágio 3, que é "subtrair o dígito máximo de todos os dígitos no local atual". Como antes, redefinimos p para 11 e q2 para 0 e, em seguida, passamos por todos os números, como fizemos no estágio anterior; Só que desta vez, * q = 3 em vez de 2. Toda vez Q2 atende q e p está em um lugar centenas, usamos um loop while para diminuir * p tantas vezes quantas existem 1s no bloco de esquerda da * r2 (5 no nosso exemplo) usando rcomo um ponteiro em execução. Na verdade, nós o decrementamos mais uma vez para que o dígito maior termine em -2, por um motivo que ficará claro mais tarde:
Depois de processarmos todos os números, estamos no final do estágio 3. Aqui, realizamos duas coisas singulares.
Agora você entende que continuamos examinando os números, localizamos o local atual (indicado pelo valor diferente de 1 de * q ) em cada número e fazemos algo dependendo do valor de * q . Vemos que * q é incrementado primeiro para 2 (= calcular o valor máximo do dígito), depois 3 (subtrai o valor máximo do dígito de cada dígito neste local) e depois subtraímos para torná-lo negativo. A partir daí, ele continuará subindo até atingir 1, restaurando assim o valor que significa "não faça nada". Nesse ponto, passamos para o próximo lugar.
Agora, quando * q é negativo, estamos produzindo. * q está exatamente no valor certo, para que possamos produzir o número certo de linhas de caracteres antes que ele atinja 1; se o dígito maior for 2, precisamos gerar 3 linhas. Vamos ver o que acontece em cada valor de * q :
'.'
(ponto) ou um':'
(dois pontos). Decidimos qual, olhando para q : se for -1, estamos no mesmo local, então produza a':'
(que calculamos como'8'
+2), caso contrário a'.'
.'|'
(canal) e depois incrementamos o valor. Dessa forma, ele alcançará -2 no lugar certo e, em seguida, produzimos'.'
s /':'
s para o restante desse dígito.'|'
(mas apenas se out for diferente de zero, porque, caso contrário, ainda estamos no estágio 2 ou 3).'.'
(e o terceiro gera a'|'
como antes).'|'
s, independentemente de * p ". Dessa forma, obtemos o preenchimento entre os dígitos.Agora incrementamos q para passar para o próximo lugar, as dezenas colocam e incrementamos * q lá. No início do estágio 2, a fita fica assim:
Em seguida, realizamos o estágio 2 como antes. Lembre-se de que isso efetivamente subtrai 2 de cada dígito neste local e também deixa um número unário à esquerda de * r2 indicando o dígito máximo. Deixamos o número unário anterior em paz e continuamos estendendo a fita para a esquerda; custaria apenas um código extra desnecessário para "limpar". Quando terminamos e incrementamos * q , no início do Estágio 3, a fita está agora:
Na verdade, isso é uma mentira. Lembra-se anteriormente de onde eu disse que definimos * (r - 4) como 1 e não lhe disse por quê? Agora eu vou te dizer o porquê. É para casos como este, em que o maior dígito é de fato 0, significando que todos os dígitos neste local são 0. A configuração * (r - 4) , indicada pela seta não identificada acima, para 1 aumenta o número unário em 1, mas apenas neste caso especial. Dessa forma, fingimos que o maior dígito era 1, o que significa que produziremos uma linha extra.
Após o estágio 3 (subtrair o dígito máximo de todos os dígitos no local atual), incluindo a etapa extra que torna * q negativo, a fita fica assim. Da última vez, o dígito maior foi representado por -2 no bloco * p , mas desta vez são todos -3, porque na verdade são todos zeros, mas estamos fingindo como se o dígito máximo fosse 1.
Agora vamos ver o que acontece à medida que * q avança em direção a 1:
'|'
incrementamos.'|'
porque é isso que sempre fazemos quando * q = 0, independentemente de * p .Assim, temos duas linhas de tubos.
Por fim, movemos * q para o local da pessoa. Este se torna interessante porque precisamos produzir
':'
s se o dígito real for qualquer coisa menos 1, mas um'8'
se for 1. Vamos ver como o programa prossegue. Primeiro, incrementamos * q para iniciar o estágio 2:Após o estágio 2 ("calcular o valor máximo de dígitos"), ficamos com isso:
Após o estágio 3 ("subtraia o valor máximo de todos os dígitos no local atual"), a fita ficará assim:
Agora vamos analisar cada iteração de * q por sua vez:
':'
(em vez de a'.'
porque q = -1).'|'
e aumente.'|'
. No entanto, desta vez, em vez de incrementar, um caso especial é acionado. Somente se estivermos produzindo o último lugar ( q = −1) e estivermos na segunda última linha para isso ( * q = −2), e o dígito for realmente um 1 ( * p = −3) , em vez de incrementá-lo para -2, configuramos para -1. Em outras palavras, usamos -1 como um valor especial para indicar que na próxima iteração, precisaremos produzir em'8'
vez de':'
.':'
.'|'
. A condição especial não é acionada porque * q não é mais -2. Portanto, incremente.'8'
.'|'
s aqui, mas no caso especial em que estamos no local ( q = -1), ignoramos isso.Depois disso, q é incrementado para 0 e o loop while grande termina.
Agora você sabe como uma entrada
202,100,1
funciona. No entanto, há mais um caso especial que ainda não abordamos. Você deve se lembrar que enquanto processávamos o último local, quando * p estava -3, o definimos como -1 para1
(em vez de aumentá-lo para -2), para que a próxima iteração produza uma'8'
alternativa. Isso funciona apenas porque temos uma iteração na qual * p é -3 e tomamos a decisão de incrementá-lo ou configurá-lo para -1. Nós não têm tal uma iteração se todos os dígitos no local queridos são 0 ou 1. Em tal caso, todos os * p valores para os 1s seria começam a -2; não há oportunidade de decidir configurá-lo para -1em vez de incrementá-lo de -3 . Por esse motivo, existe outra condição de revestimento especial dentro do Estágio 3 ("subtraia o dígito máximo de cada dígito no local atual"). Afirmei que, depois de subtrair o valor máximo do dígito de cada dígito (nesse ponto, o dígito máximo está em -1), apenas o diminuímos mais uma vez, mas, na verdade, existe uma condição que é a seguinte:Se o dígito que estamos vendo for igual ao dígito máximo nesse local ( * p = -1), e esse local for o local ( q = -1), e o dígito máximo for 1 ( * (r + 5) = 0, ou seja, o bloco unário à esquerda tem apenas 5 células); somente então deixamos * p em -1 para indicar que a única iteração da saída deve gerar an
'8'
. Em todos os outros casos, diminuímos novamente.Feito. Feliz Ano Novo!
Edição 1 (3183 → 3001): Golfe de feliz ano novo! Consegui me livrar completamente das variáveis p2 e r2 ! p agora corre para frente e para trás para encontrar o início e o fim dos números, mas parece ter um código mais curto. Tentei me livrar do q2 também, mas não consegui diminuir o código dessa maneira.
Também encontrei mais alguns lugares onde eu poderia aplicar truques típicos de golfe ilegíveis, como reutilizar o último valor de um loop while. Para dar um exemplo, em vez de
Eu posso salvar o
'""""
(faça o primeiro, depois o segundo) e o'"""
(constante 1) escrevendo-o de uma maneira que é comoObviamente, isso só funciona se eu souber que o loop while será executado por pelo menos uma iteração, mas se o fizer, seu valor de retorno será pd, para que eu possa usá-lo como condição para o if.
fonte
Javascript (ES6)
750744690604498346245234 bytesEu sou novo no PPCG e achei que poderia tentar este, pensando que era bastante simples. Cara, eu estava errado !! Estou trabalhando nisso há um tempo e tenho muito golfe para fazer ... As
sugestões são incentivadas! - embora entender isso não seja uma tarefa fácil.
Emite cordas quando a entrada é uma matriz de números (por exemplo
[204, 1]
:).Explicação
Exemplo
Entrada: Matriz de números:
[4,8,15,16,23,42]
Saída:
fonte
Python 3,
624598595574561535532527525426345328324294288286283280267265255251245238235234230228 bytesBem, como essa pergunta precisava de uma resposta, forneci uma aqui, em que a entrada deve ser uma sequência de números separada por espaço, como
"204 1"
. Rapaz, é longo. Quaisquer sugestões de golfe (ou melhores respostas) são bem-vindas.Editar: bytes salvos misturando guias e espaços.
Editar: salvei muitos bytes alterando a forma como obtive os dígitos de um número (faça uma lista com a string preenchida com zero do número e, em seguida, no corpo do código, transponha para obter centenas, dez dígitos, etc. .)
Edit: E eu salvei um pouco mais, incorporando esse último
:8
loop no loop principal do quipu.Agora, se eu pudesse descobrir porDescobri e a solução leva muitos bytes. (Também a contagem de bytes caiu porque, de alguma forma, as guias se transformaram em quatro espaços. Provavelmente era a formatação do bloco de código neste site)b=d[j*v+i]==m(d[i::v])
que não funcionaria.Edit: Eu reorganizei como fez o quipus. Agora, ele cria um fio de cada vez e depois transpõe para impressão.
Edit: Transformei minha resposta novamente em um programa Python 3 para economizar mais alguns bytes.
Edit: Encontrei um bug no meu código que o fazia de modo que não estava imprimindo zeros no meio dos números corretamente (veja o caso de teste
204 1
acima). Ao consertar isso, eu consegui jogar golfe :)Editar: Alterei a impressão para salvar 10 bytes. E eu coloquei todas as antigas contagens de bytes, apenas porque.
Edit: Golfed a atribuição de
v
usarmap
para quatro bytes. Os meus agradecimentos a CarpetPython , pois recebi a ideia da resposta deles aqui .Edit: Transformado o meio "para loop dentro de um loop for", em apenas um loop for por seis bytes.
Edit: Agora usando
enumerate
. Não está mais usandol=len(z)
. Transformado o ternárioif-else
em uma lista ternária. Veja abaixo os detalhes.Editar: o Sp3000 sugeriu uma edição
print
e uma edição na condição ternária que salvou um byte cada.Ungolfed:
fonte
0
, como0 12 4
.for r in zip(*x):print(''.join(r))
->print(''.join(r)for r in zip(*x))
C,
238235 bytesConfiando fortemente no pré-processador C para tornar o código o mais curto possível. Como efeito colateral, também o torna praticamente ilegível.
No Ubuntu 14.04, você pode compilar o código de maneira simples
gcc quipu.c
(ignore os avisos). Um exemplo de execução do executável:Testado em todos os casos de teste do OP.
Código fonte ungolfed:
fonte
Mathematica
436453357352347 bytesO de cima
IntegerDigits
; preenche cada número com zeros à esquerda (para garantir espaçamento igual); cada número de entrada, agora decomposto em dígitos, corresponde a uma linha de uma matriz; cada coluna representa um valor de local. Matriz é transposta.Exemplo
fonte
Transpose@Join
? Isso deve ser, certo?R -
446444Vejo que ainda não existe uma solução R, então aqui está uma. A função pega um vetor com números inteiros.
Ungolfed
fonte
if(v>0)
de suaif(i<r)
cláusula? R aceita um intervalo comoz+1:z
quandov==0
? Se assimq[z+1:z,j]
não seria afetado, eu pensaria. Além disso, R tem umaelse
palavra - chave e algum tipo deelse if
palavra-chave? Nesse caso, você poderá jogar golfe alguns desses condicionais.if(v>0)
é necessário porquev=0
, se o índice estiver fora dos limites (ou seja, tentar obter a linha nrow + 1). R temelse
, e eu realmente tentei sua sugestão e usei sempreelse
que possível, mas acabou sendo o mesmo número de bytes.