Você recebe uma máquina com dois registradores de 16 bits x
e y
. Os registros são inicializados x=1
e y=0
. A única operação que a máquina pode fazer é o módulo de adição 65536. Ou seja:
x+=y
-x
é substituído por(x + y) mod 65536
;y
é inalteradoy+=x
- da mesma forma paray
x+=x
-x
é substituído por2x mod 65536
; legal apenas sex
for mesmoy+=y
- da mesma forma paray
O objetivo é obter um número predeterminado em um dos registros (um x
ou y
).
Escreva um programa ou uma sub-rotina que receba um número (em stdin
, argv
parâmetro de função, parte superior da pilha ou qualquer outro local convencional) e envie um programa para obter esse número. A saída deve ir para stdout
(ou se seu idioma não tiver stdout
) para qualquer outro dispositivo de saída convencional.
O programa de saída pode ser de até 100% mais 2 etapas longe do ideal. Ou seja, se o programa mais curto para obter o número de destino tiver n
etapas, sua solução não poderá ser maior que 2n+2
. Essa restrição é para evitar soluções "fáceis demais" (por exemplo, contando 1, 2, 3, ...), mas não requer otimização total; Espero que o programa mais curto seja o mais fácil de encontrar, mas não tenho certeza ...
Por exemplo: Entrada = 25. Saída:
y+=x
x+=y
x+=y
x+=x
x+=x
x+=x
y+=x
Outro exemplo: para qualquer número de fibonacci, a saída tem esse padrão alternado. Para Input = 21, a saída é
y+=x
x+=y
y+=x
x+=y
y+=x
x+=y
y+=x
O código mais curto (medido em bytes) vence.
(esse quebra-cabeça foi inspirado em algum código para um processador de 16 bits que tive que gerar recentemente)
PS eu me pergunto - para qual número o programa ideal é mais longo?
fonte
x+=x
legal apenas sex
é par? Também para o programa mais curto, acho que algo como o BFS poderia funcionar.x+=x
apenas funciona para paresx
, como é que o exemplo de uma entrada de 25 duplos 3?Respostas:
CJam, 31
Como a resposta de @Tobia , meu algoritmo também é descaradamente
roubado,inspirado na resposta de @CChak . Mas, usando a magia negra que é CJam, consegui fazer uma implementação ainda menor do algoritmo.Experimente aqui.
Golfe:
Ungolfed:
Corrija-me se estiver errado, mas acreditava que a operação do módulo 65536 usada nas respostas com um algoritmo semelhante é desnecessária. Interpretei a questão de modo que possamos assumir que a entrada será um número inteiro de 16 bits sem sinal válido e quaisquer valores ou resultados intermediários desse algoritmo também serão.
fonte
Perl
10797Primeiro post, então aqui vai.
O que se encaixa em todos os critérios de adição de registro, mas não fiz uma verificação exaustiva para ver se minha resposta estava sempre dentro de 2n + 2 do número ideal de etapas. Está bem dentro do limite para todos os números de Fibonacci.
Aqui está uma análise mais detalhada
Como eu mencionei, esta é minha primeira tentativa de jogar golfe, então tenho certeza de que isso pode ser melhorado. Além disso, não tenho certeza se a chamada de sub-rotina inicial deve ser contada em uma chamada recursiva ou não, o que poderia levar alguns caracteres.
Curiosamente, podemos reduzir o código em 11 bytes * e melhorar nossa "eficiência" em termos de número de operações de registro, relaxando a exigência de que apenas valores pares possam ser "dobrados". Eu incluí isso por diversão aqui:
Comece o adendo:
Gostei muito desse problema, e eu tenho brincado com ele de vez em quando nas últimas duas semanas. Pensei em publicar meus resultados.
Alguns números:
Usando um algoritmo BFS para encontrar uma solução ideal, nos primeiros 2 ^ 16 números, existem apenas 18 números que requerem 23 etapas. Eles são: 58558, 59894, 60110, 61182, 61278, 62295, 62430, 62910, 63422, 63462, 63979, 64230, 64314, 4486, 64510, 64698, 64854, 65295.
Usando o algoritmo recursivo descrito acima, o número "mais difícil" de alcançar é 65535, em 45 operações. (65534 leva 44 e há 14 números que dão 43 etapas) 65535 também é a maior saída do ideal, 45 vs 22. A diferença de 23 etapas é 2n + 1. (Apenas três números atingem 2n: 65534, 32767, 32751.) Exceto nos casos triviais (etapa zero), no intervalo definido, o método recursivo calcula a média de aproximadamente 1,4 vezes a solução ideal.
Conclusão: para os números 1-2 ^ 16, o algoritmo recursivo nunca cruza o limite definido de 2n + 2, portanto a resposta é válida. Suspeito que, no entanto, começaria a se afastar muito da solução ideal para registros maiores / mais bits.
O código que eu usei para criar o BFS era desleixado, com muita memória, não comentado e deliberadamente não incluído. Então ... você não precisa confiar nos meus resultados, mas estou bastante confiante neles.
fonte
Python 3, 202 bytes
(Obrigado a @rationalis por alguns bytes)
Aqui está uma solução extremamente básica. Eu gostaria de poder jogar melhor a última linha, mas atualmente estou sem ideias. Ligue com
S(25)
.O programa apenas executa um BFS simples, sem cache, por isso é muito lento. Aqui está
S(97)
, para alguns exemplos de saída:fonte
Dyalog APL, 49 caracteres / bytes *
Algoritmo descaradamente inspirado na resposta de @CChak .
Exemplo:
Ungolfed:
* O Dyalog APL suporta um conjunto de caracteres herdado que possui os símbolos da APL mapeados para os valores superiores de 128 bytes. Portanto, um programa APL que usa apenas caracteres ASCII e símbolos APL pode ser considerado como bytes == chars.
fonte
Python, 183
Não posso garantir que isso fique dentro do dobro do programa ideal para números pares, mas é eficiente. Para todas as entradas válidas
0 <= n < 65536
, é essencialmente instantânea e gera um programa com no máximo 33 instruções. Para um tamanho de registro arbitrárion
(depois de fixar essa constante), levariaO(n)
tempo com, no máximo,2n+1
instruções.Alguma Lógica Binária
Qualquer número ímpar
n
pode ser alcançado dentro de 31 etapas: doy+=x
, obtendox,y = 1,1
e, em seguida, continuando dobrandox
comx+=x
(para o primeiro duplicadox+=y
, poisx
é estranho, para começar).x
atingirá todas as potências de 2 dessa maneira (é apenas um deslocamento para a esquerda) e, portanto, você poderá definiry
1 como uma adicionando a potência correspondente a 2. Como estamos usando registradores de 16 bits, e cada bit, exceto para a primeira leva uma duplicação para alcançar e outray+=x
para definir, temos no máximo 31 ops.Qualquer número par
n
é apenas uma potência de 2, liguea
, vezes um número ímpar, liguem
; ou sejan = 2^a * m
, ou equivalenten = m << a
. Use o processo acima para obter em
, em seguida, redefinax
movendo-o para a esquerda até chegar a 0. Faça ax+=y
para definirx = m
e continue dobrandox
, na primeira vez, usandox+=y
e subseqüentementex+=x
.Seja o que
a
for, são necessárias16-a
mudançasx
para obtery=m
e outrasa
alterações para redefinirx=0
. Outrasa
mudançasx
ocorrerão depoisx=m
. Portanto, um total de16+a
turnos é usado. Existem até16-a
bits que precisam ser configurados para obterm
, e cada um deles precisará de umy+=x
. Finalmente, precisamos de uma etapa extrax=0
para configurá-la como mx+=y
,. Portanto, são necessários no máximo 33 etapas para obter qualquer número par.Você pode, é claro, generalizar isso para qualquer registro de tamanho, caso em que sempre leva no máximo
2n-1
e2n+1
ops para númerosn
inteiros ímpares e pares , respectivamente.Optimalidade
Esse algoritmo produz um programa que é quase ideal (ou seja,
2n+2
sen
é o número mínimo de etapas) para números ímpares. Para um determinado número ímparn
, se om
th bit for o primeiro 1, qualquer programa executa pelo menosm
etapas para chegar ax=n
ouy=n
, uma vez que a operação que aumenta os valores dos registros mais rapidamente éx+=x
ouy+=y
( ou seja, duplicação) e é necessáriam
duplicação para obter om
th bit de 1. Como esse algoritmo executa no máximo algumas2m
etapas (no máximo duas por duplicação, uma para o turno e outray+=x
), qualquer número ímpar é representado quase idealmente.Números pares não são tão bons, pois sempre usam 16 ops para redefinir
x
antes de qualquer outra coisa, e 8, por exemplo, pode ser alcançado em 5 etapas.Curiosamente, o algoritmo acima nunca usa
y+=y
, poisy
é sempre mantido ímpar. Nesse caso, ele pode realmente encontrar o programa mais curto para o conjunto restrito de apenas 3 operações.Teste
Eu escrevi um teste simples para verificar se minha solução realmente produz resultados corretos, e nunca ultrapassa 33 etapas, para todas as entradas válidas (
0 <= n < 65536
).Além disso, tentei fazer uma análise empírica para comparar a saída da minha solução com a saída ideal - no entanto, verifica-se que a pesquisa pela primeira vez é muito ineficiente para obter o comprimento mínimo de saída para cada entrada válida
n
. Por exemplo, o uso do BFS para encontrar a saída paran = 65535
não termina em um período de tempo razoável. No entanto, eu participeibfs()
e estou aberto a sugestões.No entanto, testei minha própria solução no @ CChak's (implementado em Python aqui como
U
). Eu esperava que o meu fizesse pior, já que é drasticamente ineficiente para números pares menores, mas, em toda a faixa de duas maneiras, a mina produziu uma produção de comprimento em média 10,8% a 12,3% menor. Eu pensei que talvez isso fosse devido à melhor eficiência da minha própria solução em números ímpares, entãoV
usa o meu em números ímpares e @ CChak em números pares, masV
está no meio (cerca de 10% menor queU
, 3% maior queS
).fonte
x,y='xy'
era possível até agora. Infelizmente, não consigo pensar em uma maneira de reescrever dec*b+e*2
forma concisa com a%
formatação.S(2)
a produção é realmente longa?S(2)
sendo a mais curta aos 19). Eu não acompanhox
ey
explico explicitamente, mesmo quex
chegue a 2 após o segundo passo, ele continua a redefinirx
para 0. Eu sinto que deve haver uma solução melhor, mas ainda não consigo pensar em 1.