Labirynt , 28 25 24 23 22 bajtów
" >
?!?:|}\{@
@\?"":)!
To była szalona zabawa! :) To zdecydowanie najgęściej skompresowany program Labiryntu, jaki do tej pory napisałem. Miałem tak wiele wersji o wielkości 20 i 21 bajtów, które prawie działały, że wciąż wątpię, czy jest to optymalne ...
Pobiera to dane wejściowe jako listę liczb całkowitych dodatnich (z dowolnym ogranicznikiem) i wypisuje wynik do STDOUT jako liczby całkowite rozdzielane przez linię.
Polowanie na 20/21 bajtów: sprawdziłem wszystkie programy formularza
" XX
?!?X}\{@
@\?XX)!
gdzie X
jest jakikolwiek rozsądny charakter brutalnej siły, ale nie znalazł żadnych ważnych rozwiązań. Oczywiście nie oznacza to, że krótsze rozwiązanie nie istnieje, ale nie można narzucać 20-bajtowych programów bez sporej liczby założeń dotyczących jego struktury.
Wyjaśnienie
(Wyjaśnienie jest nieco nieaktualne, ale nadal nie jestem przekonany, że rozwiązanie jest optymalne, więc poczekam z aktualizacją).
Zatem normalnie programy Labiryntu powinny wyglądać jak labirynty. Gdy wskaźnik instrukcji znajduje się w korytarzu, podąży za nim. Kiedy IP trafia na jakiekolwiek połączenie, kierunek jest określany na podstawie najwyższej wartości głównego stosu Labiryntu (Labirynt ma dwa stosy, z nieskończoną liczbą zer na dole). Zwykle oznacza to, że każda nietrywialna pętla będzie dość droga, ponieważ jeśli masz komórki nieścienne w całym miejscu, wszystko jest skrzyżowaniem, aw większości przypadków górna część stosu nie będzie miała właściwej wartości dla adresu IP podążać ścieżką, którą chcesz. Więc powiększasz pętle, tak aby miały całość w środku z tylko jednym dobrze zdefiniowanym punktem wejścia i wyjścia.
Ale tym razem miałem naprawdę szczęście i wszystko tak dobrze do siebie pasowało, że mogłem wszystko to zmiażdżyć. :)
Przepływ kontrolny zaczyna się w _
kierunku południowym. _
Popycha zero na głównym stosie. Może to wydawać się brakiem operacji, ale zwiększa to (niejawną) głębokość stosu, do 1
której będziemy potrzebować później.
?
odczytuje liczbę całkowitą ze STDIN. Jeśli nie ma więcej liczb całkowitych do odczytania, przesuwa to zero. W takim przypadku adres IP przesuwa się na południe i @
natychmiast kończy program (ponieważ lista wejść jest pusta). W przeciwnym razie IP zmienia się na Wschód.
Wchodzimy teraz w bardzo ciasną pętlę z dwoma punktami wyjścia:
!?;
\?
;
!
wypisuje liczbę całkowitą z powrotem do STDOUT, pozostawiając tylko zero na stosie. Adres IP przesuwa się na wschód i ?
odczytuje następną liczbę całkowitą. Jeśli to nie jest zero, skręcamy w prawo i ruszamy na południe. ?
odczytuje inny (następny parzysty indeks). Ponownie, jeśli nie jest to zero, skręcamy w prawo i ruszamy na zachód.
Następnie \
drukuje wysuw linii bez zmiany stosu, więc skręcamy w prawo, przesuwając się na północ. !
wypisuje następną liczbę całkowitą z indeksem parzystym. Ponieważ teraz na stosie znajduje się co najmniej jedna (dodatnia) liczba całkowita o nieparzystym indeksie, skręcamy w prawo i pętla się powtarza.
Gdy któryś z nich ?
trafi na koniec listy, naciska zero i przesuwa się prosto na odpowiedni ;
, który odrzuca to zero.
W przypadku, gdy na liście znajdował się tylko jeden element, skończyliśmy (ponieważ wydrukowaliśmy to od razu), więc adres IP przesuwałby się na wschód aż do @
, ponownie kończąc program (drukując końcowy po drodze).
W przeciwnym razie musimy również wydrukować liczby całkowite o nieparzystym indeksie. W takim przypadku dwie ścieżki (z dwóch punktów wyjścia pierwszej pętli) łączą się na środku "
, w obu przypadkach kierując się na wschód.
_
naciska zero, aby uniknąć skrętu w lewo @
, i ;
odrzuca to zero. Teraz wchodzimy w nową pętlę:
"}
""
IP wchodzi do tego w lewej dolnej komórce, poruszając się na północ, omijając pętlę zgodnie z ruchem wskazówek zegara. }
Przenosi góry głównego stosu nad do stosu pomocniczego. Podczas gdy na stosie nadal znajduje się element, adres IP nadal działa. Po przeniesieniu wszystkiego do stosu pomocniczego (i odwróceniu w tym procesie) IP przesuwa się na wschód, wchodząc w ostatnią pętlę:
\{@
#!
\
wypisuje ponownie linię, {
przenosi element ze stosu pomocniczego z powrotem na główny. Jeśli nadal był to element na liście, będzie dodatni, a adres IP skręca na południe, gdzie element jest drukowany !
. Następnie #
przesuwa głębokość stosu (a teraz jest to miejsce, w którym _
ważna jest wartość początkowa , ponieważ #
zapewnia to dodatnią głębokość stosu), dzięki czemu adres IP nadal skręca w prawo, przez \
i {
ponownie.
Po wydrukowaniu wszystkiego, {
wyciąga zero z dolnej części stosu pomocniczego, IP kontynuuje Wschód i @
kończy program.