Eu pensei que este seria um desafio divertido para todos e estou curioso para ver as soluções que as pessoas apresentam.
Imprimir a letra "12 Days Of Christmas"
On the first day of Christmas,
my true love gave to me,
A partridge in a pear tree.
On the second day of Christmas,
my true love gave to me,
Two turtle doves,
And a partridge in a pear tree.
...
On the twelfth day of Christmas,
My true love gave to me,
Twelve drummers drumming,
Eleven pipers piping,
Ten lords-a-leaping,
Nine ladies dancing,
Eight maids-a-milking,
Seven swans-a-swimming,
Six geese-a-laying,
Five golden rings,
Four calling birds,
Three french hens,
Two turtle doves,
And a partridge in a pear tree.
Regras
- Você não precisa se preocupar com capitalização; todo o texto não diferencia maiúsculas de minúsculas
- Você pode ignorar sensivelmente qualquer pontuação: hífens podem ser espaços e vírgulas e pontos podem ser ignorados
- Deve haver uma linha em branco entre cada verso
- Você deve ordenar seus números: " primeiro dia de Natal", " quatro pássaros cantando", etc.
Respostas:
Brainfuck - 2.974
Estou bastante orgulhoso deste. Isso soa como um número bastante grande, mas lembre-se de que eu não usei nenhuma biblioteca de compactação externa e nenhum texto original está no meu programa em lugar algum. Nenhuma das outras submissões pode dizer isso. Tudo isso é codificado manualmente. Geradores de texto mais ingênuos dão mais de 39 mil para este texto, então eu diria que essa é uma melhoria significativa.
Infelizmente, isso tem cerca de 600 caracteres a mais que sua própria saída, mas tanto faz. Ele mantém os caracteres c, h, m, r, w em uma matriz e usa isso para imprimir todo o texto. Duas matrizes à direita de doze espaços controlam cada dia em que estamos contando e para quais itens podemos produzir. Talvez eu consiga otimizá-lo um pouco, reorganizando o mapa de memória para colocar os caracteres de impressão entre as duas matrizes de contagem para evitar cadeias tão longas de
<<<<<<<
e>>>>>>
, mas isso daria muito trabalho nesse momento. Eu também poderia provavelmente escolher alguns caracteres iniciais melhores com análise de frequência para minimizar o incremento / decremento, mas tanto faz.Isso depende das células de quebra automática de 8 bits para funcionar corretamente.
Ungolfed:
fonte
Perl,
438291caracteresInspirado pelo uso da compactação DEFLATE por Jeff Burdges , pelo código Ruby compactado do Ventero e pelo uso de Lingua :: EN :: Numbers pela JB , consegui compactar minha entrada para 291 caracteres (bem, bytes), incluindo o código de descompressão. Como o programa contém alguns caracteres não imprimíveis, eu o forneci no formato MIME Base64 :
Para descriptografar o programa, você pode usar o seguinte script auxiliar Perl:
Salve a saída em um arquivo nomeado
12days.pl
e execute-o comperl -M5.01 12days.pl
. Como observado, você precisa ter o módulo Lingua :: EN :: Numbers instalado para que o código funcione.Caso você esteja se perguntando, a parte legível do código simplesmente se parece com isso:
onde
...
significa 254 bytes de RFC 1950 compactado código Perl. Descompactado, o código tem 361 caracteres e fica assim:Escrever esse código era um tipo estranho de exercício de golfe: a repetição maximizada e a minimização do número de caracteres distintos usados são muito mais importantes do que minimizar a contagem bruta de caracteres quando a métrica relevante é o tamanho após a compactação .
Para extrair os últimos caracteres, escrevi um programa simples para tentar pequenas variações desse código e encontrar o que comprime melhor. Para compactação, usei o utilitário KZIP de Ken Silverman , que normalmente produz melhores rações de compactação (ao custo da velocidade) do que o Zlib padrão, mesmo nas configurações de compactação máxima. Obviamente, como o KZIP cria apenas arquivos ZIP, tive que extrair o fluxo DEFLATE bruto do arquivo e envolvê-lo em um cabeçalho e soma de verificação RFC 1950. Aqui está o código que usei para isso:
Se isso parece um kluge horrível, é porque é exatamente o que é.
Para interesse histórico, aqui está minha solução original de 438 caracteres, que gera uma saída melhor, incluindo quebras de linha e pontuação:
Destaques desta versão o par de regexps
s/e?t? .*/th/,s/vt/ft/
, que constroem os ordinais de 4 a 12 a partir dos cardeais no início das linhas de presentes.Obviamente, esse código também pode ser compactado usando o truque Zlib descrito acima, mas acontece que simplesmente compactar a saída é mais eficiente, produzindo o seguinte programa de 338 bytes (no formato Base64, novamente):
Eu também tenho um arquivo gzip de 312 bytes da letra, construído a partir do mesmo fluxo DEFLATE. Suponho que você possa chamá-lo de "script zcat". :)
fonte
rings
porrGs
para salvar 2 caracteresG
poring,
, mas acontece que adicionar vírgulas mais tarde é realmente mais curto. Obrigado!$_
na minha atualização abaixo.Lisp comum, 333
363As facilidades internas para formatar ordinais são úteis, mas a maior parte da compactação vem do fato de poder usar a mesma lista de argumentos repetidamente, ignorando cada vez menos argumentos a cada execução.
Conforme comprovado pelo coredump nos comentários, as instalações internas ainda podem ser bem utilizadas pelos cardeais.
fonte
(dotimes(n 12)(format t"on-the-~:R-day-of-christmas my-true-love-gave-to-me ~v*~@{~R-~A ~#[AND-~]~}A-PARTRIDGE-IN-A-PEAR-TREE "(1+ n)(- 22 n n)12'drummers-drumming 11'pipers-piping 10'lords-a-leaping 9'ladies-dancing 8'maids-a-milking 7'swans-a-swimming 6'geese-a-laying 5'golden-rings 4'calling-birds 3'french-hens 2'turtle-doves))
JavaScript 570
Esta é a minha primeira vez jogando golfe. JavaScript 570
fonte
Python 2.7 (465)
No entanto, coloquei o 'e' na mesma linha das pombas, em vez da perdiz.
fonte
Rubi (474)
ou de uma forma mais legível (486):
alguém teve uma idéia de como contornar o reverso? não consegui encontrar uma solução
fonte
12.times
vez de(0..11).each
; faça um único put com dois argumentos em vez de dois put com um argumento; use a notação% w () para a matriz dos dias do Natal. Finalmente, você pode se livrar do reverso invertendo a lista, adicionando um ^ extra ao final da string e usando em[-i..-1]
vez de [0..i].Perl,
500485Esta é a minha primeira tentativa e tenho certeza de que poderia ser muito mais curta. As quebras de linha são para facilitar a leitura. Possui três matrizes importantes, uma das quais contém o nome para cada dia
@s
, uma das quais lista todos os presentes (exceto o primeiro)@a
e uma que lista os presentes que já foram dados@b
. O principal mecanismo é que, a cada dia, ele imprime@b
e depois transfere um presente adicional de@a
para@b
.Agradecimentos a Andrew por 500-> 485
fonte
rings
porr$1s
para economizar mais 1 chars
como parte do nome da variável e a variável$is
não existe. (Na verdade, são i em vez de uns, btw)eigth
->eighth
$i
, por exemplo,$;
para contornar isso. Ninguém nunca usa$;
para o propósito a que se destina.Vim - 578 pressionamentos de tecla
Decidi tentar vim-golf isso, pois esse é o tipo de coisa que pode ser vim-golfed.
Comece inserindo a estrutura - a linha "X day of Christmas" um total de 12 vezes (89 pressionamentos de teclas):
Em seguida, execute uma série de macros que inserirão os números 2 a 12 nos respectivos locais em que precisam estar para a letra (172 pressionamentos de teclas):
O "dw" na segunda linha é livrar-se do primeiro "e", porque não vai para lá.
Em seguida, faça uma série de substituições pelo número de coisas que o amor verdadeiro deu (319 pressionamentos de tecla):
E, finalmente, substituindo cada ocorrência de
X
por um número ordinal:E nós terminamos!
Tenho certeza de que houve outras otimizações que eu perdi, mas acho que é muito bom mesmo.
fonte
:%s/2/two turtle doves,
C (644)
Contagem não inclui espaços em branco usados para apresentação.
A saída é como:
fonte
Powershell,
487453Obrigado a Daan pela idéia de dividir uma string concatenada.
Originalmente, eu incluí uma declaração de mudança para colocar o "e" na perdiz para todos, exceto o primeiro verso. Mas, como a pergunta nos absolve da pontuação, podemos simplesmente acrescentar o "e" às pombas.
Isso resulta em feeds de linha da seguinte maneira:
fonte
Perl, 368
389(sem unicode / compactação)Aproveita Lingua :: PT :: Números , embora eu não esteja 100% convencido de que é uma boa ideia quando vejo os comprimentos dos nomes dos módulos e identificadores. Precisa do Perl 5.10 ou posterior, execute a partir da linha de comando com um
-E
switch.Editar: pequenas melhorias: pare de usar uma matriz, use melhor o
$_
espaço em branco desnecessário.fonte
PowerShell, 440
Isso imprime a letra como indicado na pergunta com várias linhas por verso. Podemos salvar alguns caracteres se esse requisito não existir.
fonte
C # (528)
fonte
Java, 2062
Sei que isso foi publicado há um tempo, mas pensei em tentar. Eu sou um estudante e ainda sou novo nisso, mas parece funcionar.
fonte
Swift, 577
Você pode colar isso em um playground.
Tentei mover o
v
comando de impressão e obtive:fonte
Ruby 1.9.3, compactado, 321 caracteres
Como o código contém caracteres não imprimíveis, postarei um hexdump do código:
Para criar o código real do hexdump, coloque-o em um arquivo e execute
xxd -r hexdump > 12days.rb
. A execuçãoruby1.9.3 12.days.rb
executará o código e imprimirá a letra. Observe que esse código requer o Ruby 1.9.3 (porque usaZlib.inflate
), portanto, não funcionará com o Ruby 1.8.x, 1.9.1 e 1.9.2.O código não compactado tem 425 caracteres:
fonte
Perl, 319/313
Idéia: Descompacte e avalie a solução Lingua :: EN :: Numbers da JB.
Primeiro, cole este bloco de texto no comando
perl -e 'use MIME::Base64; print decode_base64 $_ while <>;' >12days.pl
. Em seguida, execute o comandoperl -M5.01 12days.pl
.O script em si assume o formato
use Compress::Zlib;$_='...';eval uncompress$_;
onde...
está a solução 368 char do JB após ser compactado com este comando e escapar de a'
.O script de Ilmari reclama sobre a modificação de um valor somente leitura sem os
$_=...;
caracteres extras , mas presumivelmente ele faria isso 313 . Você pode economizar mais alguns bytes ajustando a compactação manualmente, como o Ilmari fez antes, talvez atingindo 310 ou mais , mas eu não me incomodei.Perl, 376 (trapaceando outra finalização) [meu envio original]
Primeiro, crie um script perl chamado
12days.pl
contendo:Em seguida, canalize a saída de qualquer outra submissão
12days.txt
e execute o comando:O Vola
12days.pl
tem cerca de 376 bytes e imprime a música. ;) O uso divertido de rawinflate move precisamente seis bytes do documento de dados para o código a partir da saída de Ilmari.Originalmente, comecei a procurar diretamente um módulo de codificação Huffman, o que não é tão desonesto. No entanto, infelizmente o CPAN não possui módulos com a tabela de entropia de letras em inglês, que é o que você realmente deseja ao compactar strings muito curtas.
Descobri que
fortune -m Days\ of\ Christmas
isso também não funciona, infelizmente.fonte
PHP, 548
Comprimento reduzido com compressão, 502
fonte
VALA,
584, 574Não há mais aviso na compilação.
fonte
Java, 608
Primeiro post no Stack Exchange, segunda tentativa neste problema.
Java é um pouco complicado para tarefas como essa, mas o uso da divisão ajudou a reduzir a sobrecarga da String.
fonte
/// , 439 bytes
Experimente online!
Se novas linhas à direita forem permitidas, você poderá salvar quatro bytes:
Experimente online!
Explicação
/// é uma linguagem em que a única operação é uma substituição auto-modificável. Em particular, a instrução
/abc/xyz/
substitui todas as instâncias deabc
comxyz
no restante do código-fonte, incluindo outras substituições. Quaisquer outros caracteres são simplesmente enviados para STDOUT.Embora isso seja suficiente para a conclusão de Turing, o golfe em /// geralmente consiste em começar com a saída pretendida e identificar substrings repetidos que podem ser substituídos por atalhos de caractere único.
\
pode ser usado como um caractere de escape em padrões, substituições e caracteres literais para significar um literal/
ou\
.A primeira instrução encontrada é
/|/\/\//
. Isso significa "substituir tudo|
por//
no restante do programa". Isso economiza um byte para todas as substituições subseqüentes no programa.Depois disso, um conjunto de substituições é feito para compactar o próprio texto:
on the
torna-se^
.day of christmas \n my true love gave to me \n
torna-se%
.-a-
torna-se=
.ing
torna-se&
.even
torna-se*
.th%
torna-se+
.^
precedido por duas novas linhas (que aparecem em todos os versículos, mas o primeiro) se torna:
.Depois disso, escrevemos as letras em si. Isso é feito usando substituições
A
atravésK
. Cada substituição de letra adiciona uma linha à substituição após ela. Por exemplo,K
representaa partridge in a pear tree
eJ
representatwo turtle doves \n and K
.Dessa maneira, cada verso da música é composto de:
^
ou:
el*th
)%
A
através deK
que representa as letras corretas.No entanto, como a maioria dos ordinais termina em
th
, usamos a substituiçãoth%
→+
para salvar alguns bytes.fonte
Há momentos em que a solução mais óbvia também é a mais curta, ou seja, eu não conseguia mais resistir a esse desejo.
Bash no Mac OS X, 26
Perl, 111
Uma nova linha adicionada para facilitar a leitura.
fonte
eval compress
truque para afirmar que encontrei um regex que se comprime muito bem, mas que contém cerca de 200 caracteres. lolJava - 1329 caracteres
Estou com preguiça de desfazer isso, mas está aqui: http://ideone.com/MU9IcP .
fonte
SIMPLES , 1 byte
Nota :
O idioma foi desenvolvido após o desafio e ainda é um WIP.
Quão :
Qualquer caractere produzirá os 12 dias do Natal.
fonte