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 Xjest 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 1któ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.