Pensé que este sería un desafío divertido para todos y tengo curiosidad por ver las soluciones que se les ocurren.
Imprimir la letra de "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.
Reglas
- No tiene que preocuparse por la capitalización; todo el texto puede ser insensible a mayúsculas y minúsculas
- Puede ignorar sensatamente cualquier puntuación: los guiones pueden ser espacios, y las comas y los puntos pueden ignorarse
- Debe haber una línea en blanco entre cada verso
- Debe ordenar sus números: " primer día de Navidad", " Cuatro pájaros voladores ", etc.
Respuestas:
Brainfuck - 2,974
Estoy bastante orgulloso de este. Eso suena como un número bastante grande, pero tenga en cuenta que no utilicé ninguna biblioteca de compresión externa, y ninguno de los textos originales está en mi programa en ninguna parte. Ninguna de las otras presentaciones puede decir eso. Todo esto está codificado a mano. Los generadores de texto más ingenuos dan más de 39k para este texto, por lo que diría que esta es una mejora significativa.
Desafortunadamente, esto es aproximadamente 600 caracteres más largo que su propia salida, pero lo que sea. Mantiene los caracteres c, h, m, r, w en una matriz y los usa para imprimir todo el texto. Dos matrices a la derecha de doce espacios cada una registran en qué día estamos para el recuento y qué elementos podemos generar. Es posible que pueda optimizarlo un poco reorganizando el mapa de memoria para colocar los caracteres de impresión entre las dos matrices de conteo para evitar cadenas tan largas de
<<<<<<<
y>>>>>>
, pero eso sería mucho trabajo en este momento. Probablemente también podría elegir algunos mejores caracteres semilla con análisis de frecuencia para minimizar el incremento / decremento, pero lo que sea.Esto depende de que las celdas de ajuste de 8 bits funcionen correctamente.
Sin golf:
fuente
Perl,
438291 caracteresInspirado por el uso de Jeff Burdges de la compresión DEFLATE , el código rubí comprimido de Ventero y el uso de JB de Lingua :: EN :: Numbers , logré comprimir mi entrada a 291 caracteres (bueno, bytes) incluyendo el código de descompresión. Como el programa contiene algunos caracteres no imprimibles, lo he proporcionado en formato MIME Base64 :
Para descodificar el programa, puede usar el siguiente script de Perl auxiliar:
Guarde la salida en un archivo llamado
12days.pl
y ejecúteloperl -M5.01 12days.pl
. Como se señaló, debe tener el módulo Lingua :: EN :: Numbers instalado para que el código funcione.En caso de que se pregunte, la parte legible del código simplemente se ve así:
donde
...
representa 254 bytes de código Perl comprimido RFC 1950 . Sin comprimir, el código tiene 361 caracteres de longitud y se ve así:Escribir este código fue un tipo extraño de ejercicio de golf: resulta que maximizar la repetición y minimizar el número de caracteres distintos utilizados es mucho más importante que minimizar el recuento de caracteres sin procesar cuando la métrica relevante es el tamaño después de la compresión .
Para exprimir los últimos caracteres, escribí un programa simple para probar pequeñas variaciones de este código para encontrar el que mejor se comprime. Para la compresión, utilicé la utilidad KZIP de Ken Silverman , que generalmente produce mejores raciones de compresión (a costa de la velocidad) que el Zlib estándar, incluso con la configuración de compresión máxima. Por supuesto, dado que KZIP solo crea archivos ZIP, luego tuve que extraer el flujo DEFLATE sin procesar del archivo y envolverlo en un encabezado y suma de verificación RFC 1950. Aquí está el código que usé para eso:
Si esto parece un horrible kluge, es porque eso es exactamente lo que es.
Por interés histórico, aquí está mi solución original de 438 caracteres, que genera una salida más agradable, incluidos los saltos de línea y la puntuación:
Lo más destacado de esta versión es el par de expresiones regulares
s/e?t? .*/th/,s/vt/ft/
, que construyen los ordinales para 4 a 12 a partir de los cardenales al comienzo de las líneas de regalo.Este código, por supuesto, también se puede comprimir usando el truco de Zlib descrito anteriormente, pero resulta que simplemente comprimir la salida es más eficiente, produciendo el siguiente programa de 338 bytes (en formato Base64, nuevamente):
También tengo un archivo gzip de 312 bytes de la letra, construido a partir de la misma secuencia DEFLATE. Supongo que podrías llamarlo un "script zcat". :)
fuente
rings
conrGs
al ahorro 2 caracteresG
coning,
, pero resulta que agregar las comas más tarde es realmente más corto. ¡Gracias!$_
en mi actualización a continuación.Lisp común, 333
363Las funciones integradas para formatear ordinales son útiles, pero la mayor parte de la compresión proviene de poder usar la misma lista de argumentos una y otra vez, omitiendo cada vez menos argumentos en cada ejecución.
Según lo demostrado por coredump en los comentarios, las instalaciones integradas todavía se pueden aprovechar para los cardenales.
fuente
(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 es mi primera vez jugando al golf. JavaScript 570
fuente
Python 2.7 (465)
Sin embargo, puse el 'y' en la misma línea que las palomas en lugar de la perdiz.
fuente
Rubí (474)
o en una forma más legible (486):
Alguien tiene una idea de cómo sortear el .reverse? no pude encontrar una solución
fuente
12.times
lugar de(0..11).each
; hacer un solo pone con dos argumentos en lugar de dos pone con un argumento; use la notación% w () para la matriz de días de Navidad. Finalmente, puede deshacerse del reverso invirtiendo la lista, agregando un ^ adicional al final de la cadena y luego usando en[-i..-1]
lugar de [0..i].Perl,
500485Este es mi primer intento, y estoy seguro de que podría hacerse mucho más corto. Los saltos de línea son para facilitar la lectura. Tiene tres conjuntos importantes, uno de los cuales contiene el nombre de cada día
@s
, uno de los cuales enumera todos los regalos (excepto el primero)@a
, y uno que enumera los regalos que ya se han dado@b
. El mecanismo principal es que cada día, imprime@b
y luego transfiere un regalo adicional de@a
a@b
.Gracias a Andrew por 500-> 485
fuente
rings
conr$1s
para guardar 1 char máss
que es parte del nombre de la variable, y la variable$is
no existe. (En realidad son i's en lugar de unos, por cierto)eigth
->eighth
$i
, por ejemplo,$;
para evitar eso. Nadie lo usa$;
para su propósito previsto de todos modos.Vim - 578 pulsaciones de teclas
Decidí probar y jugar vim-golf, ya que este es el tipo de cosas que se pueden jugar vim-golf.
Comience por insertar el marco: la línea "X día de Navidad" un total de 12 veces (89 pulsaciones de teclas):
Luego, realice una serie de macros que insertarán los números del 2 al 12 en los lugares respectivos que deben estar para la letra (172 pulsaciones de teclas):
El "dw" en la segunda línea es deshacerse de la primera "y", porque no va allí.
Luego, realice una serie de sustituciones para la cantidad de cosas que le dio el verdadero amor (319 pulsaciones de teclas):
Y finalmente, reemplazando cada aparición de
X
con un número ordinal:¡Y hemos terminado!
Estoy seguro de que hay otras optimizaciones que me perdí, pero creo que eso es bastante bueno para mí.
fuente
:%s/2/two turtle doves,
C (644)
El recuento no incluye espacios en blanco utilizados para la presentación.
La salida es como:
fuente
Powershell,
487453Gracias a Daan por la idea de dividir una cadena concatenada.
Originalmente había incluido una declaración de cambio para obtener el "y" en la perdiz para todos menos el primer verso. Pero, debido a que la pregunta nos absuelve de la puntuación, simplemente podemos agregar el "y" a las palomas.
Esto da como resultado avances de línea de la siguiente manera:
fuente
Perl,
368389(sin compresión / unicode)Harnesses Lingua :: ES :: Números , aunque no estoy 100% convencido de que sea una buena idea cuando veo el módulo y las longitudes de sus nombres de identificadores. Necesita Perl 5.10 o posterior, ejecute desde la línea de comando con un
-E
interruptor.Editar: mejoras menores: deje de usar una matriz, mejor uso de
$_
espacios en blanco innecesarios.fuente
PowerShell, 440
Esto imprime la letra como se da en la pregunta con varias líneas por verso. Podemos guardar algunos caracteres si ese requisito no está allí.
fuente
C # (528)
fuente
Java, 2062
Sé que esto fue publicado hace un tiempo, pero pensé que lo intentaría. Soy estudiante y todavía soy nuevo en esto, pero parece funcionar.
fuente
Swift, 577
Puedes pegar esto en un patio de recreo.
Intenté mover el
v
comando de impresión y obtuve:fuente
Ruby 1.9.3, comprimido, 321 caracteres
Dado que el código contiene caracteres no imprimibles, en su lugar publicaré un hexdump del código:
Para crear el código real del hexdump, póngalo en un archivo y ejecútelo
xxd -r hexdump > 12days.rb
. Luego, la ejecuciónruby1.9.3 12.days.rb
ejecutará el código e imprimirá la letra. Tenga en cuenta que este código requiere Ruby 1.9.3 (porque usaZlib.inflate
), por lo que no funcionará con Ruby 1.8.x, 1.9.1 y 1.9.2.El código sin comprimir tiene 425 caracteres de longitud:
fuente
Perl, 319/313
Idea: descomprimir y evaluar la solución Lingua :: EN :: Numbers de JB.
Primero, pegue este bloque de texto en el comando
perl -e 'use MIME::Base64; print decode_base64 $_ while <>;' >12days.pl
. Luego, ejecuta el comandoperl -M5.01 12days.pl
.El script en sí toma la forma
use Compress::Zlib;$_='...';eval uncompress$_;
donde...
está la solución 368 char de JB después de ser comprimido con este comando y escapar de a'
.El guión de Ilmari se queja de modificar un valor de solo lectura sin los
$_=...;
caracteres adicionales , pero presumiblemente haría este 313 . Podrías guardar varios bytes más ajustando la compresión manualmente como lo hizo Ilmari antes, tal vez logrando 310 más o menos , pero no me molesté.Perl, 376 (engañando a otra presentación) [mi presentación original]
Primero, cree un script perl llamado que
12days.pl
contenga:A continuación, canalice la salida de cualquier otro envío
12days.txt
y ejecute el comando:Vola
12days.pl
tiene alrededor de 376 bytes e imprime la canción. ;) Divertidamente usando rawinflate mueve exactamente seis bytes del documento de datos al código a partir de la salida de Ilmari.Originalmente me propuse buscar un módulo de codificación de Huffman directamente, que no es tan deshonesto. Sin embargo, lamentablemente CPAN no tiene módulos con la tabla de entropía de letras en inglés, que es lo que realmente desea al comprimir cadenas muy cortas.
Descubrí que
fortune -m Days\ of\ Christmas
tampoco funciona, lamentablemente.fuente
PHP, 548
Longitud reducida con compresión, 502
fuente
VALA,
584, 574No más advertencias en la compilación.
fuente
Java, 608
Primera publicación en Stack Exchange, segundo intento en este problema.
Java es un poco engorroso para tareas como esta, pero el uso de split ayudó a reducir la sobrecarga de String.
fuente
/// , 439 bytes
Pruébalo en línea!
Si se permiten nuevas líneas finales, puede guardar cuatro bytes:
Pruébalo en línea!
Explicación
/// es un lenguaje donde la única operación es una sustitución auto modificable. En particular, la instrucción
/abc/xyz/
reemplaza todas las instancias deabc
conxyz
en el resto del código fuente, incluidas otras sustituciones. Cualquier otro carácter simplemente se envía a STDOUT.Si bien esto es suficiente para completar Turing, el golf en /// generalmente consiste en comenzar con la salida deseada e identificar subcadenas repetidas que se pueden reemplazar con atajos de un solo carácter.
\
se puede usar como un carácter de escape en patrones, reemplazos y caracteres literales para significar un literal/
o\
.La primera instrucción encontrada es
/|/\/\//
. Esto significa "reemplazar todo|
con//
el resto del programa". Esto ahorra un byte para cada sustitución posterior en el programa.Después de esto, se realizan un conjunto de reemplazos para comprimir el texto en sí:
on the
se convierte^
.day of christmas \n my true love gave to me \n
se convierte%
.-a-
se convierte=
.ing
se convierte&
.even
se convierte*
.th%
se convierte+
.^
precedido por dos nuevas líneas (que aparece en cada verso pero el primero) se convierte:
.Después de esto, escribimos la letra ellos mismos. Esto se realiza mediante reemplazos a
A
través deK
. Cada reemplazo de letra agrega una línea al reemplazo después de él. Por ejemplo,K
representaa partridge in a pear tree
yJ
representatwo turtle doves \n and K
.De esta manera, cada verso de la canción se compone de:
^
o:
el*th
)%
A
a travésK
que representa las letras correctas.Sin embargo, debido a que la mayoría de los ordinales terminan en
th
, usamos la sustituciónth%
→+
para guardar algunos bytes.fuente
Hay momentos en que la solución más obvia es también la más corta, es decir, ya no pude resistir este impulso.
Bash en Mac OS X, 26
Perl, 111
Se agregó una nueva línea para facilitar la lectura.
fuente
eval compress
truco para afirmar que encontré una expresión regular que se comprime muy bien, pero que se hinchó alrededor de 200 caracteres. lolJava - 1329 caracteres
Soy demasiado vago para deshacerme de él, pero está aquí: http://ideone.com/MU9IcP .
fuente
SIMPLE , 1 byte
Nota :
El lenguaje fue diseñado después del desafío y todavía es un WIP.
Cómo :
Cualquier char dará salida a los 12 días de Navidad.
fuente