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) + 1e 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] = 4onde nestá 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 1no final da string (antes ''') e um 1no 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 1a 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 1e 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.)
⍺=0retorna uma lista, nesse caso, com a mesma forma que ⍺, em que cada elemento ⍺é substituído por a 1se for igual a 0e por 0outro. 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, zagora é 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!