APL (158 caracteres, pontuação = 4)
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
Estou usando o Dyalog APL aqui. O número de ciclos pode ser aumentado em um adicionando 0
(0 seguido de um espaço) ao final da expressão e ao final da string (antes '''
). A duração do ciclo é (# 0's) + 1
e a duração da expressão é 150 + 4*(cycle length))
. Supondo que continuemos adicionando zeros para sempre, a pontuação é Limit[(150 + 4*n)/(n - 1), n -> Infinity] = 4
onde n
está a duração do ciclo.
Aqui está um exemplo com duração do ciclo = 6:
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0
0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0
0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0
0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0
0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0
0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0
0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0
0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1
0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0
192 caracteres, pontuação = 2
'''{2≠⍴⍺:¯3⌽(2×1+⍴⍺)⍴(1+⍴⍺)⍴⍺ ⋄ a←⊃2⌷⍺ ⋄ ⍵=0:¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a⋄(-4+⌊10⍟⊃⍺)⌽(2×1+⍴a)⍴(1+⍴a)⍴a}01'''{2≠⍴⍺:¯3⌽(2×1+⍴⍺)⍴(1+⍴⍺)⍴⍺⋄a←⊃2⌷⍺⋄⍵=0:¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a⋄(-4+⌊10⍟⊃⍺)⌽(2×1+⍴a)⍴(1+⍴a)⍴a}01
Dependendo da implementação, um ponto de falha pode ser quando o número inteiro prefixado na sequência for muito grande. Teoricamente, no entanto, podemos adicionar um ciclo adicionando dois caracteres - um 1
no final da string (antes '''
) e um 1
no final de toda a linha.
200 caracteres, pontuação = 1
'''{a←{2=⍴⍵:⊃2⌷⍵⋄⍵}⍺⋄(⍺{⍵=9:⍬⋄⍕1+{2=⍴⍵:10×⊃⍵⋄0}⍺}⍵),(¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a),⍺{⍵=9:(⍕9),⍕⊃⍺⋄⍕⌊⍵÷10}⍵}'''{a←{2=⍴⍵:⊃2⌷⍵⋄⍵}⍺⋄(⍺{⍵=9:⍬⋄⍕1+{2=⍴⍵:10×⊃⍵⋄0}⍺}⍵),(¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a),⍺{⍵=9:(⍕9),⍕⊃⍺⋄⍕⌊⍵÷10}⍵}91
Minha implementação de APL não possui números inteiros de precisão ilimitados por padrão; portanto, o número inteiro é convertido em um número flutuante quando se torna muito grande, causando uma saída incorreta. Portanto, este é o mais exigente, mas teoricamente (à mão ou com um intérprete de APL diferente), ele deve ter uma pontuação de 1. Basta adicionar 1
a ao final da expressão e você obterá outro ciclo.
Visão geral (com uma solução mais curta)
Vou dar uma visão geral da primeira versão, porque acho que é provavelmente a mais fácil de entender. Antes de abordar essa versão, no entanto, consideraremos uma solução simples no APL :
1⌽22⍴11⍴'''1⌽22⍴11⍴'''
Descobri que uma das melhores maneiras de entender algumas expressões de APL é observar a saída em toda a cascata de operadores / funções. Todos os operadores e funções no APL são associativos à direita e têm a mesma precedência, então aqui está, da direita para a esquerda:
'''1⌽22⍴11⍴'''
: Esta é apenas uma string literal (uma lista de caracteres). ''
é a maneira da APL de escapar de aspas simples. Saída: '1⌽22⍴11⍴'
.
11⍴'''1⌽22⍴11⍴'''
: Aqui, remodelamos ( ⍴
) a string para ser de comprimento 11
. Como o comprimento da string é inferior a 11, ele é repetido (ou seja, 5⍴'abc'
renderia 'abcab'
). Saída: '1⌽22⍴11⍴''
. Portanto, agora temos duas aspas no final - estamos chegando a algum lugar!
22⍴11⍴'''1⌽22⍴11⍴'''
: Da mesma forma, agora remodelamos nossa saída anterior para ser longa 22
. Saída: '1⌽22⍴11⍴'''1⌽22⍴11⍴''
. Estamos quase chegando - precisamos apenas mover a primeira citação única para o final.
1⌽22⍴11⍴'''1⌽22⍴11⍴'''
: Aqui, rotacionamos ( ⌽
) a lista de caracteres por 1
. Isso move o primeiro caractere da string para o final. Como outro exemplo, 2⌽'abcdef'
retorna 'cdefab'
. Saída: 1⌽22⍴11⍴'''1⌽22⍴11⍴'''
.
Quine rotativo
Esse quine curto é a base principal do nosso quine rotativo. Agora, com isso em mente, vamos dar uma olhada em nosso quine:
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
{ ... }
define uma função sem nome, que é onde faremos o trabalho. Observe que as funções no APL usam um argumento à direita, denotado por ⍵
, e um argumento opcional à esquerda, denotado por ⍺
(think infix). Queremos alimentar essa função tanto com a nossa cadeia quine quanto com algo que nos ajude a criar um número arbitrário de ciclos. Para facilitar as coisas para nós mesmos (e para quem deseja adicionar ciclos), tornamos a sequência quine o argumento da esquerda. O argumento certo, então, é onde colocamos nossa lista de ciclos. 2 ou mais itens separados por um espaço criam uma lista; portanto, neste exemplo, temos uma lista de 2 elementos composta por a 1
e a 0
.
Podemos ver que a função se parece com a quine de antes. Temos a mesma ...⌽...⍴...⍴...
forma de antes. Então isso é bom - pelo menos entendemos isso! Vamos aprofundar as elipses, começando com tudo após o último ⍴
: ⊃,/(~^/¨⍺=0)/⍺
.
- Como você pode ver, observando o exemplo acima, prefixamos a string com os 0 do lado direito, adicionando uma a cada iteração; mas não nos preocupamos com isso agora. Nós apenas queremos a corda!
- Primeiro, considere o que está entre parênteses. (Eles agrupam como na maioria dos outros idiomas, a propósito.)
⍺=0
retorna uma lista, nesse caso, com a mesma forma que ⍺
, em que cada elemento ⍺
é substituído por a 1
se for igual a 0
e por 0
outro. Isso é realizado recursivamente; portanto, se tivermos uma lista de uma lista de caracteres, os caracteres individuais serão testados em relação a 0 e você receberá uma lista de uma lista de valores binários.
- Portanto, se
⍺
consiste apenas em nossa string, retornamos uma lista de zeros. Caso contrário, nosso argumento esquerdo possui alguns 0's prefixados (por exemplo, 0 0 0 'quinestring'
), portanto, é uma lista que consiste em 0's e outra lista, nossa string. Então nossa saída se parece 1 1 1 <sub-list of zeros>
.
^/¨⍺=0
: Aplicamos a função derivada ^/
, que reduz ( /
) usando a função lógica AND ( ^
), a cada ¨
elemento ( ) de ⍺=0
. Isso é para achatar a sub-lista de zeros, para que possamos considerar a string quine como um valor binário. Considerando o exemplo anterior, a saída seria 1 1 1 0
.
~
: Nós binários NÃO cada um dos valores de antes (por exemplo, retornando 0 0 0 1
).
(~^/¨⍺=0)/⍺
: Para cada elemento em ⍺
, replicamos ( /
) o número de vezes fornecido pelo elemento correspondente no argumento esquerdo. Isso elimina todos os 0s, deixando-nos apenas com nossa string de quine.
⊃,/
é uma documentação necessária para garantir que recebamos de volta uma lista achatada de caracteres, reduzindo o resultado com a função de concatenação ( ,
). Se a entrada já é uma lista achatada (ou seja, o argumento esquerdo da nossa função principal é apenas a string), obtemos uma lista de 1 elemento contendo essa lista. No outro caso, quando temos uma lista que consiste em uma sub-lista para a string, obtemos a mesma coisa de volta (uma lista com uma sub-lista). Em seguida, descompactamos this ( ⊃
), fornecendo apenas o primeiro elemento da lista (ou seja, a sub-lista de caracteres). Isso pode parecer desnecessário, mas, caso contrário, estaríamos tentando remodelar uma lista de 1 elemento!
A seguir, examinamos o comprimento fornecido para a primeira remodelação, entre parênteses:
⍺,⍵
: Concatenamos o argumento correto para o primeiro argumento
⊃,/⍺,⍵
: O mesmo de antes - achatar a lista.
+/0=⊃,/⍺,⍵
: Adicione o número de zeros na lista reduzindo ( /
) usando a +
função de adição ( ).
2×+/0=⊃,/⍺,⍵
: Multiplique esse número por dois.
z←2×+/0=⊃,/⍺,⍵
: Atribua ( ←
) o resultado a uma variável z
,. Para recapitular, z
agora é o dobro do número de zeros encontrado nos argumentos esquerdo e direito.
77+z←2×+/0=⊃,/⍺,⍵
: Em seguida 77
, adicionamos , para os caracteres na sequência quine, ignorando tudo após o espaço a seguir 1
. Como no exemplo inicial de quine, adicionamos 1 ao comprimento da string para obter outra aspas simples.
- A saída dessa remodelação, neste exemplo, é:
'{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 ''
O argumento para a remodelagem a seguir é simples e reflete o quine curto (2 vezes o comprimento da primeira remodelagem). Nossa saída agora é:
'{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 ''
Agora, para a etapa final, onde calculamos quanto girar a sequência de saída:
- Como você pode ver, olhando para a saída anterior, queremos girá-la de volta (uma quantidade negativa) para trazer as 2 cotações finais para o início. Como queremos que um
0
(e outro espaço) também se mova para o início, queremos girar mais três caracteres para trás.
+/+/¨⍺=0
: Adicione o número de zeros no argumento esquerdo . O primeiro (da direita) +/¨
soma a contagem de cada elemento (ou seja, uma sub-lista ou apenas um número inteiro), e o segundo +/
nos fornece a soma dessa lista resultante.
5+2×+/+/¨⍺=0
: Multiplique por dois (para girar os espaços também) e adicione 5 (o resultado que vimos antes).
- Agora, subtraímos o valor anterior do argumento esquerdo
-
para lidar com o caso quando chegamos ao final do nosso ciclo:
(3+z)×^/⍵
: E todos os elementos no argumento certo juntos para ver se chegamos ao fim ( 1
) e multiplicamos por 3+z
.
E nós terminamos!