Pomyślałem, że będzie to zabawne wyzwanie dla wszystkich i jestem ciekawy, jakie rozwiązania wymyślają ludzie.
Wydrukuj tekst piosenki „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.
Zasady
- Nie musisz się martwić o wielkie litery; cały tekst może nie uwzględniać wielkości liter
- Można rozsądnie zignorować wszelkie znaki interpunkcyjne: łączniki mogą być spacjami, a przecinki i kropki można zignorować
- Między wierszami powinna znajdować się pusta linia
- Musisz uporządkować swoje liczby: „ pierwszy dzień świąt”, „ cztery ptaki wzywające” itp
Odpowiedzi:
Brainfuck - 2974
Jestem z tego dość dumny. To brzmi jak całkiem spora liczba, ale należy pamiętać, że nie użyłem żadnych zewnętrznych bibliotek kompresji i nigdzie nie ma oryginalnego tekstu w moim programie. Żaden z pozostałych wniosków nie może tego powiedzieć. To wszystko jest ręcznie kodowane. Bardziej naiwne generatory tekstu dają ponad 39 000 dla tego tekstu, więc powiedziałbym, że jest to znaczna poprawa.
Niestety jest to około 600 znaków dłuższych niż jego własne wyjście, ale cokolwiek. Utrzymuje znaki c, h, m, r, w tablicy i używa go do wydrukowania całego tekstu. Dwie tablice po prawej stronie dwunastu pól, każda z nich śledzi, w którym dniu liczymy, i dla których przedmiotów możemy wydać. Być może uda mi się go trochę zoptymalizować, reorganizując mapę pamięci, aby wprowadzić znaki drukujące między dwiema tablicami liczącymi, aby uniknąć takich długich łańcuchów
<<<<<<<
i>>>>>>
, ale w tym momencie byłoby to dużo pracy. Prawdopodobnie mógłbym również wybrać lepsze znaki początkowe z analizą częstotliwości, aby zminimalizować zwiększanie / zmniejszanie, ale cokolwiek.Zależy to od prawidłowego działania 8-bitowych komórek zawijających.
Nie golfowany:
źródło
Perl,
438291 znakówZainspirowany użytku Jeff Burdges męska kompresji DEFLATE , skompresowanego kodu Ventero za Ruby i użytkowania JB dnia Lingua :: PL :: Liczb , udało mi się ściskać moją pozycję w dół do 291 znaków (dobrze, bajty) włącznie z kodem dekompresji. Ponieważ program zawiera niektóre niedrukowalne znaki, podałem go w formacie MIME Base64 :
Aby odkodować program, możesz użyć następującego skryptu Perl pomocnika:
Zapisz wynik w pliku o nazwie
12days.pl
i uruchom goperl -M5.01 12days.pl
. Jak wspomniano, aby kod działał , musisz mieć zainstalowany moduł Lingua :: EN :: Numbers .Jeśli się zastanawiasz, czytelna część kodu wygląda tak:
gdzie
...
oznacza 254 bajty RFC 1950 skompresowanego kodu Perl . Kod nieskompresowany ma 361 znaków i wygląda następująco:Pisanie tego kodu było dziwnym rodzajem ćwiczenia w golfa: okazuje się, że maksymalizowanie powtórzeń i minimalizowanie liczby użytych znaków są o wiele ważniejsze niż minimalizowanie liczby znaków surowych, gdy odpowiednią miarą jest rozmiar po kompresji .
Aby wycisnąć kilka ostatnich znaków, napisałem prosty program, aby wypróbować małe odmiany tego kodu, aby znaleźć ten, który najlepiej się kompresuje. Do kompresji użyłem narzędzia KZIP Kena Silvermana , które zwykle daje lepsze racje kompresji (kosztem prędkości) niż standardowe Zlib, nawet przy maksymalnych ustawieniach kompresji. Oczywiście, ponieważ KZIP tworzy tylko archiwa ZIP, musiałem wyodrębnić surowy strumień DEFLATE z archiwum i zawinąć go w nagłówek RFC 1950 i sumę kontrolną. Oto kod, którego użyłem do tego:
Jeśli to wygląda jak okropny kluge, to dlatego, że właśnie tak jest.
Dla historycznego zainteresowania, oto moje oryginalne rozwiązanie 438-char, które generuje ładniejsze wyjście, w tym podział wierszy i interpunkcję:
Najważniejsze w tej wersji para wyrażeń regularnych
s/e?t? .*/th/,s/vt/ft/
, które konstruują liczby porządkowe dla 4 do 12 z kardynałów na początku linii prezentu.Ten kod można oczywiście również skompresować przy użyciu sztuczki Zlib opisanej powyżej, ale okazuje się, że po prostu kompresja danych wyjściowych jest bardziej wydajna, co daje następujący 338-bajtowy program (ponownie w formacie Base64):
Mam również 312-bajtowe archiwum gzip tekstów, zbudowane z tego samego strumienia DEFLATE. Przypuszczam, że można to nazwać „skryptem Zcat”. :)
źródło
rings
wrGs
celu oszczędzania 2 znakiG
zing,
, ale okazuje się, że dodawanie przecinków później rzeczywiście jest krótszy. Dzięki!$_
w mojej aktualizacji poniżej.Common Lisp, 333
363Wbudowane funkcje formatowania rzędnych są pomocne, ale większość kompresji wynika z możliwości ciągłego korzystania z tej samej listy argumentów, pomijając coraz mniej argumentów przy każdym uruchomieniu.
Jak udowodniono w rdzeniu w komentarzach, wbudowane urządzenia mogą być nadal dobrze wykorzystywane przez kardynałów.
źródło
(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
To mój pierwszy raz w golfa. JavaScript 570
źródło
Python 2.7 (465)
Jednak umieszczam „i” na tej samej linii co gołębie zamiast kuropatwy.
źródło
Rubin (474)
lub w bardziej czytelnej formie (486):
ktoś wpadł na pomysł, jak obejść rewers? nie mogłem znaleźć rozwiązania
źródło
12.times
zamiast(0..11).each
; wykonaj pojedynczy put z dwoma argumentami zamiast dwóch putów z jednym argumentem; użyj notacji% w () dla tablicy dni świątecznych. Wreszcie możesz pozbyć się rewersu, odwracając listę, dodając dodatkowe ^ na końcu łańcucha, a następnie używając[-i..-1]
zamiast [0..i].Perl,
500485To moja pierwsza próba i jestem pewien, że można by ją znacznie skrócić. Podziały linii służą do czytelności. Ma trzy ważne tablice, z których jedna zawiera nazwę na każdy dzień
@s
, z których jedna zawiera listę wszystkich prezentów (z wyjątkiem pierwszej)@a
, a druga zawiera listę prezentów, które zostały już przekazane@b
. Głównym mechanizmem jest to, że każdego dnia drukuje,@b
a następnie przesyła jeden dodatkowy prezent od@a
do@b
.Podziękowania dla Andrew za 500-> 485
źródło
rings
zr$1s
zaoszczędzić 1 więcej chars
jako część nazwy zmiennej, a zmienna$is
nie istnieje. (Tak naprawdę to ja zamiast nich, btw)eigth
->eighth
$i
, powiedzmy,$;
obejść to.$;
Zresztą i tak nikt nigdy nie korzysta z tego celu.Vim - 578 naciśnięć klawiszy
Postanowiłem spróbować grać w golfa vim, ponieważ jest to coś, co można grać w golfa vim.
Zacznij od wstawienia frameworka - linia „X dzień świąt Bożego Narodzenia” łącznie 12 razy (89 naciśnięć klawiszy):
Następnie wykonaj serię makr, które wstawią cyfry od 2 do 12 w odpowiednich miejscach, w których powinny znajdować się teksty (172 naciśnięcia klawiszy):
„Dw” w drugiej linii ma pozbyć się pierwszego „i”, ponieważ tam nie idzie.
Następnie wykonaj serię zamian za liczbę rzeczy, które dała prawdziwa miłość (319 naciśnięć klawiszy):
I na koniec, zastępując każde wystąpienie
X
liczbą porządkową:I skończone!
Jestem pewien, że istnieją inne optymalizacje, które przegapiłem, ale myślę, że to całkiem niezłe.
źródło
:%s/2/two turtle doves,
C (644)
Liczba nie obejmuje białych znaków używanych do prezentacji.
Wyjście jest jak:
źródło
PowerShell,
487453Dziękuję Daanowi za pomysł podzielenia połączonego łańcucha.
Pierwotnie zawarłem zdanie przełączające, aby uzyskać „i” na kuropatwie dla wszystkich wierszy oprócz pierwszego. Ponieważ jednak pytanie uwalnia nas od interpunkcji, możemy po prostu dołączyć „i” do gołębi.
Powoduje to następujące informacje:
źródło
Perl, 368
389(bez Unicode / kompresji)Uprzęże Lingua :: EN :: Numbers , choć nie jestem w 100% przekonany, że to dobry pomysł, kiedy widzę długości nazw modułów i ich identyfikatorów. Wymaga Perla 5.10 lub nowszego, uruchom z wiersza poleceń za pomocą
-E
przełącznika.Edycja: drobne ulepszenia: przestań używać tablicy, lepsze wykorzystanie
$_
, niepotrzebne białe znaki.źródło
PowerShell, 440
To drukuje słowa podane w pytaniu z wieloma liniami na wiersz. Możemy zapisać kilka znaków, jeśli nie ma takiego wymagania.
źródło
C # (528)
źródło
Java, 2062
Wiem, że to zostało opublikowane jakiś czas temu, ale pomyślałem, że spróbuję. Jestem studentem i wciąż jestem w tym nowy, ale wydaje się, że działa.
źródło
Szybki, 577
Możesz wkleić to na placu zabaw.
Próbowałem przenieść polecenie
v
do polecenia drukowania i uzyskałem:źródło
Ruby 1.9.3, skompresowany, 321 znaków
Ponieważ kod zawiera znaki niedrukowalne, zamiast tego opublikuję zrzut heksowy kodu:
Aby utworzyć rzeczywisty kod z zrzutu heksadecymalnego, umieść go w pliku i uruchom
xxd -r hexdump > 12days.rb
. Następnie wykonanieruby1.9.3 12.days.rb
uruchomi kod i wydrukuje tekst. Zauważ, że ten kod wymaga Ruby 1.9.3 (ponieważ używaZlib.inflate
), więc nie będzie działał z Ruby 1.8.x, 1.9.1 i 1.9.2.Nieskompresowany kod ma długość 425 znaków:
źródło
Perl, 319/313
Pomysł: rozpakuj i oceń rozwiązanie Jingu Lingua :: EN :: Numbers.
Najpierw wklej ten blok tekstowy do polecenia
perl -e 'use MIME::Base64; print decode_base64 $_ while <>;' >12days.pl
. Następnie uruchom polecenieperl -M5.01 12days.pl
.Sam skrypt przybiera formę, w
use Compress::Zlib;$_='...';eval uncompress$_;
której rozwiązanie...
JB ma znak 368 po skompresowaniu za pomocą tego polecenia i uniknięciu znaku'
.Skrypt Ilmari narzeka na modyfikację wartości tylko do odczytu bez dodatkowych
$_=...;
znaków, ale przypuszczalnie zrobiłby to 313 . Możesz zaoszczędzić jeszcze kilka bajtów, ręcznie dostosowując kompresję, tak jak to robił wcześniej Ilmari, może osiągając około 310 , ale nie zawracałem sobie głowy.Perl, 376 (oszukuje kolejne przesłanie) [moje oryginalne zgłoszenie]
Najpierw utwórz skrypt perla o nazwie
12days.pl
zawierający:Następnie potokuj dane wyjściowe z dowolnego innego przesłania
12days.txt
i wykonaj polecenie:Vola
12days.pl
ma około 376 bajtów i drukuje piosenkę. ;) Zabawne użycie rawinflate przenosi dokładnie sześć bajtów z dokumentu danych do kodu, zaczynając od wyjścia Ilmari.Początkowo szukałem modułu kodującego Huffmana bezpośrednio, co wcale nie jest tak nieuczciwe. Niestety, CPAN nie ma modułów z angielską tabelą entropii liter, co jest tym, czego naprawdę chcesz, gdy kompresujesz bardzo krótkie ciągi.
Stwierdziłem, że
fortune -m Days\ of\ Christmas
niestety nie działa.źródło
PHP, 548
Skrócona długość dzięki kompresji, 502
źródło
VALA,
584, 574Nigdy więcej ostrzeżenia przy kompilacji.
źródło
Java, 608
Pierwszy post na Stack Exchange, druga próba rozwiązania tego problemu.
Java jest trochę kłopotliwa w przypadku takich zadań, ale użycie podziału pomogło zmniejszyć obciążenie łańcucha.
źródło
/// , 439 bajtów
Wypróbuj online!
Jeśli dozwolone są końcowe znaki nowej linii, możesz zapisać cztery bajty:
Wypróbuj online!
Wyjaśnienie
/// to język, w którym jedyną operacją jest podstawienie samomodyfikujące. W szczególności, instrukcja
/abc/xyz/
zastępuje wszystkie wystąpieniaabc
zexyz
w pozostałej części kodu źródłowego, łącznie z innymi substytucji .. Wszelkie inne znaki są po prostu wyjście na standardowe wyjście.Chociaż wystarcza to do kompletności Turinga, gra w golfa w /// zasadniczo polega na rozpoczęciu od zamierzonego wyniku i zidentyfikowaniu powtarzających się podciągów, które można zastąpić skrótami jednoznakowymi.
\
może być używany jako znak zmiany znaczenia we wzorach, zamiennikach i literalnych znakach, co oznacza literał/
lub\
.Pierwsza napotkana instrukcja to
/|/\/\//
. To oznacza „zastąpić wszystko|
ze//
w dalszej części programu.” To oszczędza bajt dla każdego kolejnego podstawienia w programie.Następnie wykonywany jest zestaw zamienników w celu skompresowania samego tekstu:
on the
staje się^
.day of christmas \n my true love gave to me \n
staje się%
.-a-
staje się=
.ing
staje się&
.even
staje się*
.th%
staje się+
.^
poprzedzone dwoma znakami nowej linii (które pojawiają się w każdym wersecie oprócz pierwszego):
.Następnie sami piszemy teksty. Odbywa się to za pomocą zamienników
A
za pośrednictwemK
. Każda zamiana liter dodaje po niej wiersz do zamiany. Na przykładK
reprezentujea partridge in a pear tree
iJ
reprezentujetwo turtle doves \n and K
.W ten sposób każdy wiersz piosenki składa się z:
^
lub:
el*th
)%
A
poprzezK
który reprezentuje poprawne lyrics.Ponieważ jednak większość rzędnych kończy się
th
, używamy podstawieniath%
→,+
aby zapisać niektóre bajty.źródło
Są chwile, kiedy najbardziej oczywiste rozwiązanie jest również najkrótsze, tzn. Nie mogłem już dłużej oprzeć się tej potrzebie.
Bash na Mac OS X, 26
Perl, 111
Dodano jedną nową linię dla czytelności.
źródło
eval compress
sztuczki, aby stwierdzić, że znalazłem regex, który naprawdę dobrze się kompresuje, ale który rozdęł około 200 znaków. lolJava - 1329 znaków
Jestem zbyt leniwy, aby go rozholfować, ale jest tutaj: http://ideone.com/MU9IcP .
źródło
PROSTE , 1 bajt
Uwaga :
Język został zaprojektowany po wyzwaniu i nadal jest PWT.
W jaki sposób :
Każdy znak wyda 12 dni Bożego Narodzenia.
źródło