7 , 410 znaków, 154 bajty w kodowaniu 7, 0 liter = wynik 154
55104010504200144434451510201304004220120504005434473340353241135014335450302052254241052253052244241052335452241114014241310052340435303052335442302052335500302052335430302052313340435303135014243241310335514052312241341351052302245341351525755102440304030434030421030442030424030455733413512410523142410523030523112411350143355142410523414252410523102410523002410523413342411145257551220304010420030455741403
Wypróbuj online!
W wyzwaniu, które nie lubi używania liter, jaki jest lepszy język niż ten składający się wyłącznie z cyfr?
Jest to pełny program, który kończy się przez awarię, więc istnieje dodatkowe wyjście dla stderr, ale standardowe wyjście jest prawidłowe.
Wyjaśnienie
Program 7 podczas pierwszej iteracji po prostu wypycha na stos pewną liczbę elementów (ponieważ spośród 12 poleceń istniejących w 7 tylko 8 z nich może być reprezentowanych w programie źródłowym, a te 8 specjalizują się w pisaniu kodu wypychanie określonych struktur danych na stos). Ten program nie używa 6polecenia (który jest najprostszym sposobem tworzenia zagnieżdżonych struktur, ale w przeciwnym razie nie pojawia się dosłownie w programie źródłowym), więc to tylko 7polecenia określają strukturę; 7wypycha nowy pusty element na szczyt stosu (podczas gdy polecenia 0… 5po prostu dołączają się na szczyt stosu). Możemy zatem dodać do programu białe znaki, aby pokazać jego strukturę:
551040105042001444344515102013040042201205040054344 7
33403532411350143354503020522542410522530522442410523354522411140142413100523
40435303052335442302052335500302052335430302052313340435303135014243241310335
514052312241341351052302245341351525 7
55102440304030434030421030442030424030455 7
33413512410523142410523030523112411350143355142410523414252410523102410523002
41052341334241114525 7
551220304010420030455 7
41403
Elementy pod koniec programu są wypychane na końcu, więc znajdują się na szczycie stosu na początku drugiej iteracji. Podczas tej iteracji i wszystkich przyszłych iteracji 7 interpreter automatycznie tworzy kopię wierzchu stosu i interpretuje ją jako program. Literał 41403popycha (nie-literalny, aktywny kod) 47463(7 ma 12 poleceń, ale tylko 8 z nich ma nazwy; jako takie używam pogrubienia, aby pokazać kod, i niepogrubionego, aby pokazać literał, który generuje ten kod, co oznacza że np. 4jest to polecenie dołączane 4do elementu najwyższego stosu). Tak więc programem działającym przy drugiej iteracji jest 47463. Oto, co to robi:
47463
4 Zamień dwa górne elementy stosu, dodaj pusty element między
7 Dodaj pusty element stosu na górę stosu
4 Zamień dwa górne elementy stosu, dodaj pusty element między
6 Sprawdź, które polecenia wygenerują górny element stosu;
dodaj to do elementu poniżej (i pop starą górę stosu)
3 Wyjmij górny element stosu, pop element poniżej
Łatwiej to zrozumieć, jeśli spojrzymy na to, co stanie się ze stosem:
- ... d c b a
47463 (kod uruchomić: 47463)
- ... d c b opróżnić z (kod biegu: )
47463 7463
- ... d c b opróżnić z pustą (kod uruchomić: )
47463 463
- ... d c b pustej pustej pustej A (kod uruchomić: )
47463 63
- ... d c b pustej pusty " w " (kod uruchomić: )
47463 3
- … D c b pusty (kod do uruchomienia: pusty )
47463
Innymi słowy, bierzemy górę stosu a , sprawdzamy, jaki kod najprawdopodobniej go wytworzył i wypisujemy ten kod. Interpreter 7 automatycznie wyrzuca puste elementy ze szczytu stosu na końcu iteracji, więc kończymy z 47463powrotem na stosie, tak jak w oryginalnym programie. Powinno być łatwo zobaczyć, co będzie dalej: w końcu przeglądamy każdy element stosu jeden po drugim, wypisując je wszystkie, aż stos się przepełni i program się nie zawiesi. Zasadniczo stworzyliśmy prostą pętlę wyjściową, która sprawdza kod źródłowy programu w celu ustalenia, co należy wydrukować (nie wysyłamy struktur danych, które zostały wypchnięte na stos przez 0…5polecenia, zamiast tego odtwarzamy, które polecenia zostały użyte, sprawdzając, jakie struktury zostały utworzone i wysyłamy je). Tak więc, pierwszy fragment danych wyjściowych to 551220304010420030455(kod źródłowy, który generuje element stosu drugi od góry), drugi to 3341351…114525(kod źródłowy, który generuje element stosu trzeci od góry) i tak dalej.
Oczywiście te fragmenty kodu źródłowego nie są generowane w postaci niezakodowanej. 7 zawiera kilka różnych języków specyficznych dla domeny do kodowania danych wyjściowych; po wybraniu języka specyficznego dla domeny pozostaje on w użyciu aż do jawnego wyczyszczenia, ale jeśli żaden z języków nie został jeszcze wybrany, pierwsza cyfra wyprowadzanego kodu określa, którego języka należy użyć. W tym programie używane są tylko dwa języki: 551i 3.
551jest dość proste: jest to w zasadzie stary kod Baudot / teletype używany do przesyłania liter za pomocą teletypów, jako 5-bitowy zestaw znaków, ale zmodyfikowany tak, aby wszystkie litery były małe. Tak więc pierwsza część kodu, który ma zostać wydrukowany, dekoduje w następujący sposób:
551 22 03 04 01 04 20 03 04 55
c a SP e SP n a SP reset output format
Jak widać, dopasowujemy każdy znak do dwóch cyfr ósemkowych, co jest dość przyzwoitym stopniem kompresji. Pary cyfr z zakresu 0-5 dają nam 36 możliwości, w przeciwieństwie do 32 możliwości, których potrzebuje Baudot, więc pozostałe cztery są używane do specjalnych poleceń; w tym przypadku 55na końcu usuwa zapamiętany format wyjściowy, co pozwala nam użyć innego formatu dla następnego produkowanego przez nas fragmentu.
3jest koncepcyjnie jeszcze prostszy, ale z pewnym zwrotem. Podstawową ideą jest pobranie grup trzech cyfr (ponownie w zakresie 0-5, ponieważ są to cyfry, dla których możemy zagwarantować, że możemy odtworzyć oryginalny kod źródłowy z jego wyniku), interpretować je jako trzycyfrowe liczba w bazie 6 i po prostu wyślij go jako bajt w formacie binarnym (pozwalając w ten sposób wypisać znaki wielobajtowe w żądanym wyniku po prostu przez wyprowadzenie wielu bajtów). Skręt wynika jednak z faktu, że w bazie 6 jest tylko 216 liczb trzycyfrowych (z możliwymi zerami wiodącymi), ale 256 możliwych bajtów. 7 omija to, łącząc liczby od 332₆ = 128₁₀ w górę do dwóch różnych bajtów; 332może wyprowadzać bajt 128 lub 192, 333bajt 129 lub 193, i tak dalej, aż do 515bajtów 191 lub 255.
Skąd program wie, która z dwóch możliwości wyjścia? Możliwe jest użycie trojaczków cyfr od 520góry, aby to wyraźnie kontrolować, ale w tym programie nie musimy: domyślnie 7 wybiera wszystkie niejednoznaczne bajty w taki sposób, że wyjście jest poprawne UTF-8! Okazuje się, że zawsze jest co najwyżej jeden sposób, aby to zrobić, tak długo, jak chcemy UTF-8 (i robimy w tym przypadku), możemy po prostu pozostawić to dwuznaczne, a program i tak działa.
Koniec każdej z 3…sekcji to 525, która resetuje format wyjściowy, pozwalając wrócić do 551następnej sekcji.
as - lub nie, w zależności od liczby potrzebowałaby liter, ponieważ 20 znaków to naprawdę duża kara (chociaż gdy wszystko inne jest oceniane według bajtów, nie jest to całkiem dobrze zdefiniowane ...)!