Deadfish é uma das mais conhecidas linguagens de programação completas de Turing. Ele possui apenas um acumulador (que começa em 0) para armazenar dados e apenas quatro comandos:
i - Increment the accumulator
s - Square the accumulator
d - Decrement the accumulator
o - Output the accumulator
Um programa Deadfish pode se parecer com:
iiisdo
E isso imprimiria:
8
O desafio
Crie um programa que insira um número e imprima o código Deadfish para exibir o número (ou crie uma função que use o número como parâmetro e retorne o código.) Ele deve funcionar para qualquer número inteiro de 0
até255
Objetivo
Tente tornar seu código o código mais curto possível para gerar o número fornecido. Por exemplo:
iiiiiiiiio
e
iiiso
cada impressão 9
, mas a segunda é mais curta.
Pontuação
Sua pontuação é:
The number of characters in your source code +
The sum of the lengths of your output for all numbers from 1-255
-100 if the language you chose is Deadfish :)
Menor pontuação ganha!
No desafio original, eu tinha apenas a soma de 6 números (9,17,99,100 e 123). Isso era porque eu queria não fazer todo mundo testar para cada número, e eu queria que o código mais curto fosse relevante. Então eu percebi que os programadores são bons em criar scripts para testar coisas assim, e eu prefiro que este seja um concurso para o melhor algoritmo, com o golfe como desempate.
Por isso, mudei isso, conforme sugerido por Martin Büttner.
fonte
16^2 = 0
ou16^2 = 256
ou16^2 = error
?-1
OR256
, será redefinido para0
. Mas se você acertar um número maior do que256
ao quadrado, ele permanece inalterado, por exemplo17^2 = 289
. (consulte a página esolang)Respostas:
Perl,
132131 bytes + 2036 bytes = 2167Inclui +2 para
-lp
Corra com o número alvo no STDIN, por exemplo
deadfish.pl:
O grep é um filtro para restringir um pouco a explosão exponencial (embora esse programa ainda precise de 2 GB para os casos difíceis). Também funciona sem, mas não posso executá-lo no meu hardware assim, exceto nos casos fáceis. Mas, em princípio, este
110=108+2
programa de bytes também funciona:Lista de saída:
fonte
ES6 JavaScript 2126 + 311 = 2437 pontuação
Semi-comentado:
Isso aproveita o fato de que em peixes mortos, você pode imprimir mais de um caractere.
Exemplo:
10
compila aoiodo
qual é "imprima um, diminua, imprima zero".Uso:
Aqui estão os dados json da saída:
Isso foi gerado por este código:
que imprime
result = (the result)
ec =
a coisa acima.Isso obtém uma pontuação notavelmente alta, apesar de ser bastante simples. Ele procura o quadrado perfeito mais próximo, calcula a raiz quadrada desse quadrado perfeito, adiciona 's' e incrementa / diminui adequadamente.
Versão antiga que não usava o fato de "10" = "imprimir um, imprimir zero"
fonte
d
errou o efeito da operação - se ela diminui para-1
, ela é redefinida para0
, não255
.o
faz; ele gera o acumulador e uma nova linha.iodo
saídas1\n0\n
, não10
.o
. Nem muitos compiladores (em diferentes línguas) imprimir uma nova linha como
Mathematica,
254165 caracteres + 3455 = 3620Menos golfe:
Eu acredito que os números resultantes são ótimos. Isso está fazendo uma pesquisa abrangente em todos os 256 números, mantendo o controle da maneira mais curta que encontrou para representar cada número. A pesquisa está construindo uma espécie de tabela de pesquisa na função
g
que é aplicada à entrada.Para referência, aqui estão todos os resultados de 255:
fonte
n > 256
nãon ≥ 256
. E isso também está de acordo com a página esolang: "Embora o comentário na implementação C indique/* Make sure x is not greater then [sic] 256 */
, a implementação define o valor como zero se e somente sevalue == -1 || value == 256
".d
, de modo que deve imprimir 0. #Código C, 433 + saída 3455 = 3888
C ++, código 430 + saída 3455 = 3885
E agora para algo completamente diferente.
Eu usei a saída da resposta do Martin Mathematica (atualizada em 23 de outubro, pois estava errada para mais de 240). Minha saída tem os mesmos 3455 caracteres. Analisei padrões na saída e descobri que [0,255] pode ser representado por esta sequência:
i
ss
si
s oud
ss
si
ou 0-16d
so
O passo seguinte foi a construção cuidadosamente estes cinco colunas (
c
atravésg
do código abaixo). Eu usei números negativos para indicar emd
vez dei
em colunase
eg
. Acontece que os resultados funcionam principalmente como um contador nag
coluna, pois cada linhau
normalmente remove umd
ou adiciona um emi
relação à linha anterior (v
). Há 15 exceções, que são armazenadas nosx
(índices) eb
(nas cinco colunas, empacotadas em um número inteiro que requer apenas 14 bits para armazenar o máximo10832
).Por exemplo, a primeira "exceção" é a primeira linha, na qual queremos zero caracteres além da terminação
o
. Assimx[0]
é0
, eb[0]
é544
, que quando descompactado é (estilo "little endian", já queg
é a coluna de contagem){ 32, 0, 4, 0, 0 }
. Sempre subtraímos 32 deg
e 4 dee
para fazer os campos de bits não assinados funcionarem (ou seja, essas duas colunas representam números negativos conceitualmente quandod
é necessário, em vez dei
, mas na implementação os valores são deslocados para evitar números negativos reais).Aqui está uma tabela mostrando como os dez primeiros números funcionam (os espaços em branco são zeros):
Você pode ver que, na
g
maioria das vezes, apenas incrementa um por cada nova linha, mas algumas linhas (0, 4, 8, ..., que eu esperava encontrar brevemente no OEIS) "redefinem" a sequência, o que significa queg
assume um novo valor e pelo menos uma outra coluna também é modificada.A contagem de caracteres do código exclui os espaços em branco, exceto a nova linha obrigatória antes de cada
#
e o espaço apósunsigned
eint
. Você pode salvar três caracteres compilando como C ++ em vez de C, substituindo<stdio.h>
por<cstdio>
e*(int*)&u
por(int&)u
.Um fato interessante sobre esse código: uma versão anterior usava uma matriz de 256 uniões em vez de apenas
u
ev
. Essa versão fez com que o GCC 4.7.2 gerasse um erro interno do compilador! O GCC 4.9 o corrigiu, no entanto, e o código acima funciona com qualquer uma das versões.fonte
for(...)
porscanf
- isso diminuiria a contagem de caracteres).#include
, e talvez você possa tornar ostruct
interiorunion
sem nome.for
loop ainda é necessário devido à maneira como calculo o resultado. Isso, além de remover o nome da estrutura, salvou 5 caracteres; outro dois foram salvos alterando==
a>
e remover o final de linha. :) O programa é totalmente válido apenas em C99, porquemain
não retorna explicitamente um valor; removendo os#include
resultados em um erro devido ascanf()
agora.256
.Haskell,
220021772171 = 2036 + 135isso funciona com uma lista infinita de todos os programas de peixes mortos, classificados por seu comprimento, acompanhados pelo estado interno e pela saída. a função
f
pesquisa na lista e retorna a primeira entrada que corresponde.essa abordagem permite múltiplos
o
em cada código resultante, mas não a restringe a imprimir todos os dígitos separadamente ou a imprimir o número inteiro de uma só vez. por exemplo, aqui 216 tem o código deiiosso
.Edit: de
acordo com a especificação, quando o estado é 256 (mas não 257) é transformado em um 0. agora meu código leva isso em consideração. por exemplo, 160 é
iissoso
.isso tem alguns problemas de eficiência; porque
l
é uma lista de nível superior, todos os elementosl
avaliados foram mantidos na memória e, portanto, o tempo de execução provavelmente ficará sem memória em algum momento.para calcular a pontuação, criei uma versão equivalente, mas com menos memória pesada.
meu código mais eficiente funciona recalculando a lista em todos os aplicativos de
f
, para que o coletor de lixo possa jogar fora a parte já pesquisada da lista. de certa forma, essa é a primeira pesquisa abrangente usando preguiça.o código mais eficiente também adiciona mais restrições aos elementos da lista - filtra todos os códigos que contêm
id
oudi
, ou contém ums
quando o estado é menor que 2.Editar:
movi a
g
função do nível superior para ser uma função auxiliarf'
, então agorag
filtra códigos que imprimem algo que não é um prefixo do número desejado. agora o código é muito mais rápido.o código mais eficiente:
observe que o código mais eficiente não terá os mesmos resultados, porque os programas atravessam todos os códigos possíveis em ordem diferente. no entanto, eles produzirão códigos do mesmo comprimento. Além disso, alternar
c:x
comx++[c]
torna os programas equivalentes.com este código, eu era capaz de calcular todos os programas em
520,81 segundos.Edit:
aparentemente esta é a melhor resposta! Eu notei isso agora, tão longe de quando isso foi perguntado ...
os resultados:
fonte
Picat 516 + 2060 = 2576
É uma versão um pouco modificada do programa Sergey Dymchenko . Esta versão gera programas de peixes mortos mais compactos.
Tanto quanto eu entendi a frase "comprimentos de saídas", significa que eu deveria somar a saída sem caracteres de nova linha.
Usar:
1-255 Códigos:
Atuação:
Versão do programa para medir o tempo:
Resultado:
Saída total:
fonte
ioio
iria imprimir"12"
e não"11"
JavaScript (E6) 141 + 3455 = 3596
A função recursiva que procura a raiz quadrada mais próxima, mas evitar 16 como 16 * 16 = 256 será alterada para 0. Muitas outras respostas não entendem esse ponto.
Teste no console do FireFox / FireBug
Saída
fonte
Picat, código 242 + saída 3455 = 3697
Veja http://picat-lang.org/ para obter informações sobre Picat.
Menos golfe:
fonte
Python 3 - 4286 + 168 = 4454
Não é muito sério, mas extremamente simples. Apenas encontra o melhor da adição a 0, uma praça, a 4 ª poder
e um 8 th poder.EDIT: Golfed 75 bytes, o 8 th poder não fez nada
EDIT 2: Removidos alguns bytes para implementar corretamente
d
. A pontuação aumentou, no entanto.Python 3-2594 + 201 = 2795
Este usa um tipo de pesquisa aprofundada para encontrar o programa mais curto. Eu adicionei algumas otimizações (desnecessárias?) A ele, para que eu pudesse obter o resultado; desta forma, não precisa executar tantos caminhos. Pode tentar remover alguns deles. Não supera o JS, pois usa truques inteligentes como múltiplos
o
.Edição: Golfed 93 bytes, aparentemente, eu tinha um crapton de código inútil deixado lá pelo desenvolvimento. Também removi tudo o que achei desnecessário até agora. Aqui vou eu, JS.
Edição 2: Golfed fora outros 8 bytes. Isso
return
foi desnecessário.EDIT 3: Jogou 5 bytes adicionais. Agora que nos livramos disso, um poderia colocar um em
elif
vez do outroreturn
.EDIT 4: Corrigida a funcionalidade de
d
. Tamanho aumentado em 1 byte, pontuação em alguns bytes.fonte
APL: 80 + 3456 = 3536
Explicação: (corrigida após a nota de edc65, obrigado)
⍵ <4: i'i 'Se o argumento for menor que 3, replique "i" tantas vezes
(⌈, ⌊) ⍵ * .5 ⍵ é o argumento, crie raiz quadrada e pegue o teto e o chão
| ⍵-2 * ⍨ eleve aqueles teto e piso à potência 2, remova argumentos e faça positivo
b←⊃(>,<,=)/ get a boolean vector with a>b, a
(⍵> 240) ⌽ Para evitar ir para 256, faça "i" para números acima de 240, em vez de ^ 2
b / 'ids' usa esse booleano para pegar i, d ou se anexá-lo à solução com,
, ∇ (-⊃b) + b [2] + ⍵ * 1 + 3⊃b Chame recursivamente a função com o argumento -b 1 + b [2] elevado à potência (inverso de b [3] +1)
Pode contar a saída com:
¨ aplica a função a cada número 0-255
+ / ⊃, / ⍴¨ conta o número total de elementos
Novamente, você pode tentar todas as opções acima em TryApl.org
BTW: São 3456 e não 3455, porque também estou considerando 0, pois acho que o problema estava perguntando. Se for 1-255, a pontuação é 80 + 3455 = 3535
fonte
Python 2712 = 2608 + 104
Código:
Usar:
0-255 Código:
fonte
CJam,
2436 2392 22962173 ( 74 caracteres + 2099)Que se traduz em:
Tenta otimizar o comprimento do código Deadfish, escolhendo o caminho mais curto para alcançar cada dígito do número.
Obrigado Martin pela tradução Unicode
Aqui está a lista completa de códigos
Experimente online aqui:
fonte
o
imprima nova linha. Todos os compiladores também estavam simplesmente imprimindo sem nova linha.C printf("%d\n",x);
C# Console.WriteLine(x)
GO fmt.Println(x)
pascal WRITELN(val);
python print accumulator (no comma)
bash echo $no;; (no -n)