A sequência Collatz iniciando com um número inteiro positivo n é definida desta maneira:
- se n for par, então divida-o por 2 (
n' = n / 2
) - se n for ímpar, multiplique-o por 3 e adicione 1 (
n' = 3n + 1
)
Repita a iteração acima até n atingir 1.
Não se sabe (é um grande problema não resolvido na teoria dos números) se a sequência eventualmente alcançará o número 1, independentemente do número inteiro positivo escolhido inicialmente.
Uma máquina de dois contadores (2CM) é uma máquina equipada com dois registradores que podem conter um valor inteiro não negativo e podem ser programados com o seguinte conjunto de instruções:
INCX increase the value of register X
INCY increase the value of register Y
JMP n jump to instruction n
DJZX n if register X is zero jump to instruction n,
otherwise decrement its value
DJZY n if register Y is zero jump to instruction n,
otherwise decrement its value
HALT halt (and accept)
PRINTX print the content of register X
Um programa de 2cm é simplesmente uma sequência de instruções, por exemplo, o programa a seguir copia o conteúdo do registro X para registrar Y:
cp: DJZX end
INCY
JMP cp
end: HALT
Observe que um 2CM é Turing Complete (ou seja, pode calcular todas as funções computáveis com uma codificação de entrada adequada, mas é irrelevante aqui). Observe também que o conjunto de instruções é um pouco diferente daquele no artigo da Wikipedia.
O desafio
Escreva o programa mais curto de 2CM, que calcula e imprime a sequência de collatz até 1 e pára (o registro X inicialmente contém o valor inicial n
e o registro Y inicialmente contém 0). Observe que o comprimento de um programa de 2cm é o número de instruções usadas (não o comprimento do texto).
Por exemplo, quando iniciado a partir de X = 3, ele deve imprimir: 3 10 5 16 8 4 2 1
e HALT.
Portanto, você pode usar seu idioma favorito para criar um simulador / intérprete de 2CM, mas o código final (mais curto) que você colocou na resposta deve estar no idioma de 2CM .
fonte
Respostas:
18 instruções
Fiquei um pouco desapontado por ter chegado tarde à cena, pois a natureza minimalista do problema e a linguagem fazem ali (aparentemente) apenas uma abordagem geral para uma boa resposta. Eu recebi uma resposta de 19 instruções rapidamente, mas não achei que fosse suficiente para postá-la na mesa. Mas, depois de muito esforço, minha experiência em montagem do z80 hacky veio à tona e eu encontrei uma maneira de salvar uma instrução reutilizando um bloco de código para um propósito a que não se destinava!
fonte
PONTUAÇÃO: 21
Aqui está a minha tentativa:
main
: imprimeX
e pula parafinish
(seX==1
).divisibility
: faz uma distinção seX%2==0
ouX%2==1
. Também copiaX
aY
e fazX==0
. Salta paraisDivisible
(seX%2==0
) ouisNotDivisible
(seX%2==1
).isDivisible
: loop usado quandoY%2==0
. Para cada diminuição deY
2, aumentaX
em 1. QuandoY==0
, salta paramain
.isNotDivisible
: usado quandoY%2==1
. AumentaX
em 1.notDivLoop
: loop usado quandoY%2==1
. Para cada diminuição deY
1, aumentaX
em 3. QuandoY==0
, pula paramain
.finish
: páraFornecido com 3 (usando o intérprete fornecido pelo @orlp), o resultado produzido é:
fonte
19 instruções
Escrevi meu próprio intérprete porque sou assim. Aqui está minha solução para meu próprio intérprete:
E aqui está o que parece com sintaxe compatível com o outro intérprete:
fonte
19 instruções
Você pode executá-lo usando meu intérprete .
fonte