Krótka historia języków programowania 2D: 16 (+2) lat
v19977/2{@{{4{\_______>/02&&&#???? * P+++++1P1P-1P+1E * *
\'\02'oo100@n590@n; * * *
>"8991",,,;5-;,@ * * *
* * * *
\ * ++++++++++++++++++++++++ ++++++++++++++++++++++++ ++O--OO++++++++OX******* *
* #2018O@ * * * * * * *
* * * * * * * *
* * * * * * * *
* **** **** * **** **** * **** **** * **** *****
* * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * *
* * * **** * * * * **** * * * * **** * * * * ****
* * * * * * * * * * * * * * * *
R"2014"; ***** ******* ****** ******* ****** ******* ****** *******
x
x%"2010"x
x
$'main' \/\/\/\
\-[2005]o-# \++++++\
/++++++/
\++++++\
/++++++/
\/\/\/\++.--..+++.#
S1^2^2^6^8MAOUOAOOF
/K:0:1:@
> "7102"4&o@
| }+++++[>++++++++++<-]>.--..++++++.@
Czy wspomniałem, że lubię języki programowania 2D?
Język, który (rzekomo patrz ostatnia sekcja) zaczął to wszystko. W Befunge możesz przekierować kontrolę za pomocą <v>^
, ale teraz wszechobecne lustra \
i /
jeszcze nie były niczym. Interpreter Befunge używany w Anarchy Golf ignoruje nieznane polecenia. Możemy to wykorzystać do odróżnienia rodziny Befunge od rodziny> <>. Dlatego kod wykonywany przez Befunge jest następujący:
v
\
>"8991",,,;5-;,@
"8991"
Popycha poszczególne znaki na stos. ,,,
drukuje pierwsze trzy z nich. Wtedy ;
jest nieznane (którego użyjemy, aby odróżnić go od Befunge 98), 5-
zamienia a 8
na 3
i ,
drukuje to również przed @
zakończeniem programu.
Napisanie tej części rozwiązania zajęło mi chyba tyle, ile napisanie wszystkich pozostałych i połączenie ich razem ...
Wierd zna tylko dwa symbole: przestrzeń i wszystko inne. Wskaźnik instrukcji próbuje podążać ścieżką utworzoną przez znaki spacji, zaczynając po przekątnej od lewego górnego rogu i zawsze próbując iść tak prosto, jak to możliwe. Zakręty na ścieżce tworzą rzeczywiste instrukcje (ze stopniami zakrętu określającymi, która instrukcja ma zostać wykonana). Więc kod widziany przez Wierda jest następujący:
v1997 * * *
' * * *
8 * * *
* * * *
* ++++++++++++++++++++++++ ++++++++++++++++++++++++ ++O--OO++++++++OX******* *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* **** **** * **** **** * **** **** * **** *****
* * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * *
* * * **** * * * * **** * * * * **** * * * * ****
* * * * * * * * * * * * * * * *
***** ******* ****** ******* ****** ******* ****** *******
U 1997
góry nie jest właściwie wykonywane, ale Wierd pozwala nam odczytać go z kodu źródłowego, który jest o wiele krótszy niż próba skonstruowania kodów znaków dla samych czterech cyfr (nawet jeśli nie wygląda to tak ... .). Nie mam ochoty rozbijać tego wszystkiego, ale wyraźnie widać cztery powtarzające się sekcje. To powoduje, że najpierw przechowujemy 1
na stosie, a następnie każda z tych czterech sekcji zwiększa to 1
, a następnie rozgałęzia. Dolna gałąź popycha inną1
, pobiera znak źródłowy na tych współrzędnych i drukuje go, podczas gdy górna gałąź jest przekierowywana do następnej sekcji. Być może zastanawiasz się, dlaczego końce ścieżek są tak niepotrzebnie długie, ale dzieje się tak, ponieważ gdy Wierd dotrze do końca ścieżki, próbuje przeskoczyć na pobliską ścieżkę, zanim zdecyduje, że powinna zakończyć obecną gałąź. Aby tego uniknąć, musimy przenieść te końce wystarczająco daleko od jakiegokolwiek innego kodu.
Befunge otrzymało dość znaną aktualizację w 1998 roku z bardzo rygorystyczną specyfikacją, którą można uogólnić na dowolne wymiary (i myślę, że także arbitralne topologie). Jest jednak w dużej mierze kompatybilny wstecz z Befunge, co sprawia, że dość łatwo można poligotować te dwa. To Befunge wciąż nie miało żadnych mirrorów, więc wykonywana ścieżka jest taka sama jak dla Befunge 93:
v
\
>"8991",,,;5-;,@
Różnica polega na tym, że Befunge 98 nie ignoruje ;
. Zamiast tego zachowuje się trochę jak komentarz, ponieważ wszystkie polecenia do następnego ;
są ignorowane. W ten sposób, nie zmniejszamy że 8
do 3
i wydrukować 1998
jak jest.
2001: A Space Od ... PingPong
Rok 2001 to rok Piet, ale tak naprawdę nie miałem ochoty poligotować pliku obrazu za pomocą wszystkich innych programów, więc tutaj jest mniej znany język 2D. Wygląda na to, że ma sporo funkcji (z których nie będziemy korzystać). Podziękowania dla Sp3000 za znalezienie oryginalnego tłumacza (który jest jedynym martwym linkiem w zarchiwizowanej wersji oficjalnej strony internetowej).
PingPong jest nieco niezwykły, ponieważ ma tylko kopie lustrzane i nie ma <v>^
przekierowań. Więc to przesuwa się v19977
na początku, a następnie uderza w lustro, które owija go do dna. Odpowiedni kod to:
v19977/
...
/K:0:1:@
...
Rzeczywisty kod jest dość prosty: K
popycha 20
, cyfry pchają się, :
wypisuje liczbę całkowitą i @
kończy działanie programu.
Jest to pierwszy język, w którym sprawy stają się nieco łatwiejsze, ponieważ SNUSP obsługuje wyraźny punkt wejścia. Ten punkt wejścia jest oznaczony $
. Sądząc z niektórych artykułów na temat esolangów, ten język zainspirował kilka innych, ale niestety pod koniec dnia jest tylko pochodną Brainfuck. To powiedziawszy, myślę, że sposób, w jaki ustawia obecną komórkę na 48, jest dość schludny (i został skradziony z artykułu esolangs). Oto odpowiednia część kodu:
$'main' \/\/\/\
\++++++\
/++++++/
\++++++\
/++++++/
\/\/\/\++.--..+++.#
Są to 24 +
s, a mirrory wysyłają adres IP dokładnie dwa razy.
Z jakiegoś powodu, ten język nie mają <^>
przekierowań ale zamiast zwykle v
używa %
. Dlatego po prostu przesuwa się on w pierwszej linii. Odpowiedni kod to:
v19977/2{@{{4{\
Na początek wciskamy kilka cyfr, dokonujemy podziału. Następnie 2{
drukuje 2
, @
usuwa stos. {{
wypisuje dwa (niejawne) 0
. 4{
drukuje 4
i \
kończy program.
2005 był trudnym wyborem. Przez żaden inny rok nie znalazłem tylu języków 2D, a jest też REGULACJA i Archway, które zaczynają się w lewym dolnym rogu (co ułatwiłoby im dodawanie). Lubię Rail, a ponieważ ma wyraźny punkt wejścia, nie było trudno go dodać. Rail szuka linii zaczynającej się od $'main'
i zaczyna poruszać się na południowy wschód od $
. Oznacza to, że odpowiedni kod to:
$'main'
\-[2005]o-#
\
I -
są tylko tory (nie-OPS). Jest [2005]
to literał łańcuchowy, który o
wypisuje się przed #
zakończeniem programu.
Dwuwymiarowy Brainfuck. Jest jeszcze jeden interesujący język na ten rok, zwany Czarnym, który zaczyna się od współrzędnych (3,3)
(oparty na 1), co sprawiłoby, że użycie tego w poliglocie też jest interesujące. Nie mogłem jednak znaleźć tłumacza. Więc zamiast tego będziemy musieli pracować z inną pochodną BF ...
Ciekawą rzeczą w tym jest to, że nie formatuje siatki na linie z liniami, jak w większości innych języków 2D. Zamiast tego |
służy jako separator linii. Ponieważ nie korzystałem |
z żadnego innego języka, mogłem po prostu wstawić |
ostatni wiersz, co czyni całą resztę programu jedną linią, jeśli chodzi o BF.js. Odpowiedni kod jest więc następujący (zamieniając go |
w rzeczywisty wysuw linii):
v19977/2{...
}+++++[>++++++++++<-]>.--..++++++.@
BF.js nie używa <v>^
ani mirrorów. Jedynym sposobem na przekierowanie przepływu sterującego jest {}
obrócenie kierunku IP o 90 °. Te nawiasy klamrowe przenoszą adres IP do drugiej linii. Pozostała część to proste rozwiązanie Brainfuck (niezbyt dobrze golfowane), które ustawia komórkę na 50
(punkt kodowy 2
), a następnie drukuje 2006
, przesuwając nieco wartość. @
kończy program.
W tym roku naprawdę chciałem użyć DOBELA który korzysta z wielu punktów wejścia i wygląda jak LoveChild z rozszczepienia i Ziim . Niestety nie udało mi się przekonać tłumacza do pracy. Oto kolejna pochodna BF (ostatnia, obiecuję).
W przeciwieństwie do ostatniego, ten zna oba <v>^
i mirrory, więc odpowiedni kod to:
v
\'\
8
\ * ++++++++++++++++++++++++ ++++++++++++++++++++++++ ++O--OO++++++++OX
Ten nie ma zwykłej []
pętli w stylu BF (zamiast tego musisz utworzyć rzeczywistą pętlę 2D), więc po prostu zdecydowałem się na hardcode, 50
ponieważ i tak miałem mnóstwo znaków z rzędu od Wierda. Zauważ, że '
i 8
są ignorowane, *
jest to trampolina warunkowa, którą możemy zignorować, i O
jest Brainfuck .
. X
Kończy program.
Prawdopodobnie najpopularniejszy fungeoid (inny niż sam Befunge) przynajmniej wokół tych części. > <> ma zarówno <v>^
i mirrory, ale także literały łańcuchowe, więc wykonany kod jest następujący:
v
\'\02'oo100@n590@n;
Dosłowny ciąg znaków służy głównie do pominięcia \
stosowanego w BrainSpace 1.0, ale gdy już to robimy, równie dobrze możemy przesuwać pierwsze dwa znaki. oo
drukuje je. Następnie przesuwa 100
trzy cyfry, @
przesuwa górną na dolną i n
drukuje 0
pod spodem. Robimy to samo, 590
co drukuje 9
. Jeśli zastanawiasz się, dlaczego nie tylko drukuję w tej 2009
postaci, poczekaj na 2015 r., ;
Kończy program.
Ten był prosty, ponieważ ma wyraźny punkt wejścia na %
. Jednak ten tworzy 4 adresy IP we wszystkich kierunkach (stąd nazwa języka, jak sądzę) i musimy pozbyć się 3 z nich. Oto odpowiedni kod:
x
x%"2010"x
x
No tak. (W Cardinal tryb strun drukowany jest bezpośrednio zamiast wypychania znaków na stos.)
Kolejny język z wyraźnym punktem wejścia ( David Catt, który stworzył kilka innych bardzo miłych esolangów), tym razem o S
. To sprawia, że odpowiedni kod jest tą częścią:
S1^2^2^6^8MAOUOAOOF
RunR jest nieco interesujący, ponieważ większość operacji działa z rodzajem rejestru, a wartości muszą zostać jawnie przeniesione na stos w celu wykonania operacji binarnych. Cyfry same ustawiają wartości rejestru i ^
wypychają bieżący rejestr na stos. Potem M
jest mnożenie (rejestr razy wartość wyskakująca ze stosu), U
to odejmowanie, A
dodawanie, O
wyprowadzanie. F
kończy program.
Podobnie jak Wierd, Ropy próbuje śledzić sekcje znaków spacji, ale tutaj zakręty nie określają poleceń. W rzeczywistości okazuje się, że Ropy jest bardziej podobny do mojego własnego Labiryntu , ponieważ wybrany kierunek zależy od wierzchu stosu. Jednak tak naprawdę nie musimy się tym martwić, ponieważ Ropy przesuwa się wzdłuż pierwszej linii:
v19977/2{@{{4{\_______>/02&&&#????
Istnieje wiele rzeczy, które możemy zignorować aż do >
. Wszystko, co musimy wiedzieć, to że na górze stosu będzie w tym miejscu a, 4
a będzie 2
poniżej.
>
powiela 4
, /
jest podział zamieniający go w 1
. Potem pchamy 02
. &&&
łączy cztery pierwsze cyfry stosu w odwrotnej kolejności, dając 2012
. #
wyprowadza to. ????
po prostu usuwa stos, ponieważ w przeciwnym razie górna część stosu również jest wyprowadzana.
Jednym punktem zainteresowania jest to, że drugi 7
w 19977
został dodany z powodu ropy. /
Podział w ropy nie top / second
(naprzeciwko zwykłym celu, w wielu językach, na stosie), gdzie 7 / 9
da 0
. Gdybyśmy mieli zero na szczycie stosu, Ropy zrobiłby jakieś dzikie rzeczy z jego kierunkiem ruchu, więc musimy popchnąć drugi, 7
aby upewnić się, że szczyt stosu pozostaje dodatni, a Ropy porusza się na wschód.
Dzięki wyraźnym punktom wejścia ten jest łatwy. RDLU
twórz atomy (wskaźniki instrukcji) w odpowiednim kierunku, więc odpowiedni bit jest następujący:
R"2014";
Zauważ, że jest też U
kod źródłowy, ale ten atom w końcu uderza w jeden *
z Wierd, który kończy program (i ten atom zajmuje dużo więcej czasu niż R
potrzeba do wydrukowania 2014
).
Silniejsza pochodna Sp3000> <>. Jest w dużej mierze wstecznie kompatybilny z> <>, więc wykonywany kod jest nadal:
v
\'\02'oo100@n590@n;
Jednak zmieniono kierunek obrotu @
, co jest standardową sztuczką do rozróżnienia> <> i Gol> <> w poliglotach, więc ten drukuje 15
zamiast 09
. Stąd dziwność w drugiej połowie programu.
CSL jest dość interesujące, ponieważ polecenia nie są wykonywane natychmiast. Zamiast tego każde polecenie jest wypychane na stos poleceń e
i E
może być używane do wykonywania poleceń z niego. Odpowiedni kod staje się:
v19977/2{@{{4{\_______>/02&&&#???? * P+++++1P1P-1P+1E
Więc E
wykonuje cały stos poleceń, co oznacza, że rzeczy przed nim są wykonywane w odwrotnej kolejności. Musimy tylko spojrzeć na *
:
1+P1-P1P1+++++P*
Do 1
s wcisnąć się na stosie danych. +
i -
są zmniejszanie / zwiększanie. P
drukuje górę stosu. Następnie *
próbuje pomnożyć dwie najwyższe wartości stosu. Jednak stos jest pusty, więc to kończy działanie programu.
W tym momencie przechodzimy do języków, które zostały wydane po opublikowaniu tego wyzwania, więc tak naprawdę nie liczę ich za wynik, zwłaszcza że sam je stworzyłem (choć nie z myślą o tym wyzwaniu). Mają jednak nowatorską semantykę ruchu IP, która ułatwiła dopasowanie ich do poliglota, a także dodanie czegoś interesującego do tej prezentacji języków 2D.
Alice została zaprojektowana jako bogaty w fungeoid. Jedną interesującą różnicą w stosunku do większości (ale nie wszystkich) języków 2D jest to, że IP może poruszać się ortogonalnie lub ukośnie. Przełączanie się między nimi zmienia również semantykę prawie wszystkich poleceń w języku. Co więcej, Alice obsługuje zarówno tradycyjne <^>v
nastawniki kierunku, jak i \/
mirrory, ale mirrory mają bardzo wyjątkowe zachowanie w Alice (co ułatwia poprowadzenie IP Alice do dotychczas nieużywanej części kodu).
Podczas gdy większość języków leczyć \
i /
jak gdyby były lustra w kącie 45 °, a IP jako promienia świetlnego odbijając się od niego, Alice traktuje je jako posiadające 67,5 ° kąt (która jest bliżej kątem rzeczywistych glifów ukośnik) , a adres IP również przechodzi przez lustro (stąd nazwa języka). Ze względu na ten kąt lustra przełączają się między ruchem wzdłuż kierunków prostopadłych lub ukośnych. Ponadto, podczas gdy w trybie zwykłym (tzn. Gdy IP porusza się wzdłuż przekątnych), siatka nie zawija się, a zamiast tego IP odbija się od krawędzi (podczas gdy w trybie kardynalnym zawija się).
Podsumowując, kod wykonywany przez Alice jest następujący:
v19
\ \
...
> "7102"4&o@
...
Adres IP zaczyna się jak zwykle w lewym górnym rogu i v
wysyła na południe. Teraz \
odzwierciedla IP, aby przejść na północny zachód, gdzie natychmiast odbija się od lewej krawędzi siatki (i zamiast tego przesuwa się na północny wschód). 1
można zignorować, IP odbija się od górnej krawędzi, aby przejść dalej na południowy wschód. Uderzyliśmy inny, \
który odzwierciedla północ IP. 9
można również zignorować, a następnie IP zawija się w dolnej części siatki. Po kilku wierszach przekierowujemy go na wschód >
dla wygody. Następnie "7102"
przesuwa punkty kodowe 2017
, 4&o
drukuje te cztery znaki i @
kończy działanie programu.
Wumpus to pierwszy język 2D na trójkątnej siatce, który sprawia, że poruszanie się po kodzie jest zupełnie inne (i ponownie pozwala nam łatwo dotrzeć do nieużywanej części kodu). Dlatego zamiast myśleć o każdej postaci w siatce jako małym kwadracie, powinieneś myśleć o nich jako naprzemiennych trójkątach w górę i w dół. Lewy górny róg jest zawsze trójkątem skierowanym w górę.
Wumpus nie ma takich ustawień <^>v
, ale ma lustra \/
. Jednak ze względu na trójkątną siatkę działają one inaczej niż większość innych języków. IP odbija się od nich jak promień światła (jak zwykle), ale powinieneś myśleć o nich jako o kącie 60 °. Tak więc IP przemieszczające się na wschód kończy się przemieszczaniem wzdłuż północno-zachodniej osi siatki.
Kolejną różnicą w stosunku do większości innych języków jest to, że krawędzie siatki nie zawijają się, ale zamiast tego IP odbija się od krawędzi (tak jakby te komórki krawędzi zawierały odpowiednie kopie lustrzane). Kolejnym zabawnym szczegółem jest to, że przekątne przez trójkątną siatkę faktycznie wyglądają jak schody w kodzie źródłowym.
Mając to na uwadze, kod wykonywany przez Wumpusa jest następujący (w celu zastąpienia spacji .
dla przejrzystości:
v19977/
02
89
..
..
.....*...#2018O@
To v19977
tylko śmieci, które możemy zignorować. /
wysyła adres IP na północny zachód, gdzie ponownie przechodzi przez 977
(z prawej), odbijając się od górnej krawędzi. Następnie IP przesuwa się na południowy zachód przez 2089
i kilka przestrzeni, zanim trafi w lewą krawędź, aby ponownie odbić się na wschód. *
jest również śmieciami. Następnie w końcu #2018
naciska 2018
, O
drukuje i @
kończy działanie programu.
Brakujące lata
Na koniec kilka notatek o latach, których nie opisałem.
Podczas badań języków 2D w celu znalezienia odpowiednich języków, które mogłyby być używane w poliglocie, dowiedziałem się, że wbrew powszechnemu przekonaniu Befunge nie był pierwszym językiem 2D. Wydaje się, że tytuł ten należy do Bioty, która została już stworzona w 1991 roku. Niestety, język nie ma żadnych wyników, więc nie mogłem go użyć do tego wyzwania.
O ile wiem, w 1992 i 1995 r. Nie utworzono języków 2D. Pozostało kilka lat:
- 1994: Powstaje Orthagonal , niezależnie od Befunge. Języki są semantycznie całkiem podobne, ale Ortogonalnie tak naprawdę nie przedstawia kodu źródłowego w 2D. Zamiast tego każda linia jest
(x, y, instruction)
krotką. Otrzymałem nawet specyfikację języka i oryginalnego tłumacza od twórcy Jeffa Eplera, ale ostatecznie fakt, że składnia nie jest 2D, sprawił, że język nie był odpowiedni dla tego poliglota.
- 1996: Utworzono ortogonalnego następcę ortagonalnego (stworzonego przez kogoś innego), ale na potrzeby tego poliglota występują te same problemy co ortagonalne.
- 1999: Jedynym językiem, jaki mogłem znaleźć, był automat komórkowy Chris Pressey REDGREEN . Niestety, w przeciwieństwie do swojego poprzednika RUBE, nie ma on żadnej semantyki we / wy.
- 2000: Istnieje inny automat komórkowy Chrisa Presseya o nazwie noit o 'mnain worb, ale nie ma również żadnych wejść / wyjść. Jest też Numberix, którego nie próbowałem uruchomić i nie jestem pewien, czy zignorowałby znaki inne niż szesnastkowe w kodzie źródłowym.
- 2002: Jest Clunk bez I / O i ZT, których specyfikacja językowa mnie przeraża.
- 2007: Znalazłem tutaj trzy języki. Zetaplex jest oparty na obrazie (więc nie), a RubE On Conveyor Belts wydaje się wymagać nagłówka o dość ścisłym formacie, który pomieszałby się z pierwszą linią programu. Istnieje również Cellbrain firmy Quintopia, ale wydaje się również, że wymaga określonego nagłówka.
- 2013: Znów znalazłem trzy języki. Połowy mogą być możliwe z dużą ilością restrukturyzacji, ale wymagałoby to rozpoczęcia programu od ważnego doku. Quipu , z pamięci, jest zbyt surowe pod względem składni, aby pozwolić na wiele poliglotów. A Swordfish jest kolejnym członkiem rodziny> <>, ale niestety nie udało mi się znaleźć tłumacza. W przeciwnym razie ten prawdopodobnie byłby dość łatwy do dodania.
Jeśli ktoś jest zainteresowany, oto pełna lista zaimplementowanych języków 2D posortowana według lat, o ile mogłem je znaleźć (w momencie opublikowania tej odpowiedzi). Jeśli czegoś brakuje na tej liście, daj mi znać na czacie, ponieważ naprawdę byłbym zainteresowany pełną listą.