Stackylogic to język programowania oparte na logice wymyśliłem, że biorą w 0
„s i 1
” s dla wejścia i wyjścia jednego 0
lub 1
po zakończeniu.
Program Stackylogic składa się z wierszy, które mogą zawierać tylko trzy znaki, 01?
a także dokładnie jeden <
na końcu jednego z wierszy. Linie nie mogą być puste, a linia z <
musi mieć co najmniej jednego 0
, 1
lub ?
przed nim.
Oto przykładowy program, który (jak wyjaśnię) oblicza NAND dwóch bitów:
1
?<
11
?
0
Każda linia w programie Stackylogic jest uważana za stos , z dolną po lewej stronie i górną po prawej stronie. Domniemany jest pusty stos (pusta linia) przed pierwszą linią w programie i po ostatniej linii.
<
, Które będziemy nazywać się kursor , znaki stos rozpocząć się, gdy program jest uruchamiany Stackylogic. Wykonanie programu Stackylogic przebiega następująco:
Usuń górną postać ze stosu, na który wskazuje obecnie kursor.
- Jeśli znakiem jest
?
, poproś użytkownika o znak a0
lub a1
i postępuj tak, jakby to był znak. - Jeśli znak jest
0
, przesuń kursor o jeden stos w górę (do linii powyżej bieżącej linii). - Jeśli znak jest
1
, przesuń kursor o jeden stos w dół (do linii poniżej bieżącej linii).
- Jeśli znakiem jest
Jeśli stos, do którego przesuwa się kursor, jest pusty, wypisz ostatnią wartość, która została usunięta ze stosu (zawsze a
0
lub1
) i zakończ program.W przeciwnym razie, jeśli stos, na który przesuwa się kursor, nie jest pusty, wróć do kroku 1 i powtórz proces.
Zauważ, że programy Stackylogic zawsze kończą się, ponieważ ostatecznie muszą wyczerpać swoje stosy.
Przykład NAND
W programie NAND kursor zaczyna się od ?
:
1
?<
11
?
0
Zakładamy, że dane wprowadzone przez użytkownika zostaną 1
raz wyświetlone ?
, co oznacza, że kursor przesunie się w dół, dzięki czemu program będzie wyglądał następująco:
1
11<
?
0
Teraz równina 1
znajduje się na górze stosu kursora. Jest należycie wysunięty, a kursor znów się porusza:
1
1
?<
0
Załóżmy teraz, że dane wejściowe użytkownika 0
dla ?
, co oznacza, że kursor przesunie się w górę:
1
1<
0
Znów a 1
znajduje się na stosie kursora, więc kursor wysuwa się i przesuwa w dół:
1
<
0
Na koniec stos kursorów jest pusty, więc wyświetlana jest ostatnia wartość, to 1
, i program się kończy.
Jest to poprawne dla bramki NAND, ponieważ 1 NAND 0
jest 1
. To oczywiście działa na pozostałe trzy dwubitowe wejścia, jeśli chcesz to sprawdzić.
LUB Przykład
Ten program Stackylogic symuluje bramkę OR :
?
?<
Łatwo zauważyć, że początkowe wejście 1
popchnie kursor do domyślnego pustego stosu poniżej ostatniego wiersza, kończąc program i wyprowadzając to, 1
co właśnie zostało wprowadzone.
Z 00
drugiej strony, kursor dojdzie do niejawnego pustego stosu u góry, kończąc program i wysyłając ostatni 0
do wprowadzenia.
Wyzwanie
Napisz program lub funkcję, która pobiera program Stackylogic jako ciąg znaków i uruchamia go, drukując lub zwracając wynikowe 0
lub 1
.
Po ?
, możesz poprosić użytkownika o wprowadzenie 0
lub 1
wejście, lub odczytać wartość ze wstępnie ustawionego ciągu 0
„i 1
”, który również bierzesz jako dane wejściowe. (Może to być kolejny ciąg znaków do twojego programu / funkcji lub możesz po prostu założyć, że pierwszy lub ostatni wiersz łańcucha programu będzie strumieniem wejściowym).
Możesz założyć, że program jest zawsze dobrze sformułowany. Opcjonalnie możesz założyć, że programy wejściowe mają pojedynczy znak nowej linii (pamiętaj jednak, że na końcu zawsze jest ukryty pusty stos).
Najkrótszy kod w bajtach wygrywa.
Więcej przykładowych programów
ZERO
0<
ONE
1<
BUFFER
?<
NOT
1
?<
0
AND
?<
?
NAND
1
?<
11
?
0
OR
?
?<
NOR
1
?
00
?<
0
XOR(v1)
?
0
1?<
?
0
XOR(v2)
?
?<
11
?
0
XNOR(v1)
1
?
0?<
1
?
XNOR(v2)
1
?
00
?<
?
MEDIAN(v1)
1
???<
0
MEDIAN(v2)
?
1?<
??
źródło
?\1?<\??
. Alternatywnie, oto symetryczna implementacja 5-liniowa:?\?0\?<\?1\?
1\???<\0
.111\???????<\000
.Odpowiedzi:
Retina ,
79787368666563625544 bajtówLiczba bajtów zakłada kodowanie ISO 8859-1.
Dane wejściowe są przesyłane przez STDIN i oczekuje się, że będą to dane wejściowe użytkownika oddzielone dwoma wejściami liniowymi od kodu źródłowego.
Wypróbuj online! (Pierwsze dwa wiersze włączają zestaw testowy, gdzie każdy wiersz jest oddzielnym przypadkiem testowym
/
zamiast z wierszami).Nie jestem do końca pewien, co się tutaj stało.
To wydaje się być naprawdę niezręcznym rozwiązaniem inie jest to naprawdę problem, dla którego stworzono Retinę, ale z jakiegoś powodu wciąż bije wszystkie aktualne odpowiedzi.Wyjaśnienie
Ostateczna wersja tego faktycznie okazała się dość prosta.
Pierwszym etapem jest po prostu pętla (z powodu
+
opcji), która dokonuje faktycznej interpretacji języka. Etap jest pojedynczą substytucją wyrażenia regularnego, ale tak naprawdę są to trzy różne substytucje wciśnięte w jeden etap, wykorzystując fakt, że przechwytywanie grup z nieużywanych gałęzi jest po prostu uważane za puste podczas podstawienia.Przetwarzanie
?
:To po prostu bierze pierwszy znak wejścia, a następnie dopasowuje dowolne znaki, aż znajdzie
?<
, i umieszcza ten pierwszy znak przed<
(usuwanie?
).Przetwarzanie
0
:Pasuje do linii poprzedzającej a
0<
i umieszcza ją po<
usunięciu0
. (W efekcie to po prostu usuwa0
i przesuwa<
jedną linię w górę.)Przetwarzanie
1
:Prawie to samo, z wyjątkiem tego, że przesuwamy
<
jedną linię w dół podczas usuwania a1
. Ważnym szczegółem, na który należy zwrócić uwagę, jest użycie+
zamiast tego*
, że wymagamy, aby następny wiersz nie był pusty.Interesującą częścią jest ustalenie, dlaczego to działa i dlaczego nie musimy śledzić ostatniej wartości, którą podaliśmy, aby określić ostateczny wynik. Aby to zrobić, musimy rozważyć, w jaki sposób powyższa pętla może się zakończyć. Ponieważ każde możliwe dopasowanie zmienia ciąg (ponieważ co najmniej jeden znak jest z niego usuwany), musimy jedynie rozważyć przypadki, w których dopasowanie całkowicie się nie powiedzie.
Jeśli znak z przodu
<
jest?
jedynym sposobem na porażkę, to to, że nigdzie przed nim nie ma znaku nieciągłego, ale to nie może się zdarzyć, ponieważ mamy gwarancję, że zawsze jest wystarczająca ilość danych wejściowych.Jeśli przed nim
<
jest znak0
, wyrażenie regularne zawsze będzie pasować, ponieważ zawsze jest inny wiersz nad bieżącym (którym może być pusty wiersz oddzielający dane wejściowe od kodu źródłowego).Jeśli przed nim
<
znajduje się znak1
, wyrażenie regularne zakończy się niepowodzeniem, jeśli znajdziemy się w ostatnim wierszu (ponieważ¶
nie uda się dopasować) lub jeśli następny wiersz będzie pusty (ponieważ.+
nie uda się dopasować). Zauważ, że oba te przypadki odpowiadają zakończeniu programu po kliknięciu na1
.Wreszcie istnieje również możliwość, której
<
nie poprzedza żadna z nich?01
. Okazuje się, że możemy dojść do tej sytuacji tylko przez naciśnięcie przycisku0
i przejście do pustej linii, tak że<
poprzedza ją teraz linia .Tak więc, gdy program zakończy się na
1
,<
nadal będzie po nim1
. Ale jeśli program zakończy się na a0
, zostanie przeniesiony do pustej linii. Możemy łatwo przekształcić te informacje w pożądany wynik za pomocą prostego etapu dopasowania:To po prostu zlicza dopasowania
1<
ciągu. Zgodnie z powyższym rozumowaniem będzie tak,1
jeśli program zakończy się na a1
, a0
jeśli zakończy na0
.źródło
Wypukły ,
10295 bajtówCóż, język oparty na liście stosów zakodowany w języku opartym na stosie okazał się dość trudny.
Zaznacz moje słowa: otrzymam to do 100 bajtów lub mniej!EDYCJA: Sukces!Wypróbuj online!
Wprowadzanie programu odbywa się za pomocą argumentów wiersza poleceń. Wejścia
0
si1
normalnie (w TIO oznacza to separację nowej linii w polu „input”).Wyjaśnienie:
Cały kod można podzielić na trzy części:
Ten bit po prostu pobiera program wejściowy i przekształca go w tablicę linii, a także dodaje
" "
linie na początku tablicy. Ponieważ tablice wypukłe się zawijają, wystarczy mieć tylko pusty stos na początku.Ta część określa, od której linii (lub stosu) rozpocząć wykonywanie. Przeszukuje każdą linię i umieszcza poprawny numer stosu w
M
zmiennej.To jest trochę zabawy! Ciągle zapętla się, aż osiągnie linię ze spacją (
" "
) (symbolizującą pusty stos). Jeśli linia nie jest pusta, wykonuje następujące czynności:?
, wprowadź dane wejściowe i dodaj ten znak do wiersza.0
, przesuń wskaźnik linii w górę o jeden.1
, przesuń wskaźnik linii w dół o jeden.(spacja), wydrukuj ostatnio wyskakujący element i zakończ program.
źródło
32-bitowy kod maszynowy x86, 70 bajtów
W hex:
Dane wejściowe to wielowierszowy łańcuch zakończony znakiem NULL (oddzielony od linii) przekazywany przez ESI. Zakłada się, że dane wejściowe użytkownika są pierwszym wierszem. Zwraca „0” / „1” w AL.
Demontaż:
źródło
JavaScript (ES6), 136
138Zakładając zakończenie nowej linii w programie
Mniej golfa
Test
źródło
05AB1E ,
58565553515046 bajtówZaoszczędź 2 bajty dzięki Emignie ! Kod:
Wykorzystuje kodowanie CP-1252 . Wypróbuj online! .
źródło
Python 3,
147146145144 bajtów1 bajt dzięki @Lynn.
źródło
Python 3, 318
F oznacza program, z jest wprowadzany. Tak, moje zmienne nazwy są szalone.
źródło
ES6, 190 bajtów
Użyj jak
f(program, input)
źródło
[...o]
zamiasto.split``
i użyjfor
zamiastwhile
, ponieważ pozwala to przenieść dwa wyrażenia dofor
dwóch zapisujących bajtów. Kilka konkretnych wskazówek: myślę, że twojaNumber
obsada jest niepotrzebna, podobnie jak*2
rzutowanie dla ciebie, a ja po prostu czytami
używającj=0
ii[j++]
który, jak sądzę, oszczędza 11 bajtów.f=
, anonimowe funkcje są dozwolone.Java,
256255231219215213 bajtówDemo na Ideone.
Bierze program i dane wejściowe jako argumenty i zwraca wynik jako liczbę całkowitą.
źródło
for
pętlę, ale co oznacza twój pierwszy komentarz?int f(String[]I)...
i można uniknąćString[]p=I.split("\n");
int f(String[]P)
->(String[]I){...
PHP (<7.0),
195192 bajtówTraktuje program jako pierwszy argument, a każdą wartość jako dodatkowy argument.
Zauważ, że przetestowałem to ze spacjami („”,…) asn zamiast spacjami, ale i tak powinno to działać.
Daje przestarzałe powiadomienie, jeśli działa w php> 5.3.
Daje również ostrzeżenie, jeśli wyjdziesz z górnej części programu. Jednak nadal działa i działa poprawnie, więc jest w porządku.
źródło
C
264249244242C nie radzi sobie tak dobrze z manipulowaniem łańcuchami, ale jest to dość krótkie.
Działa poprzez skanowanie łańcucha w celu znalezienia kursora (
<
), przesunięcie wstecz o 1 miejsce, odczytanie polecenia, zastąpienie gotab
znakiem i przejście o jedną linię do przodu lub do tyłu. Dane wejściowe mają postać tablicy znaków C, na przykładchar array[]="1\n?<\n11\n?\n0";result = f(array);
, chociaż dozwolone są również powrotu karetki.Chociaż łańcuch wejściowy jest zmodyfikowany, długość nie jest zmieniana.
Program testowy
Uruchom ten program dla każdego przypadku testowego jako osobnego parametru, używając pojedynczego ukośnika odwrotnego zamiast znaków nowej linii. Przypadki testowe zostaną oddzielone pustą linią.
źródło