Esse desafio é assustadoramente adequado para ilegível.
A primeira versão disso era 3379 bytes, apenas para lhe dar uma idéia do quanto eu joguei isso.
O programa aceita a entrada exatamente como descrito no desafio: uma lista de palavras separadas por espaço (que também podem conter dígitos e sinais de pontuação), seguida por um espaço e um número inteiro que é pelo menos 4 (números mais baixos geram loops infinitos) .
'"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "'" "" ""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" ""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "'" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" '""' "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""'""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "" ""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" ""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "'" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "'" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" ""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" '' '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ '' '"'" '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "'"' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "
Explicação
Vou mostrar como o programa processa a entrada thyme horseradish peppermint 10
. A saída esperada é thyme,\nhorser...,\npeppermint
.
Primeiro, começamos na célula 7 e lemos toda a entrada, mas subtraímos 32 de cada caractere para que os espaços se tornem zeros.
Por razões óbvias, isso deixa o ponteiro em execução (chamado p aqui, armazenado na célula # 0) no final. Usamos um loop while para encontrar a última lacuna, que é o começo do número que define a largura da saída (célula nº 36 neste exemplo).
Agora queremos decodificar o número (ou seja, converter de decimal). O resultado final será nas células t e r . Contamos com o fato de que eles começam do zero.
Para cada dígito no número, faça o seguinte:
- Defina t para -15.
- Em um loop while, decrement r (que contém o resultado até agora) para 1 (porque precisamos exatamente r iterações, mas desde que o decréscimo acontece antes de ser verificado que a condição de loop while, diminuindo a 0 daria um menor número de iterações) e para cada iteração, adicione 10 a t . Agora t contém 10 vezes o resultado anterior menos 15.
- Novamente em um loop while, diminua * p para 0 e, para cada iteração, adicione 1 a t . Depois que t contém o resultado intermediário correto até o momento: os caracteres
'0'
com '9'
códigos ASCII 48–57; portanto, após a subtração anterior de 32, eles são 16–25; portanto, adicionamos 15–24 a t , o que cancela com −15. nós configuramos para mais cedo. Também é importante que isso zere as células que costumavam conter os caracteres de dígito para que o código subseqüente possa reconhecer o final da lista de palavras.
- Defina r para o novo resultado intermediário para que a próxima iteração o encontre em r . (Observe que não precisamos ler de t novamente, podemos apenas usar o último valor do loop while anterior, porque sabemos que * p não pode ser zero, portanto, ele foi executado pelo menos uma vez.)
Finalmente, usamos outro loop while simples (diminuindo t como o contador) para converter o número que acabamos de calcular em unário. Armazenamos uma sequência de 1s indo para a esquerda a partir da célula # 0. Isso se baseia no fato de que a célula nº 1, nosso ponteiro em execução para este ( q ), começa em 0. Temos um 1s a menos porque os loops em Ilegível são assim:
Depois disso, não precisamos mais do valor em r , então reutilizamos essa célula para outra coisa. Nós redefinir a ponteiros p e q e inicializar algumas células com códigos ASCII de caracteres que precisamos mais tarde. Eu também rotulei c e s, que usaremos mais tarde, e confiaremos no fato de que s começa em zero:
Ei, espera um pouco. Por que a célula # 0 está vermelha? ... Bem, isso é para destacar um truque sorrateiro. Lembre-se de que produzimos um 1 a menos? O truque é que usamos a célula # 0 como uma "extensão" para corrigir isso. Isso funciona porque sabemos que p nunca será 0. Dessa forma, o bloco vermelho agora tem 10 células de largura, exatamente o número que queremos. Ele também salva 9 caracteres para poder inicializar q para 1 em vez de 0.
Agora, entramos no loop while, que percorre as palavras e gera todas elas.
Etapa 1: descubra se a próxima palavra se encaixará na linha atual. Para fazer isso, basta mover p para a direita eq para a esquerda com um loop while até que p atinja a próxima lacuna:
Agora que p está à direita da palavra, podemos verificar se esta é a última palavra da lista, verificando se * (p + 1) é zero. Também armazenamos esse valor (que em nosso exemplo é 72 porque é o "h" de "rábano silvestre" menos 32) em c porque precisamos dele novamente mais tarde. Nesse caso, não é zero; portanto, precisamos gerar uma vírgula junto com a palavra, para que a palavra tenha um caractere a mais. Considere isso diminuindo q mais uma vez. Por fim, use outro loop while para retornar p ao início da palavra.
Agora sabemos que a palavra se encaixará na linha atual porque q está apontando para um valor diferente de zero, então tudo o que precisamos fazer é:
- Mover p a frente através da palavra de novo, imprimindo cada personagem (mais de 32, porque todos os códigos ASCII são desativados por 32).
- Se c for diferente de zero, imprima uma vírgula (usando o valor na célula nº 5).
- Defina s como um valor diferente de zero para indicar para a próxima iteração que não estamos mais no início de uma linha e, portanto, precisamos gerar um caractere de espaço antes da próxima palavra. (Reutilizamos o valor de retorno da declaração de impressão acima para isso, que é 44 para a vírgula.)
Saída até agora: thyme,
Em seguida, a próxima iteração do grande loop é iniciada. Como antes, verificamos se a próxima palavra se encaixa no restante da linha, diminuindo q à medida que passamos pela palavra da esquerda para a direita. Observe que q ainda é –5 da iteração anterior, mantendo o controle de quantos caracteres já imprimimos na linha atual. Depois de contar os caracteres em "rábano", mais um para a vírgula, mais um porque s é diferente de zero, indicando que também precisamos gerar um espaço, q terá ultrapassado o final do bloco de 1s:
Agora q aponta para uma célula zero, o que significa que o "rábano silvestre" não se ajustará à linha atual. O que fazemos agora depende se s é diferente de zero. No nosso caso, é o que significa que precisamos avançar para a próxima linha. Tudo o que precisamos fazer é:
- Imprimir uma nova linha (usando a célula nº 3)
- Defina q de volta para 1
- Defina s como 0
Saída até agora: thyme,\n
Para a próxima iteração, p está no mesmo lugar que antes, portanto, veremos a mesma palavra novamente. Como antes, contamos os caracteres em "raiz-forte", definimos c como 80 novamente quando notamos que há outra palavra após esta, diminui q para a vírgula e retrocede p de volta ao início da palavra:
Como na iteração anterior, descobrimos que "raiz forte" ainda não se encaixa porque q acaba em uma célula que é zero. No entanto, desta vez s é zero, o que significa que fazemos algo diferente da última vez. Precisamos produzir parte da palavra, três pontos e uma vírgula. Nossa largura é 10, portanto, precisamos gerar 6 caracteres da palavra. Vamos ver onde terminamos se:
- Encontre o início do bloco vermelho de 1s. Podemos fazer isso indo para a direita, porque sabemos que q deve ser deixado dela.
- Incremente q mais uma vez se também precisarmos gerar uma vírgula ( c ≠ 0).
A fita agora fica assim:
Eu marquei um espaço de 6 células aqui. Como você pode ver, precisamos gerar caracteres até q = -1. Isso é muito eficiente em termos de código para verificar (basicamente while ((++q)+1) { ... }
). Então:
- Imprima esses caracteres (mais 32, porque todos os códigos ASCII estão desativados em 32) até q atingir -1. p estará então na célula 19, no meio da palavra "rábano".
- Imprima três pontos. Como o comando print retorna seu próprio argumento, podemos aninhar com eficiência o código (essencialmente
print(print(print('.')))
). Pegamos o valor ASCII da célula nº 5 e adicionamos 2 para obter o código ASCII do ponto.
- Mova p para o final da palavra. Como sabemos que ainda não podemos chegar ao final da palavra (porque a palavra era muito longa e tivemos que remover pelo menos três caracteres para ajustar os pontos), esse loop definitivamente tem pelo menos uma iteração, portanto seu código é mais curto para que o corpo do loop while calcule o valor ASCII do ponto e depois passe o valor de retorno do loop while para as funções de impressão.
- Imprima uma vírgula se c for diferente de zero.
Depois de tudo isso, também imprimimos uma nova linha (usando a célula nº 3) e configuramos q de volta para 1. Também podemos definir s como 0, mesmo que já seja 0, o que torna o mesmo que fizemos anteriormente quando envolvemos o arquivo próxima linha (quando s é diferente de zero), para evitar repetir o código, fazemos isso após o condicional que verifica s .
Saída até agora: thyme,\nhorser...,\n
Há apenas uma iteração restante. Desta vez, depois de contar as letras da palavra, obtemos o seguinte:
Desta vez, como não há nada após p , definimos c como 0 para indicar “sem vírgula” e, portanto, não diminuímos q mais uma vez. Como q agora aponta para uma célula diferente de zero, sabemos que a palavra se ajustará; portanto, o mesmo código é executado como na primeira iteração, exceto que, desta vez, c é zero e, portanto, simplesmente não imprime a vírgula.
Resultado: thyme,\nhorser...,\npeppermint
Nesta explicação passo a passo, não incluí um caso em que o código realmente imprimiria um espaço, mas acho que deveria estar bem claro agora. Se o código achar que a palavra se encaixa ( * q ≠ 0) e s é diferente de zero, ele simplesmente produzirá um espaço antes da palavra.