Napisz najkrótszy program, który drukuje cały tekst piosenki „Never Gonna Give You Up” Ricka Astleya.
Zasady:
- Musisz wyprowadzać teksty dokładnie tak, jak pojawiają się w powyższej paczce *. Oto zrzut zrzutów: http://pastebin.com/raw/wwvdjvEj
- Nie można polegać na żadnych zasobach zewnętrznych - wszystkie teksty muszą być generowane przez / osadzone w kodzie.
- Bez użycia istniejących algorytmów kompresji (np. Gzip / bzip2), chyba że umieścisz pełny algorytm w swoim kodzie.
- Używaj dowolnego języka, wygrywa najkrótszy kod.
Aktualizacja, 1 czerwca 2012 r .:
W przypadku rozwiązań zawierających tekst inny niż ASCII rozmiar rozwiązania będzie liczony w bajtach na podstawie kodowania UTF-8. Jeśli użyjesz punktów kodowych, których nie można zakodować w UTF-8, twoje rozwiązanie nie zostanie uznane za prawidłowe.
Aktualizacja, 7 czerwca 2012 r .:
Dziękujemy wszystkim za wspaniałe rozwiązania! Przyjmuję najkrótszą odpowiedź jutro po południu. W tej chwili odpowiedź GolfScript Petera Taylora wygrywa, więc skorzystaj z ulepszeń, jeśli chcesz go pokonać! :)
* W Pastebin znajduje się literówka (wiersz 46, „know” powinno być „znane”). Możesz go powtórzyć lub nie według własnego uznania.
źródło
Odpowiedzi:
Ruby
576 557556 (552) znaków i & PHP 543 znakówKolejne rozwiązanie wyszukiwania i zamiany. Zauważ, że ta forma rozwiązania jest zasadniczo kodem kompresji opartym na gramatyce http://en.wikipedia.org/wiki/Grammar-based_code Sprawdź http://www.cs.washington.edu/education/courses/csep590a/07au /lectures/lecture05small.pdf dla prostego do zrozumienia przykładu kompresji.
Napisałem reguły podstawiania, aby znak początkowy dla każdego podstawienia był obliczany (są one w kolejności ASCII); nie musi być obecny w danych przejściowych.
uwagi dotyczące wdrażania
starsze wdrożenie
Ta starsza implementacja ma 576 znaków i zaczęła się od reguł podstawiania z implementacji bash / sed ugorena. Ignorując zmianę nazwy zmiennej podstawienia, moje pierwsze 28 podstawień jest dokładnie takie samo jak te wykonane w programie ugorena. Dodałem jeszcze kilka, aby obniżyć ogólną liczbę bajtów. Jest to możliwe, ponieważ moje reguły są bardziej wydajnie reprezentowane niż te w implementacji ugorena.
W tym przypadku nie próbowałem optymalizować reguł podstawiania.
notatki z zawodów
Schemat dekompresji typu „szukaj i zamień” działa dobrze w tym konkursie, ponieważ większość języków ma wbudowane procedury, które mogą to zrobić. Przy tak małej ilości tekstu do wygenerowania złożone schematy dekompresyjne nie wydają się być wykonalnymi wygranymi.
Użyłem tylko tekstu ASCII, a także unikałem używania niedrukowalnych znaków ASCII. Przy tych ograniczeniach każdy znak w kodzie może reprezentować maksymalnie maksymalnie 6,6 bitów informacji; to bardzo różni się od prawdziwych technik kompresji, w których używasz wszystkich 8 bitów. W pewnym sensie porównywanie z rozmiarem kodu gzip / bzip2 nie jest „sprawiedliwe”, ponieważ algorytmy te wykorzystują wszystkie 8 bitów. Bardziej zaawansowany algorytm dekompresyjny może być możliwy, jeśli możesz dołączyć tradycyjnie niedrukowalne ASCII do swoich łańcuchów ORAZ każdy niedrukowalny znak jest nadal zapisany w kodzie jako pojedynczy bajt.
Rozwiązanie PHP
Powyższe rozwiązanie bierze PHP z „smutnego kolesia” i łączy je z moimi zasadami podstawiania. Okazuje się, że odpowiedź PHP ma najkrótszy kod dekompresyjny. Zobacz http://ideone.com/XoW5t
źródło
sed
rozwiązanie z pewnością nie da rady. Pracuję nad czymś, co mam nadzieję, ma szansę - masz 75 bajtów narzutów, może to zmniejszy (nie w Ruby).Bash / Sed,
705650588582 znakówLogika :
Podstawową ideą jest prosta zamiana. Zamiast pisać, na przykład
Never gonna give you up\nNever gonna let you down
, piszęXgive you up\nXlet you down
i zastąpić wszystkoX
zNever gonna
.Osiąga się to poprzez uruchomienie
sed
zestawu reguł w formies/X/Never gonna /g
.Zamienniki można zagnieżdżać. Na przykład
Never gonna
jest powszechny, ale tak samo jestgonna
w innych kontekstach. Więc mogę użyć dwóch zasad:s/Y/ gonna/g
is/X/NeverY/g
.Podczas dodawania reguł fragmenty tekstów piosenek są zastępowane pojedynczymi znakami, więc stają się krótsze. Reguły stają się dłuższe, ale jeśli zastępowany ciąg jest długi i częsty, warto.
Następnym krokiem jest usunięcie powtórzeń z
sed
samych poleceń. Sekwencjas/X/something/g
jest dość powtarzalna.Aby było krótsze, zmieniam polecenia sed tak, aby wyglądały
Xsomething
. Następnie używamsed
do przekonwertowania tego na normalnesed
polecenie. Kodsed 's#.#s/&/#;s#$#/g;#
to robi.Ostatecznym wynikiem jest
sed
polecenie, którego argumenty są generowane przez innesed
polecenie, w cudzysłowach.Bardziej szczegółowe wyjaśnienie można znaleźć w tym linku .
Kod:
Uwagi:
Silnik dekompresyjny ma tylko 40 znaków. Pozostałe 543 to tabela tłumaczeń i skompresowany tekst.
bzip2
kompresuje utwór do 500 bajtów (oczywiście bez silnika), więc musi być miejsce na ulepszenia (choć nie rozumiem, jak dodałbym kodowanie Huffmana lub coś takiego wystarczająco tanio).<<Q
(lub<<_
) służy do czytania, aż do danego znaku. Ale koniec skryptu (lub wyrażenie w cudzysłowie) jest wystarczająco dobry. To czasami powoduje ostrzeżenie.Starsze i prostsze rozwiązanie, 666 znaków:
źródło
\0
z&
.&
robi 5.Biała spacja - 33115 znaków
StackExchange skompromitował moją odpowiedź, oto źródło: https://gist.github.com/lucaspiller/2852385
Nie wspaniale ... Myślę, że może uda mi się to trochę zmniejszyć.
(Jeśli nie wiesz, co to jest Whitespace: http://en.wikipedia.org/wiki/Whitespace_(programming_language) )
źródło
JavaScript,
590588 bajtówZależnie od sposobu, w jaki napis jest „drukowany”.
https://gist.github.com/2864108
źródło
if(g.indexOf(g[i])!=-1)
wcześniej,e=
aby to naprawić.with(f.split(g[i]))f=join(pop())
wfor..in
pętli oszczędza bajtC #
879816789 znakówPierwsza próba CodeGolfa, więc zdecydowanie nie wygrała, jestem całkiem pewna, że jest ważna, mimo że jest nieprzyjemna.
źródło
var s1="a";var s2="b";
spróbuj użyćstring s1="a",s2="b"
; jeśli masz deklaracje 2+, jest to krótsze.!
i usuwając je z innych miejsc.Python,
597589 bajtówMoże być możliwe wyciśnięcie kolejnej pary bajtów:
źródło
BrainFuck - 9905
Jestem całkiem pewien, że uda mi się go ulepszyć, ale to na razie jest całkiem dobre. Zakładając, że nie ma problemu z tym, że jest on znacznie większy niż oryginalny tekst.
źródło
Scala, 613 bajtów
Jest to algorytm dekompresji tekstu, rekurencyjnie stosujący regułę, na którą
~stuff~ blah ~ ~
należy przekonwertowaćstuff blah stuff stuff
(tzn. Gdy po raz pierwszy zobaczysz nieznaną parę symboli, określa to, co skopiować, a następnie podajesz wartość, gdy ją widzisz).Uwaga: na końcu może być dodatkowy zwrot karetki, w zależności od tego, jak się liczy. Jeśli nie jest to dozwolone, możesz upuścić ostatni z cytatów (zapisując jeden znak) i zmienić podział na
split(" ",-1)
(wydając 3 znaki) na 615 bajtów.źródło
N
powtórzeń długościL
używaszL+N+1
znaków, podczas gdy ja używamL+N+2
. Ale twój kod dekompresyjny ma 102 znaki, a mój 40.589, C (tylko funkcja biblioteki to putchar)
Tabela reguł podstawiania, w których znaki z zakresu -.._ (45..90) określają, którą regułę zastosować, a zatem około 48 reguł (45, c-45> U48 w kodzie), inne znaki mają zostać wydrukowane
reguły są rozdzielane znakiem „&” (38 w kodzie, n jest zmniejszane do zera, a zatem s wskazuje na prawidłową regułę)
reguła 0 wskazuje, że następny znak powinien być pisany wielkimi literami (poprzez ustawienie k = 32 w kodzie), to zwalnia więcej miejsca na dodanie większego ciągłego zakresu znaków dla reguł
main (..) jest wywoływany z 1 (zgodnie z konwencją programu C argumentu zero), a zatem reguła 1 jest regułą root
Ewolucja kodu
zgolił kolejne 9 bajtów dzięki sugestii ugorena
ogolił kolejne 36 bajtów, tworząc tabelę algorytmicznie, a nie ręcznie i za pomocą końcówki „”
ogolił kolejne 15 bajtów, zmieniając tabelę z znaku * * na pojedynczy ciąg znaków, w którym „&” ogranicza części
ogolił jeszcze 19 bajtów dzięki więcej wskazówek od ugorena
ogolono 31 bajtów, dodając więcej reguł, utworzono specjalną regułę, która ma być pisana wielkimi literami, co pozwala na więcej miejsca na indeksy reguł.
ogoliłem 10 bajtów, dzięki jeszcze więcej wskazówek od urgoren i nieznacznie zmieniając zasady
źródło
*p>>4^3?putchar(*p):e(r[*p-48])
"\'"
nie jest potrzebne."We're"
jest poprawnym ciągiem.ing
jest lepszym kandydatem.d(int n)
->d(n)
. Zmiana*s=='~'
na*s-'~' and reverse the
?:, also saving parenthesis around
! N? ..: 0. Using 126 instead of
'~' 'jest bezużyteczna, ale dlaczego~
?main
ustaw rekurencję. Wstępna rozmowa jestmain(1)
zamiastd(0)
, ale może być rozpatrywane (może być wiodącym~
ws
). Najlepszą alternatywą~
jest także zakładka (ascii 9 - jedna cyfra).Perl,
724714883 bajtówTak więc zmiana zasad karających za użycie rodzaju Latin-1 zabiła moje rozwiązanie. Jest to na tyle inne podejście, że nienawidzę go po prostu usuwać, więc tutaj jest ograniczona wersja, która używa tylko 7-bitowego ASCII, zgodnie z nowymi regułami, przy ogromnym wzroście rozmiaru.
Oczywiście znaki kontrolne są nadal zniekształcone, więc nadal będziesz chciał użyć kodowania base64:
Ponieważ myślę, że powinno być nadal widoczne, mimo że DQ'd, oto oryginalne rozwiązanie:
Kodowanie skryptu base64:
źródło
Python
781731605579 znakówJest wiele, wiele lepszych odpowiedzi od kiedy to zobaczyłem, ale zmarnowałem dużo czasu na mój skrypt Pythona, więc zamierzam go opublikować w jakikolwiek sposób, byłoby wspaniale zobaczyć sugestie dotyczące dalszego skrócenia,
Edycja: dzięki sugestiom Eda H posiekano 2 znaki, aby przejść dalej, być może będę musiał zrestrukturyzować wiele rzeczy tutaj, co zajmie trochę czasu
Po pierwszym ręcznym utworzeniu łańcucha (bardzo żmudne) napisałem funkcję rekurencyjnego znajdowania zastępowania wzorca, która była najbardziej opłacalna (na tym etapie), co dało mi rozwiązanie, ale okazało się, że zwiększyłem rozmiar o 10 znaki.
Więc uczyniłem mój algorytm nieco mniej chciwym, zamiast zajmować miejsce w końcowym rankingu tylko dla „znaków zmniejszonych”, rankingu na podstawie funkcji „znaków zmniejszonych”, „długości wzoru” i „liczby wzorów”
długość wzoru = długość liczenia = liczba
Następnie poprosiłem mojego biednego laptopa, aby działał nieskończenie, przypisując losowe wartości do
lengthWeight
icountWeight
otrzymując różne końcowe rozmiary kompresji oraz zapisując dane dla minimalnych rozmiarów kompresji w plikuOkoło pół godziny wyszło z powyższym ciągiem (próbowałem dalej go majstrować, aby sprawdzić, czy mogę skrócić kod), i nie obniży się, myślę, że coś tu brakuje.
oto mój kod, również
max_pattern
jest bardzo powolny (uwaga: kod wyrzuca ciąg podobny do formy w mojej poprzedniej wersji rozwiązania, ręcznie go przepracowałem, aby uzyskać bieżący formularz, ręcznie mam na myśli, ręcznie w powłoce pytona)źródło
\n
kosztuje 5 znaków i oszczędza 9. 2. Dodatkowe miejsce win (g,l..)
. 3.join(..)
działa równie dobrzejoin([..])
(co najmniej w wersji 2.7).Malbolge, 12735 bajtów
Wypróbuj online.
Wygenerowano za pomocą narzędzi tutaj.
źródło
JavaScript 666 bajtów
Zainspirowany rozwiązaniem tkazec .
Sprawdź post na blogu , który o nim napisałem, zawiera wszystkie źródła i wyjaśnia, jak zbudowałem ten kod.
Możesz skopiować i wkleić kod do konsoli przeglądarki. Lub spróbuj na http://jsfiddle.net/eikes/Sws4g/1/
źródło
Perl,
584578577576575571564554553540To rozwiązanie jest oparte na tym samym podstawowym podejściu, co większość innych: biorąc pod uwagę początkowy ciąg znaków, wykonaj powtarzane podstawienia powtarzających się części tekstu.
Reguły podstawiania są określone przez jeden znak, najlepiej taki, który nie występuje w tekście wyjściowym, więc reguła długości L i występowania N razy pozwoli zaoszczędzić około N * LNL-1 (N * L to pierwotna długość wszystkich wystąpień, ale znak podstawienia występuje N razy, a sam literalny tekst ma długość L, a reguły są dzielone znakiem rozdzielającym.) Jeśli znaki podstawienia są wyraźnie określone, to oszczędności są zmniejszane do N * LNL-2. Biorąc pod uwagę, że większość języków może obliczyć znak za pomocą chr () lub podobnie krótkiego kodu, pierwsze podejście jest na ogół lepsze.
Obliczenie znaku podstawienia ma pewne wady, z których najbardziej znacząca jest potrzeba ciągłego zakresu znaków ASCII. Dane wyjściowe używają głównie małych liter, ale jest wystarczająca liczba wielkich liter i interpunkcji, aby wymagać albo zastąpienia znaku samym sobą, ponownego przypisania kilku znaków na etapie naprawy lub uporządkowania reguł, aby zastąpienie problematycznymi znakami miało miejsce wcześniej. Użycie języka, który zastępuje użycie wyrażeń regularnych, oznacza również, że istnieją wyrażenia specjalne dla znaków, które mają specjalne znaczenie w wyrażeniu regularnym:
.
+
*
\
?
Moje oryginalne podejście miało 63 bajty w dekoderze i 521 w regułach. Spędziłem dużo czasu na optymalizacji reguł, co może być trudne, szczególnie w przypadku krótkich reguł, ponieważ mogą się one nakładać. Dekodowanie zostało zmniejszone do 55 bajtów, a reguły do 485, trochę oszukując formułę. Zwykle reguła składająca się z 2 znaków występująca 3 razy lub reguła składająca się z 3 znaków, która występuje dwa razy, tak naprawdę nie pozwoliłaby na zaoszczędzenie żadnej długości, ale istnieje luka - która umożliwia także tworzenie słów, które nie są częścią wyniku; - ).
W tym rozwiązaniu używam znaków kontrolnych, więc rozwiązanie jest tutaj zakodowane w standardzie base64.
I tutaj jest to wersja nieco bardziej czytelna (ale mniej wykonywalna).
Podejrzewam jednak, że nadal nie jest to minimum, ponieważ Ed H. wskazuje, że dekodowanie php jest najkrótsze przy 44 bajtach i widziałem miejsce na ulepszenie reguł, których używa. W Perlu mam 52-bajtowy dekoder, ale nie mogłem go użyć do tego rozwiązania, ponieważ musiałem uruchomić zakres w odwrotnej kolejności.
źródło
PHP
730707 znakówźródło
$s="Never gonna give...
można skrócić za pomocą$n
.Perl -
589 588 583 579576 bajtówKażda reguła składa się z 1 znaku głowy, ciała i podkreślenia. Tak długo, jak reguły można odciąć na początku, treść reguły jest zastępowana jej treścią w pozostałej części tekstu. Podano nagłówek pierwszej reguły, nagłówki wszystkich następnych reguł są generowane ze zmiennej $ i.
Ponieważ nagłówek następnej reguły jest umieszczony na początku tekstu przez poprzednią regułę, ostatnia reguła utworzy znak, który nie będzie już usuwany. Musiałem wybrać zakres nazw, w których ostatnim byłoby „W”, więc mogłem usunąć oryginalne „W” z początku tekstu i zastąpić je podstawieniem reguły.
Kodowania dokonano za pomocą skryptu Python przy użyciu prostego algorytmu wspinaczki górskiej.
Oto kod Perla:
(Uważam za niezwykłe, że skompresowany tekst zawiera „usłyszeć”: D)
A tutaj kod Pythona, który go generuje:
źródło
while
dla pętli; pozwala to zrezygnować z nawiasów klamrowych i nawiasów. Kolejny pomysł: wymyśl, jak użyćsay
zamiastprint
zrobić wynik.Python 2.7,
975803 bajtówNie największe - ja (teraz) chciałbym, żeby python tak sformatował rozszerzenia. Niestety tak nie jest.
Edycja: Symulowane rozszerzenie z alternatywną składnią formatowania (tak jakby ...)
źródło
Clojure
720 bajtów / znaków:
(Reprodukcja tutaj z dodatkową spacją, dzięki czemu można zobaczyć formatowanie)
źródło
C # - 605 znaków | T-SQL - 795 znaków | C # - 732 znaków | C # - 659 znaków
Inspiracją do tego jest przykład sed. Jedyną istotną zmianą, jaką wprowadziłem, było wyszukiwanie kolejnych znaków ASCII, aby nie musiały być deklarowane. Niestety jest to C #, więc nie wiem, jak go zmniejszyć. Wziąłem ten sam tekst zastępczy i zrobiłem kod w T-SQL przy użyciu tabeli tymczasowej.
T-SQL
C # - Second Try To było inne podejście. Kompresja została wykonana w całości przez komputer poszukujący najlepszych zamienników. Wyszukiwania są sekwencyjne i uporządkowane według rozmiaru, więc nie ma potrzeby wyszukiwania z ograniczeniami, jednak kod do wykonywania przeglądów był mniej wydajny niż myślałem, więc ostatecznie kosztował 127 dodatkowych znaków! Żyj i ucz się.
3. próba w C #. Tym razem straciłem ważność ze znakami \ b, \ r, \ t. Możesz użyć \ rN \ n, aby zastąpić pierwszy znak w linii wielką literą N, ale tak naprawdę nie zapisał on znaków. Utworzyłem \ b aliasy, aby przesunąć kursor do tyłu, a następnie napisać nad istniejącym tekstem. Ale żadna z tych zaoszczędzonych przestrzeni, a na koniec byłam w gorszej sytuacji niż prosta strategia wyszukiwania i zamiany.
źródło
REPLACE
podejście, szczególnie w przypadku dynamicznego SQL, ale istnieje wiele sposobów gry w golfa, które bardziej: Użyj@
jako zmiennej zamiast@s
, ustaw jako stały stółt
zamiast#t
(nie musisz sprzątać po sobie), pozbyć się 29-znakowej instrukcji COLLATE i po prostu wymagać, aby była uruchamiana na serwerze / bazie danych z odpowiednim zestawieniem, użyciemvarchar(999)
lubvarchar(max)
tonami niepotrzebnych białych znaków wokół znaków równości i przecinków itp.PHP,
591585568564 bajtówźródło
Ruby, 1014 bajtów
Uczę się programowania, więc nie zamierzam tutaj bić żadnych rekordów. Ale to było fajne zadanie.
źródło
GolfScript (511 bajtów)
Wykorzystuje zmianę podstawy do spakowania bitów, więc zawiera znaki, które nie są w ASCII. Jednak niewłaściwe jest ocenianie tych znaków za pomocą kodowania UTF-8, ponieważ interpreter traktuje program jako ISO-8859-1. Z tego powodu podałem długość w bajtach, a nie w znakach.
Kodowane w standardzie Base-64:
Zrzut szesnastkowy (wyjście z
xxd
):Jak większość najlepszych rozwiązań, wykorzystuje to podejście oparte na gramatyce z podziałami łańcuchów i łączeniami w celu rozszerzenia gramatyki. Gramatyka ma 30 zasad i została znaleziona przez zachłanne poszukiwania.
źródło
JavaScript, 854 znaków (dodano nowe wiersze dla „czytelności”)
źródło
Naiwne sh / echo - 810 bajtów
źródło
JavaScript 789 znaków
Mój javascript (drukuje za pomocą „document.write ()”):
Zmieniam niektóre popularne słowa i frazy za pomocą cyrylicy, a następnie zmieniam je z powrotem za pomocą funkcji replace ().
Po skróceniu tekstu skróciłem mój program tą samą metodą i wykonałem kod za pomocą eval ().
źródło
Rubinowy,
741678657627619 bajtówTo jest iteracyjne rozwinięcie symbolu. Dla każdego z 28 znaków ciągu w pierwszym argumencie do
gsub!
wszystkie wystąpienia tego znaku_
są zastępowane odpowiednią sekcją drugiego ciągu (oddzieloną+
znakami).źródło
Python, 573 znaków
Moje
sed
rozwiązanie nie pójdzie dalej i zostało pobite przez kilka osób, więc wybrałem nowe podejście.Niestety, wystarczy tylko na
2.3. miejsce (na razie) - Ed H. wciąż jest przede mną .Uwagi :
Główna idea została zapożyczona od Eda H. - używając do zamiany kolejnych znaków, zamiast określać je w każdej regule wymiany.
Mój sposób radzenia sobie z postaciami występującymi w piosence
jest inny niż Eda- po prostu upewniam się, że każdy z nich tłumaczy na siebie (i jeśli zawsze towarzyszy temu coś, dodaj go również, co tylko działałoW
).Kod jest generowany przez skrypt, który szuka dobrych tłumaczeń. Na początku użyłem chciwego algorytmu, który po prostu przyjmuje ten, który daje najlepszą redukcję. Potem odkryłem, że poprawianie go w celu preferowania dłuższych ciągów poprawia to trochę. Myślę, że to wciąż nie jest optymalne.
źródło
Golfscript,
708702699691 bajtówźródło
" I'm feeling":i;
?j
, przypisałem trzy konkatenowane ciągi znaków (usunięte{
i}
dodane, ale dodane++
do konkatenacji). To pozwoliło mi zadeklarowaći
inline, podczas komponowania zawartościj
.g
i na refren, używając jednego łańcucha z nowymi liniami, a następnien/g*
g
ponieważ jest on również używany pod koniec (faktycznie jest to możliwe, ale ostatecznie kosztowałby 1 znak więcej). Jednak metoda dzielenia / składania w celu wstawienia g na początku każdej linii jest świetnym narzędziem do oszczędzania znaków.Java, 858 bajtów
Łał. Naprawdę nie sądziłem, że mógłbym to mocno skompresować.
UngolfedW formie czytelnej dla człowieka:źródło
String foo; String bar;
podczas golfa.JavaScript,
14281451883 * znakówZdecydowanie nie najkrótsze rozwiązanie, ale proszę bardzo.
Logika rozwiązania jest dość prosta:
* Oczywiście rozwiązanie staje się o wiele krótsze, gdy przyjmuje się unikalne wiersze zamiast unikalnych słów.
źródło