Ecrivez le programme le plus court qui imprime l'intégralité des paroles de "Never Gonna Give You Up" de Rick Astley.
Règles:
- Doit sortir les paroles exactement comme elles apparaissent dans le pastebin * ci-dessus. Voici le dump brut: http://pastebin.com/raw/wwvdjvEj
- Ne pouvez pas compter sur des ressources externes - toutes les paroles doivent être générées par / incorporé dans du code.
- Aucune utilisation des algorithmes de compression existants (par exemple, gzip / bzip2) à moins d’inclure l’algorithme complet dans votre code.
- Utilisez n'importe quelle langue, le code le plus court gagne.
Mise à jour du 1er juin 2012:
pour les solutions contenant du texte non-ASCII, la taille de votre solution sera comptée en octets, en fonction du codage UTF-8. Si vous utilisez des points de code qui ne peuvent pas être codés en UTF-8, votre solution ne sera pas jugée valide.
Mise à jour du 7 juin 2012:
Merci à tous pour vos solutions géniales! J'accepterai la réponse la plus courte demain après-midi. Pour le moment, la réponse GolfScript de Peter Taylor est gagnante, alors n'hésitez pas à faire des améliorations si vous voulez le battre! :)
* Il y a une faute de frappe dans la Pastebin (ligne 46, "savoir" doit être "connu"). Vous pouvez le reproduire ou non, à votre discrétion.
la source
Réponses:
Ruby
576 557556 (552) caractères && PHP 543 caractèresUne autre solution de recherche et remplacement. Notez que cette forme de solution est essentiellement un code de compression basé sur la grammaire http://en.wikipedia.org/wiki/Grammar-based_code Voir http://www.cs.washington.edu/education/courses/csep590a/07au /lectures/lecture05small.pdf pour un exemple de compression simple à comprendre.
J'ai écrit les règles de substitution afin que le caractère de départ de chaque substitution soit calculé (elles sont dans l'ordre ASCII séquentiel); il n'est pas nécessaire qu'il soit présent dans les données de transition.
notes d'implémentation
ancienne mise en œuvre
Cette ancienne implémentation a 576 caractères et a commencé avec les règles de substitution de l'implémentation bash / sed d'ugoren. En ignorant la variable de substitution renommée, mes 28 premières substitutions sont exactement les mêmes que celles effectuées dans le programme de ugoren. J'ai ajouté un peu plus pour réduire le nombre total d'octets. Cela est possible parce que mes règles sont mieux représentées que celles de la mise en œuvre d'Ugoren.
Je n'ai pas essayé d'optimiser les règles de substitution de celui-ci.
notes du concours
Le schéma de décompression par recherche et remplacement fonctionne bien pour ce concours car la plupart des langues ont des routines prédéfinies qui peuvent le faire. Avec une telle quantité de texte à générer, les schémas de décompression complexes ne semblent pas être des gagnants possibles.
J'ai utilisé uniquement du texte ASCII et ai également évité d'utiliser des caractères ASCII non imprimables. Avec ces restrictions, chaque caractère de votre code ne peut représenter qu’un maximum de 6,6 bits d’informations; c'est très différent des techniques de compression réelles où vous utilisez tous les 8 bits. D'une certaine manière, il n'est pas "juste" de comparer la taille de code gzip / bzip2 car ces algorithmes utiliseront les 8 bits. Un algorithme de décompression plus sophistiqué peut être possible si vous pouvez inclure un ASCII traditionnellement non imprimable dans vos chaînes ET que chaque caractère non imprimable est toujours écrit dans votre code sous la forme d'un seul octet.
Solution PHP
La solution ci-dessus prend le PHP d'un "mec triste" et le combine avec mes règles de substitution. La réponse PHP s'avère avoir le code de décompression le plus court. Voir http://ideone.com/XoW5t
la source
sed
solution ne peut sûrement pas la battre. Je travaille sur quelque chose qui, espérons-le, a une chance - vous avez 75 octets de frais généraux, peut-être que je vais le réduire (pas en Ruby).Bash / Sed,
705650588582 caractèresLogique :
L'idée de base est un simple remplacement. Au lieu d'écrire, par exemple,
Never gonna give you up\nNever gonna let you down
j'écrisXgive you up\nXlet you down
et remplace toutX
parNever gonna
.Ceci est réalisé en exécutant
sed
un ensemble de règles, sous la formes/X/Never gonna /g
.Les remplacements peuvent être imbriqués. Par exemple,
Never gonna
est commun, mais il en va de mêmegonna
dans d'autres contextes. Je peux donc utiliser deux règles:s/Y/ gonna/g
ets/X/NeverY/g
.Lors de l'ajout de règles, des parties du texte de la chanson sont remplacées par des caractères uniques, ce qui le rend plus court. Les règles deviennent plus longues, mais si la chaîne remplacée est longue et fréquente, cela en vaut la peine.
L'étape suivante consiste à supprimer la répétition des
sed
commandes elles-mêmes. La séquences/X/something/g
est assez répétitive.Pour le rendre plus court, je modifie les commandes sed pour qu'elles ressemblent
Xsomething
. Ensuite, jesed
convertis cela en unesed
commande normale . Le code lesed 's#.#s/&/#;s#$#/g;#
fait.Le résultat final est une
sed
commande, dont les arguments sont générés par une autresed
commande, entre guillemets.Vous pouvez trouver une explication plus détaillée dans ce lien .
Code:
Remarques:
Le moteur de décompression ne contient que 40 caractères. Les 543 autres sont la table de traduction et le texte compressé.
bzip2
compresse la chanson à 500 octets (sans le moteur, bien sûr), il doit donc y avoir place à amélioration (bien que je ne vois pas comment j'ajouterais un encodage de Huffman ou quelque chose comme ça assez bon marché).<<Q
(ou<<_
) est utilisé pour lire jusqu'à un caractère donné. Mais la fin du script (ou expression de citation inverse) est suffisante. Cela provoque parfois un avertissement.Solution plus ancienne et plus simple, 666 caractères:
la source
\0
par&
.&
il fait 5.Espace blanc - 33115 caractères
StackExchange chomped ma réponse, voici la source: https://gist.github.com/lucaspiller/2852385
Pas génial ... Je pense cependant pouvoir le réduire un peu.
(Si vous ne savez pas ce qu'est l'espace blanc: http://en.wikipedia.org/wiki/Whitespace_(programming_language) )
la source
JavaScript,
590588 octetsDépendant légèrement de la façon dont la chaîne est "imprimée".
https://gist.github.com/2864108
la source
if(g.indexOf(g[i])!=-1)
avante=
de le réparer.with(f.split(g[i]))f=join(pop())
dans lafor..in
boucle enregistre un octetC #
879816789 caractèresPremière tentative de CodeGolf, donc certainement pas un gagnant, à peu près sûr que c'est valide malgré sa méchanceté.
la source
var s1="a";var s2="b";
essayer d'utiliserstring s1="a",s2="b"
; si vous avez 2 déclarations ou plus, c'est plus court.!
et en le retirant de partout ailleurs.Python,
597589 octetsIl est peut-être possible d'extraire deux autres octets:
la source
Brainfuck - 9905
Je suis sûr que je peux aller un peu mieux en le réglant, mais c'est plutôt bien pour le moment. En supposant que cela ne vous pose pas de problème, il est beaucoup plus volumineux que le texte original.
la source
Scala, 613 octets
Il s'agit d'un algorithme de décompression de texte, appliquant de manière récursive la règle
~stuff~ blah ~ ~
à convertirstuff blah stuff stuff
(c'est- à -dire que la première fois que vous voyez une paire de symboles inconnue, il délimite ce qu'il faut copier; vous complétez ensuite la valeur lorsque vous la voyez).Remarque: il peut y avoir un retour de chariot supplémentaire à la fin, en fonction de votre compte. Si cela n'est pas autorisé, vous pouvez supprimer le dernier sur la citation (en enregistrant un caractère) et modifier le fractionnement en
split(" ",-1)
(dépensant 3 caractères), pour 615 octets.la source
N
répétitions de longueurL
, vous utilisez desL+N+1
caractères, tandis que j'utiliseL+N+2
. Mais votre code de décompression est de 102 caractères, alors que le mien en a 40.589, C (seule la fonction de bibliothèque est putchar)
Table de règles de substitution où les caractères compris entre -.._ (45..90) spécifient la règle à appliquer; ainsi, quelque 48 règles (45, c-45> U48 dans le code), les autres caractères doivent être imprimés
les règles sont délimitées par le caractère '&' (38 dans le code, n est décrémenté jusqu'à ce que le zéro et donc s pointe vers la règle correcte)
la règle 0 indique que le caractère suivant doit être mis en majuscule (en définissant k = 32 dans le code), cela libère plus d'espace pour ajouter une plage continue plus étendue de caractères pour les règles
main (..) est appelé avec 1 (conformément à la convention du programme C sans argument), et donc la règle 1 est la règle racine
Evolution du code
rasé encore 9 octets grâce à la suggestion de ugoren
supprime 36 autres octets en créant un tableau de manière algorithmique plutôt que manuellement, et via le "" "
coupé 15 octets supplémentaires en changeant la table d'un caractère * [] en une chaîne unique où '&' délimite des portions
rasé encore 19 octets grâce à plus de conseils de ugoren
rasé 31 octets en ajoutant plus de règles, fait la règle spéciale à capitaliser, permettant ainsi plus d'espace pour les index de règles.
rasé 10 octets grâce à encore plus de conseils de urgoren, et modifier légèrement les règles
la source
*p>>4^3?putchar(*p):e(r[*p-48])
"\'"
traduction n'est pas nécessaire."We're"
est une chaîne valide.ing
est un meilleur candidat.d(int n)
->d(n)
. Changer*s=='~'
en*s-'~' and reverse the
?:, also saving parenthesis around
! N? ..: 0. Using 126 instead of
'~' `est inutile, mais pourquoi~
?main
récursif. L'appel initial est aumain(1)
lieu ded(0)
, mais il peut être traité (peut - être un chef de file~
danss
). En outre, la meilleure alternative~
est un onglet (ascii 9 - un chiffre).Perl,
724714883 octetsAinsi, le changement des règles pénalisant l'utilisation du type Latin-1 a tué ma solution. C'est une approche suffisamment différente pour que je déteste simplement la supprimer, voici donc une version restreinte qui utilise uniquement du code ASCII 7 bits, conformément aux nouvelles règles, avec une augmentation énorme de la taille.
Bien sûr, les caractères de contrôle sont toujours mutilés ici, vous voudrez donc toujours utiliser le codage base64:
Parce que je pense qu'il devrait toujours être visible malgré le fait d'être DQ'd, voici la solution originale:
Le codage base64 du script:
la source
Python
781731605579 caractèresIl y a beaucoup plus de réponses bien meilleures depuis que j'ai vu cela pour la première fois, mais j'ai perdu beaucoup de temps sur mon script en python, alors je vais le poster de toute façon, ce serait génial de voir des suggestions pour le raccourcir davantage,
Edit: grâce aux suggestions de Ed H, 2 caractères hachés, pour aller plus loin, je pourrais devoir restructurer beaucoup de choses ici, ce qui va prendre un certain temps
Après la première fois que je produisais manuellement la chaîne (très fastidieux), j’ai écrit une fonction permettant de trouver récursivement le motif le plus rentable (à cette étape-là), ce qui m’a apporté une solution, mais il a été 10 fois plus grand. caractères.
Donc, j'ai rendu mon algorithme un peu moins gourmand en au lieu de faire le classement final uniquement sur les "caractères réduits", le classement sur une fonction de "caractères réduits", "longueur du motif" et "nombre de motifs"
longueur du motif = longueur compte = compte
Ensuite, j'ai demandé à mon pauvre ordinateur portable de fonctionner indéfiniment, d'assigner des valeurs aléatoires à
lengthWeight
et d'countWeight
obtenir différentes tailles de compression finale, puis de stocker les données pour les tailles de compression minimales dans un fichier.En une demi-heure environ, la chaîne ci-dessus est apparue (j'ai essayé de la bricoler davantage pour voir si je pouvais raccourcir le code), et ça ne va pas aller plus bas, je suppose que quelque chose me manque ici.
voici mon code pour cela, aussi
max_pattern
est très lent (Note: le code crache une chaîne similaire à celle de la forme dans ma version précédente de la solution, je l'ai travaillée manuellement pour obtenir la forme actuelle, manuellement, je veux dire, manuellement dans un shell Python)la source
\n
coûterait 5 caractères et économiser 9. 2. Espace supplémentaire dansin (g,l..)
. 3.join(..)
fonctionne aussi bien quejoin([..])
(au moins dans 2.7).Malbolge, 12735 octets
Essayez-le en ligne.
Généré en utilisant les outils ici.
la source
JavaScript 666 octets
Inspiré par la solution de tkazec .
Découvrez le blog que j'ai écrit à ce sujet, il contient toutes les sources et explique comment j'ai construit ce code.
Vous pouvez copier et coller le code dans la console de votre navigateur. Ou essayez-le sur http://jsfiddle.net/eikes/Sws4g/1/
la source
Perl,
584578577576575571564554553540Cette solution suit la même approche de base que la plupart des autres: en fonction d'une chaîne initiale, effectuez des substitutions répétées de parties répétées du texte.
Les règles de substitution sont spécifiées par un seul caractère, de préférence ne figurant pas dans le texte de sortie. Ainsi, une règle de longueur L et apparaissant N fois économisera environ N * LNL-1 (N * L est la longueur d'origine de toutes les occurrences, mais le caractère de substitution apparaît N fois et le texte littéral a lui-même une longueur L; les règles sont séparées par un caractère de séparation.) Si les caractères de substitution sont spécifiés explicitement, les économies sont réduites à N * LNL-2. Étant donné que la plupart des langues peuvent calculer un caractère avec chr () ou un code court similaire, la première approche tend à être supérieure.
Il existe certains inconvénients au calcul du caractère de substitution, le plus important étant la nécessité d’une plage continue de caractères ASCII. La sortie utilise principalement des lettres minuscules, mais il y a suffisamment de lettres majuscules et de ponctuation pour exiger le remplacement d'un caractère par lui-même, le remappage de quelques caractères dans une étape de correction ultérieure ou l'ordre des règles de sorte que les remplacements avec des caractères problématiques se produisent plus tôt. L'utilisation d'un langage qui remplace l'utilisation de regex signifie également qu'il existe des pièges à caractères ayant une signification spéciale dans une regex:
.
+
*
\
?
Mon approche initiale avait 63 octets dans le décodeur et 521 dans les règles. J'ai passé beaucoup de temps à optimiser les règles, ce qui peut être délicat, en particulier avec les règles courtes car elles peuvent se chevaucher. J'ai décodé à 55 octets et les règles à 485 en trompant un peu la formule. Normalement, une règle à 2 caractères qui apparaît 3 fois ou une règle à 3 caractères deux fois ne sauvegarde pas de longueur, mais une faille - qui permet également de composer des mots qui ne font pas partie de la sortie; - ).
J'utilise des caractères de contrôle dans cette solution, la solution est donc fournie ici en base64.
Et voici une version légèrement plus lisible (mais moins exécutable).
Cependant, je soupçonne que ce n'est toujours pas le minimum, comme Ed H. fait remarquer que le décodage php est le plus court à 44 octets et que des améliorations sont possibles dans les règles qu'il utilise. J'ai un décodeur 52 octets en Perl, mais je ne pouvais pas l'utiliser pour cette solution car je devais parcourir la plage en sens inverse.
la source
PHP
730707 caractèresla source
$s="Never gonna give...
peut être raccourci avec$n
.Perl -
589 588 583 579576 octetsChaque règle consiste en une tête de 1 caractère, un corps et un trait de soulignement. Tant que les règles peuvent être coupées du début, la tête de la règle est remplacée par son corps dans le reste du texte. La tête de la première règle est donnée, les têtes de toutes les règles suivantes sont générées à partir de la variable $ i.
Etant donné que la tête de la règle suivante est placée au début du texte par la règle précédente, la dernière règle crée un caractère qui ne sera plus supprimé. Je devais choisir une plage de noms dont le dernier serait "W", afin de pouvoir supprimer le "W" original du début des paroles et de le remplacer par la substitution de règle.
L'encodage a été effectué par un script Python utilisant un simple algorithme de hillclimbing.
Voici le code Perl:
(Je trouve remarquable que le texte compressé contienne "hearBach": D)
Et voici le code Python qui le génère:
la source
while
pour la boucle; Cela vous permet de renoncer aux accolades et aux parenthèses. Une autre idée: déterminer comment utilisersay
au lieu deprint
faire la sortie.Python 2.7,
975803 octetsPas le plus grand - je souhaite (maintenant) que Python réalise des extensions de formatage similaires. Hélas ce n'est pas le cas.
Éditer: Expansion simulée avec une autre syntaxe de mise en forme (en quelque sorte ..)
la source
Clojure
720 octets / caractères:
(Reproduit ici avec des espaces supplémentaires pour que vous puissiez voir la mise en forme)
la source
C # - 605 caractères | T-SQL - 795 caractères | C # - 732 caractères | C # - 659 caractères
L'inspiration pour cela est venue de l'exemple sed. La seule modification majeure que j'ai apportée consiste à rendre les recherches consécutives en caractères ASCII, de sorte qu'elles ne doivent pas être déclarées. Malheureusement, c'est C #, donc je ne sais pas comment le rendre plus petit. J'ai pris le même texte de remplacement et ai fait le code dans T-SQL en utilisant une table temporaire.
T-SQL
C # - Deuxième essai Il s’agissait d’une approche différente. La compression a été entièrement réalisée par l'ordinateur à la recherche des meilleurs remplaçants. Les recherches sont séquentielles et classées par taille. Aucune recherche délimitée n’est donc nécessaire. Toutefois, le code utilisé pour effectuer les recherches a été moins efficace que je ne le pensais. Il a donc coûté 127 caractères supplémentaires au total! Vivre et apprendre.
3ème essai en C #. Cette fois, j'ai expiré avec les caractères \ b, \ r, \ t. Vous pouvez utiliser \ rN \ n pour remplacer le premier caractère de la ligne par un N majuscule, mais cela n’a pas pour autant sauvegardé les caractères. J'ai créé des alias \ b pour déplacer le curseur en arrière, puis écrire sur le texte existant. Mais rien de tout cela ne permettait de gagner de la place et à la fin, j'étais encore pire qu'une simple stratégie de recherche et de remplacement.
la source
REPLACE
approche intelligente , en particulier avec le SQL dynamique, mais il existe de nombreuses façons de jouer au golf: utilisez@
la variable au lieu de@s
, créez une table permanente aut
lieu de#t
(vous n'avez pas à nettoyer après vous-même), débarrassez-vous de l'instruction COLLATE à 29 caractères et exigez simplement qu'elle soit exécutée sur un serveur / une base de données avec la collation, l'utilisationvarchar(999)
ou desvarchar(max)
tonnes d'espace blanc inutile autour des signes égaux et des virgules, etc.PHP,
591585568564 octetsla source
Ruby, 1014 octets
Je suis juste en train d'apprendre la programmation, donc je ne vais pas battre un record ici. Mais c'était une tâche amusante.
la source
GolfScript (511 octets)
Ceci utilise un changement de base pour regrouper les bits, ainsi il inclut des caractères qui ne sont pas en ASCII. Cependant, il n'est pas approprié de marquer ces caractères avec leur codage UTF-8 car l'interpréteur considère le programme comme ISO-8859-1. Pour cette raison, j'ai spécifié la longueur en octets plutôt qu'en caractères.
Encodé en base 64:
Décharge Hex (sortie de
xxd
):Comme la plupart des meilleures solutions, cela utilise une approche basée sur la grammaire avec des divisions et des jointures de chaînes pour développer la grammaire. La grammaire a 30 règles et a été trouvée par une recherche gourmande.
la source
JavaScript, 854 caractères (nouvelles lignes ajoutées pour "lisibilité")
la source
Naive sh / echo - 810 octets
la source
JavaScript 789 caractères
Mon javascript (imprime avec "document.write ()"):
Je modifie des mots et des phrases usuels avec des lettres cyriliques, puis les remonte avec la fonction replace ().
Après avoir raccourci les paroles, j'ai raccourci mon programme avec la même méthode et exécuté le code avec eval ().
la source
Ruby,
741678657627619 octetsCeci est une expansion de symbole itérative. Pour chacun des 28 caractères de la chaîne dans le premier argument de
gsub!
, toutes les occurrences de ce caractère_
sont remplacées par la section appropriée de la deuxième chaîne (séparées par des+
caractères).la source
Python, 573 caractères
Ma
sed
solution ne va pas plus loin, elle a été battue par plusieurs personnes, alors je suis parti pour une nouvelle approche.Malheureusement, cela ne suffit que pour la
2ème3ème place (pour l'instant) - Ed H. a encore beaucoup d'avance sur moi .Notes :
L'idée principale a été empruntée à Ed H. - utiliser des caractères consécutifs pour le remplacement, au lieu de les spécifier dans chaque règle de remplacement.
Ma façon de traiter les personnages qui existent dans la chanson
est différente de celle d'Ed- je m'assure simplement de traduire chacun d'eux (et si elle est toujours suivie de quelque chose, ajoutez-la également, ce qui n'a fonctionné que pourW
).Le code est généré par un script qui recherche de bonnes traductions. Au début, j'ai utilisé un algorithme glouton, qui prend simplement celui qui donne la meilleure réduction. Ensuite, j'ai constaté que le modifier pour qu'il préfère les chaînes plus longues l'améliore quelque peu. Je suppose que ce n'est toujours pas optimal.
la source
Golfscript,
708702699691 octetsla source
" I'm feeling":i;
?j
, j’ai assigné trois chaînes concaténées (supprimées{
et}
, mais ajoutées++
pour la concaténation). Cela m'a permis de déclareri
inline, lors de la composition du contenu dej
.g
et pour le choeur en utilisant une seule chaîne avec des nouvelles lignes, puisn/g*
g
car il est également utilisé vers la fin (en fait, mais aurait coûté 1 caractère en plus). Cependant, l’approche split / fold pour insérer g au début de chaque ligne est un excellent économiseur de caractères.Java, 858 octets
Sensationnel. Je ne pensais pas vraiment pouvoir compresser si fort.
UngolfedSous une forme lisible par l'homme:la source
String foo; String bar;
quand je ne faisais pas de golf.JavaScript,
14281451883 * caractèresCe n'est certainement pas la solution la plus courte, mais voilà.
La logique de la solution est assez simple:
* Bien sûr, la solution devient beaucoup plus courte lorsque vous prenez des lignes uniques au lieu de mots uniques.
la source