Escreva o programa mais curto que imprima a letra inteira de "Never Gonna Give You Up" de Rick Astley.
Regras:
- É necessário que a letra seja impressa exatamente como aparece no pastebin * acima. Aqui está o despejo bruto: http://pastebin.com/raw/wwvdjvEj
- Não pode confiar em nenhum recurso externo - todas as letras devem ser geradas por / incorporadas no código.
- Nenhum uso de algoritmos de compactação existentes (por exemplo, gzip / bzip2), a menos que você inclua o algoritmo completo em seu código.
- Use qualquer idioma, o código mais curto vence.
Atualização, 1º de junho de 2012:
Para soluções que contenham texto não ASCII, o tamanho da sua solução será contado em bytes, com base na codificação UTF-8. Se você usar pontos de código que não podem ser codificados em UTF-8, sua solução não será considerada válida.
Atualização, 7 de junho de 2012:
Obrigado a todos por suas soluções impressionantes! Aceitarei a resposta mais curta amanhã à tarde. No momento, a resposta do GolfScript de Peter Taylor está ganhando, então aproveite algumas melhorias se você quiser vencê-lo! :)
* Há um erro de digitação no Pastebin (linha 46, "saber" deve ser "conhecido"). Você pode replicá-lo ou não, a seu critério.
fonte
Respostas:
Ruby
576 557556 (552) chars && PHP 543 charsOutra solução de busca e substituição. Observe que esta forma de solução é essencialmente um código de compactação baseado em gramática http://en.wikipedia.org/wiki/Grammar-based_code Confira http://www.cs.washington.edu/education/courses/csep590a/07au /lectures/lecture05small.pdf para um exemplo simples de entender a compactação.
Eu escrevi as regras de substituição para que o caractere inicial de cada substituição seja calculado (eles estão em ordem ASCII sequencial); ele não precisa estar presente nos dados de transição.
notas de implementação
implementação mais antiga
Esta implementação mais antiga possui 576 caracteres e começou com regras de substituição da implementação bash / sed do ugoren. Ignorando a renomeação da variável de substituição, minhas primeiras 28 substituições são exatamente iguais às executadas no programa da ugoren. Adicionei mais alguns para diminuir a contagem geral de bytes. Isso é possível porque minhas regras são representadas com mais eficiência do que aquelas na implementação da ugoren.
Eu não tentei otimizar as regras de substituição neste.
notas do concurso
O esquema de descompactação de busca e substituição funciona bem para este concurso, porque a maioria dos idiomas possui rotinas pré-criadas que podem fazer isso. Com uma quantidade tão pequena de texto a ser gerada, esquemas complexos de descompressão não parecem ser vencedores possíveis.
Usei apenas texto ASCII e também evitei usar caracteres ASCII não imprimíveis. Com essas restrições, cada caractere no seu código pode representar apenas um máximo de 6,6 bits de informação; isso é muito diferente das técnicas de compactação reais , nas quais você usa todos os 8 bits. Em certo sentido, não é "justo" comparar com o tamanho do código gzip / bzip2 porque esses algoritmos usarão todos os 8 bits. Um algoritmo de descompactação mais sofisticado pode ser possível se você puder incluir ASCII tradicionalmente não imprimível em suas seqüências E cada caractere não imprimível ainda será gravado no seu código como um único byte.
Solução PHP
A solução acima pega o PHP de "um cara triste" e o combina com minhas regras de substituição. A resposta PHP acaba tendo o menor código de descompactação. Consulte http://ideone.com/XoW5t
fonte
sed
solução certamente não pode vencê-lo. Estou trabalhando em algo que espero ter uma chance - você tem 75 bytes de sobrecarga, talvez eu o reduza (não em Ruby).Bash / Sed,
705650588582 caracteresLógica :
a idéia básica é a substituição simples. Em vez de escrever, por exemplo,
Never gonna give you up\nNever gonna let you down
escrevoXgive you up\nXlet you down
e substituo todosX
porNever gonna
.Isso é conseguido executando
sed
com um conjunto de regras, no formulários/X/Never gonna /g
.As substituições podem ser aninhadas. Por exemplo,
Never gonna
é comum, mas tambémgonna
em outros contextos. Então, eu posso usar duas regras:s/Y/ gonna/g
es/X/NeverY/g
.Ao adicionar regras, partes dos textos das músicas são substituídas por caracteres únicos, tornando-as mais curtas. As regras se tornam mais longas, mas se a sequência substituída for longa e frequente, vale a pena.
O próximo passo é remover a repetição dos
sed
próprios comandos. A sequências/X/something/g
é bastante repetitiva.Para torná-lo mais curto, altero os comandos sed para que se pareçam
Xsomething
. Então eu usosed
para converter isso em umsed
comando normal . O códigosed 's#.#s/&/#;s#$#/g;#
faz isso.O resultado final é um
sed
comando, cujos argumentos são gerados por outrosed
comando, entre aspas.Você pode encontrar uma explicação mais detalhada neste link .
Código:
Notas:
O mecanismo de descompressão possui apenas 40 caracteres. Os outros 543 são a tabela de conversão e o texto compactado.
bzip2
compacta a música para 500 bytes (sem o mecanismo, é claro), então deve haver espaço para melhorias (embora eu não veja como adicionaria a codificação Huffman ou algo assim barato o suficiente).<<Q
(ou<<_
) é usado para ler até um determinado caractere. Mas o final do script (ou expressão de aspas) é bom o suficiente. Isso às vezes causa um aviso.Solução mais antiga e simples, 666 caracteres:
fonte
\0
com&
.&
faz 5.Espaço em branco - 33115 caracteres
StackExchange chomped minha resposta, aqui está a fonte: https://gist.github.com/lucaspiller/2852385
Não é ótimo ... Acho que posso diminuir um pouco.
(Se você não souber o que é o espaço em branco: http://en.wikipedia.org/wiki/Whitespace_(programming_language) )
fonte
JavaScript,
590588 bytesDependendo um pouco da maneira como a string é "impressa".
https://gist.github.com/2864108
fonte
if(g.indexOf(g[i])!=-1)
antese=
para corrigi-lo.with(f.split(g[i]))f=join(pop())
nofor..in
circuito salva um byteC #
879816789 caracteresA primeira tentativa no CodeGolf definitivamente não é um vencedor, com certeza é válido, apesar de ser desagradável.
fonte
var s1="a";var s2="b";
tentar usarstring s1="a",s2="b"
; se você tiver mais de 2 declarações, é mais curto.!
e retirando-o de qualquer outro lugar.Python,
597589 bytesPode ser possível extrair mais alguns bytes:
fonte
BrainFuck - 9905
Tenho certeza de que posso melhorar um pouco ajustando-o, mas isso é muito bom por enquanto. Supondo que você não tenha nenhum problema com isso ser muito maior que o texto original.
fonte
Scala, 613 bytes
Este é um algoritmo de descompressão de texto, aplicando recursivamente a regra que
~stuff~ blah ~ ~
deve ser convertidastuff blah stuff stuff
(ou seja, na primeira vez em que você vê um par de símbolos desconhecido, ele delimita o que copiar; depois, você preenche o valor quando o vê).Nota: pode haver um retorno de carro extra no final, dependendo de como você conta. Se isso não for permitido, você pode soltar o último na cotação (salvando um caractere) e alterar a divisão para
split(" ",-1)
(gastando 3 caracteres), para 615 bytes.fonte
N
repetições de comprimentoL
, você usaL+N+1
caracteres, enquanto eu usoL+N+2
. Mas o seu código de descompressão é de 102 caracteres, enquanto o meu é de 40.589, C (apenas a função de biblioteca é putchar)
Tabela de regras de substituição em que caracteres no intervalo -.._ (45..90) especificam qual regra aplicar; assim, 48 regras (45, c-45> U48 no código), outros caracteres devem ser impressos
as regras são delimitadas pelo caractere '&' (38 no código, n é decrementado até o zero e, portanto, s aponta para a regra correta)
regra 0 indica que o próximo caractere deve ser maiúsculo (definindo k = 32 no código), isso libera mais espaço para adicionar um intervalo contínuo maior de caracteres para regras
main (..) é chamado com 1 (conforme a convenção do programa com argumento zero C) e, portanto, a regra 1 é a regra raiz
Evolução do código
raspou mais 9 bytes graças à sugestão de ugoren
eliminou outros 36 bytes, criando a tabela algoritmicamente, e não manualmente, e através da dica "'"
eliminou outros 15 bytes alterando a tabela de um caractere * [] para uma única sequência em que '&' delimita partes
raspou mais 19 bytes graças a mais dicas da ugoren
raspou 31 bytes adicionando mais regras, criou regras especiais para capitalizar, permitindo assim mais espaço para índices de regras.
eliminou 10 bytes graças a mais dicas da urgoren e aprimora ligeiramente as regras
fonte
*p>>4^3?putchar(*p):e(r[*p-48])
"\'"
tradução não é necessária."We're"
é uma sequência válida.ing
é um candidato melhor.d(int n)
->d(n)
. Mude*s=='~'
para*s-'~' and reverse the
?:, also saving parenthesis around
! N? ..: 0. Using 126 instead of
'~' 'é inútil, mas por quê~
?main
recursivas. A chamada inicial émain(1)
, em vez ded(0)
, mas pode ser tratada (talvez um líder~
ems
). Além disso, a melhor alternativa~
é uma guia (ascii 9 - dígito único).Perl,
724714883 bytesPortanto, a mudança nas regras que penalizam o uso do tipo Latin-1 acabou com minha solução. É uma abordagem diferente o suficiente que eu odeio excluí-la, então aqui está uma versão restrita que usa apenas ASCII de 7 bits, de acordo com as novas regras, com um grande aumento de tamanho.
É claro que os caracteres de controle ainda estão mutilados aqui, então você ainda desejará usar a codificação base64:
Como eu acho que ainda deve estar visível, apesar de ter uma DQ, eis a solução original:
A codificação base64 do script:
fonte
Python
781731605579 CharsHá muito mais e melhores respostas desde quando vi isso pela primeira vez, mas perdi muito tempo no meu script python, então vou publicá-lo de qualquer maneira, seria incrível ver sugestões para encurtá-lo ainda mais,
Edit: graças às sugestões de Ed H 2 caracteres picados, para ir mais longe, talvez eu precise reestruturar muita coisa aqui que vai levar algum tempo
Após a primeira vez que produzi manualmente a string (muito entediante), escrevi uma função para encontrar recursivamente a substituição do padrão que era mais lucrativa (nessa etapa), o que me deu uma solução, mas acabou aumentando o tamanho em 10 caracteres.
Portanto, tornei meu algoritmo um pouco menos ganancioso, em vez de fazer a classificação final apenas em 'caracteres reduzidos', classificando em uma função de 'caracteres reduzidos', 'comprimento do padrão' e 'contagens do padrão'
comprimento padrão = contagem de comprimento = contagem
Então eu perguntei a minha pobre laptop para executar infinitamente, atribuindo valores aleatórios para
lengthWeight
ecountWeight
e obter diferentes tamanhos de compressão final, e armazenar os dados para tamanhos mínimos de compressão em um arquivoEm meia hora, surgiu a string acima (tentei mexer ainda mais para ver se era possível encurtar o código), e não diminuirá mais, acho que estou perdendo alguma coisa aqui.
aqui está o meu código para ele, também
max_pattern
é muito lento (Nota: o código cospe uma string semelhante ao formulário na minha versão anterior da solução, eu trabalhei manualmente para obter o formulário atual, quer dizer manualmente, manualmente no shell python)fonte
\n
custará 5 caracteres e economizará 9. 2. Espaço extra emin (g,l..)
. 3.join(..)
funciona tão bem quantojoin([..])
(pelo menos em 2.7).Malbolge, 12735 bytes
Experimente online.
Gerado usando as ferramentas aqui.
fonte
JavaScript 666 bytes
Inspirado na solução da tkazec .
Confira o post que escrevi sobre ele, ele contém todas as fontes e explica como eu criei esse código.
Você pode copiar e colar o código no console do seu navegador. Ou tente em http://jsfiddle.net/eikes/Sws4g/1/
fonte
Perl,
584578577576575571564554553540Essa solução segue a mesma abordagem básica que a maioria das outras: dada uma sequência inicial, execute substituições repetidas de partes repetidas do texto.
As regras de substituição são especificadas por um único caractere, de preferência um que não ocorra no texto de saída; portanto, uma regra de comprimento L e N vezes ocorrida economizará aproximadamente N * LNL-1 (N * L é o comprimento original de todas as ocorrências, mas o caractere de substituição ocorre N vezes e o próprio texto literal tem comprimento L e as regras são divididas por um caractere de separação.) Se os caracteres de substituição forem explicitamente especificados, a economia será reduzida para N * LNL-2. Dado que a maioria dos idiomas pode calcular um caractere com chr () ou código curto similar, a primeira abordagem tende a ser superior.
Existem algumas desvantagens em calcular o caractere de substituição, sendo a mais significativa a necessidade de um intervalo contínuo de caracteres ASCII. A saída usa principalmente letras minúsculas, mas há letras maiúsculas e pontuação suficientes para exigir a substituição de um caractere por si mesmo, remapeando alguns caracteres em um estágio de correção posteriormente ou ordenando as regras para que substituições por caracteres problemáticos ocorram anteriormente. O uso de uma linguagem que substitui o uso de expressões regulares também significa que existem dicas para caracteres que têm um significado especial em uma expressão regular:
.
+
*
\
?
Minha abordagem original tinha 63 bytes no decodificador e 521 nas regras. Passei muito tempo otimizando as regras, o que pode ser complicado, especialmente com as regras curtas, pois elas podem se sobrepor. Eu consegui a decodificação para 55 bytes e as regras para 485 enganando a fórmula um pouco. Normalmente, uma regra de 2 caracteres que ocorre 3 vezes ou uma regra de 3 caracteres que ocorre duas vezes não economiza muito, mas existe uma brecha - que também permite criar palavras que não fazem parte da saída; )
Eu uso caracteres de controle nesta solução, portanto a solução é fornecida aqui codificada em base64.
E aqui está uma versão um pouco mais legível (mas menos executável).
No entanto, suspeito que isso ainda não é o mínimo, como Ed H. salienta que a decodificação do php é a mais curta de 44 bytes e vi espaço para melhorias nas regras que ele está usando. Eu tenho um decodificador de 52 bytes no Perl, mas não consegui usá-lo para esta solução, pois precisava executar o intervalo inversamente.
fonte
PHP
730707 caracteresfonte
$s="Never gonna give...
pode ser encurtado com$n
.Perl -
589588583 579576 bytesCada regra consiste em uma cabeça de 1 caractere, um corpo e um sublinhado. Desde que as regras possam ser cortadas no início, a cabeça da regra é substituída por seu corpo no restante do texto. O cabeçalho da primeira regra é fornecido, os cabeçotes de todas as regras a seguir são gerados a partir da variável $ i.
Como o cabeçalho da próxima regra é colocado no início do texto pela regra anterior, a última regra criará um personagem que não será mais removido. Eu tive que escolher uma variedade de nomes onde o último seria "W", para que eu pudesse remover o "W" original desde o início da letra e substituí-lo pela substituição de regra.
A codificação foi feita por um script Python usando um algoritmo simples de alpinismo.
Aqui está o código Perl:
(Acho notável que o texto compactado contenha "hearBach": D)
E aqui o código Python que o gera:
fonte
while
para o loop; isso permite que você abandone os aparelhos, além dos parênteses. Outra idéia: descobrir como usar emsay
vez deprint
fazer a saída.Python 2.7,
975803 bytesNão é o melhor - eu (agora) gostaria que o python fizesse expansões de formatação assim. Infelizmente não.
Editar: expansão simulada com sintaxe de formatação alternativa (tipo de ..)
fonte
Clojure
720 bytes / caracteres:
(Reproduzido aqui com espaço em branco extra para que você possa ver a formatação)
fonte
C # - 605 caracteres | T-SQL - 795 caracteres | C # - 732 caracteres | C # - 659 caracteres
A inspiração para isso veio do exemplo sed. A única grande mudança que fiz disso foi tornar as pesquisas caracteres ASCII consecutivos para que eles não precisassem ser declarados. Infelizmente, é C #, então não sei como diminuí-lo. Peguei o mesmo texto de substituição e fiz o código no T-SQL usando uma tabela temporária.
T-SQL
Segunda tentativa Esta foi uma tentativa de uma abordagem diferente. A compactação foi realizada inteiramente pelo computador, buscando as melhores substituições. As pesquisas são seqüenciais e ordenadas por tamanho, portanto, não há necessidade de pesquisas delimitadas; no entanto, o código para fazer as pesquisas foi menos eficiente do que eu pensava, por isso acabou custando 127 caracteres a mais no total! Viva e aprenda.
Terceira tentativa em C #. Dessa vez, venci com caracteres \ b, \ r, \ t. Você pode usar \ rN \ n para substituir o primeiro caractere da linha por N maiúsculo, mas ele não salvou os caracteres. Criei \ b aliases para mover o cursor para trás e depois escrever sobre o texto existente. Mas nada disso economizou espaço e, no final, eu ainda estava pior do que uma simples estratégia de busca e substituição.
fonte
REPLACE
abordagem inteligente , especialmente com o SQL dinâmico, mas existem muitas maneiras de jogar mais: Use@
como variável em vez de@s
, torne-a uma tabela permanente emt
vez de#t
(você não precisa se limpar), livrar-se da declaração COLLATE 29 caracteres e simplesmente exigir que ele seja executado em um servidor / banco de dados com o agrupamento, utilizaçãovarchar(999)
ouvarchar(max)
, toneladas de espaço em branco desnecessário em torno de sinais de igual e vírgulas, etc.PHP,
591585568564 bytesfonte
Ruby, 1014 bytes
Estou apenas aprendendo programação, então não vou quebrar nenhum recorde aqui. Mas, essa foi uma tarefa divertida.
fonte
GolfScript (511 bytes)
Isso usa uma mudança de base para compactar os bits, por isso inclui caracteres que não estão em ASCII. No entanto, não é apropriado pontuar esses caracteres pela codificação UTF-8, porque o intérprete trata o programa como ISO-8859-1. Por esse motivo, especifiquei o comprimento em bytes, em vez de caracteres.
Codificado na base 64:
Despejo hexadecimal (saída de
xxd
):Como a maioria das melhores soluções, isso usa uma abordagem baseada em gramática com divisões e junções de strings para expandir a gramática. A gramática tem 30 regras e foi encontrada por uma pesquisa gananciosa.
fonte
JavaScript, 854 caracteres (novas linhas adicionadas para "legibilidade")
fonte
Shive / eco ingênuo - 810 bytes
fonte
JavaScript 789 caracteres
Meu javascript (imprime com "document.write ()"):
Altero algumas palavras e frases comuns com letras cirílicas e depois as troquei de volta com a função replace ().
Depois de encurtar a letra, abreviei meu programa com o mesmo método e executei o código com eval ().
fonte
Ruby,
741678657627619 bytesEsta é uma expansão de símbolo iterativo. Para cada um dos 28 caracteres da sequência no primeiro argumento para
gsub!
, todas as ocorrências desse caractere_
são substituídas pela seção apropriada da segunda sequência (separada por+
caracteres).fonte
Python, 573 caracteres
Minha
sed
solução não vai mais longe, e foi derrotada por várias pessoas, então fui para uma nova abordagem.Infelizmente, é bom o suficiente para o
2ºlugar (a partir de agora) - Ed H. ainda está muito à minha frente .Notas :
A idéia principal foi emprestada de Ed H. - usando caracteres consecutivos para substituição, em vez de especificá-los em cada regra de substituição.
Minha maneira de lidar com os personagens que existem na música
é diferente da de Ed- simplesmente traduzo cada um para si (e se for sempre seguido por algo, adicione-o também, o que só funcionouW
).O código é gerado por um script que procura boas traduções. No começo, usei um algoritmo ganancioso, que simplesmente pega o que oferece a melhor redução. Então eu descobri que ajustá-lo para preferir cordas mais longas melhora um pouco. Eu acho que ainda não é o ideal.
fonte
Golfscript,
708702699691 bytesfonte
" I'm feeling":i;
?j
, designei três concatenadas para as strings (excluídas{
e}
, mas adicionadas++
para concatenação). Isso me permitiu declarari
inline ao compor o conteúdo dej
.g
e para o coro usando uma única corda com novas linhas e, em seguida,n/g*
g
, pois também é usado no final (realmente possível, mas teria custado mais 1 char no final). No entanto, a abordagem de divisão / dobra para inserir g no início de cada linha é uma ótima economia de caracteres.Java, 858 bytes
Uau. Eu realmente não acho que poderia comprimir isso com força.
UngolfedDe uma forma legível por humanos:fonte
String foo; String bar;
quando estavam jogando golfe.JavaScript,
14281451883 * caracteresDefinitivamente não é a solução mais curta, mas aqui está.
A lógica da solução é bem simples:
* É claro que a solução se torna muito mais curta ao usar linhas únicas em vez de palavras únicas.
fonte