Istnieje wiele formalizmów, więc chociaż mogą okazać się przydatne inne źródła, mam nadzieję, że sprecyzuję to na tyle jasno, że nie będą one konieczne.
RM składa się ze skończonej maszyny stanów i skończonej liczby nazwanych rejestrów, z których każdy zawiera nieujemną liczbę całkowitą. Aby ułatwić wprowadzanie tekstu, zadanie to wymaga również nazwania stanów.
Istnieją trzy rodzaje stanów: inkrementacja i dekrementacja, które odnoszą się do określonego rejestru; i zakończyć. Stan przyrostowy zwiększa rejestr i przekazuje kontrolę jednemu następcy. Stan dekrementacji ma dwóch następców: jeśli jego rejestr jest różny od zera, to dekrementuje go i przekazuje kontrolę pierwszemu następcy; w przeciwnym razie (tzn. rejestr ma wartość zero), po prostu przekazuje kontrolę drugiemu następcy.
W przypadku „niceness” jako języka programowania, stany zakończenia wymagają wydrukowania na stałe łańcucha (abyś mógł wskazać wyjątkowe zakończenie).
Dane wejściowe pochodzą ze standardowego wejścia. Format wejściowy składa się z jednej linii na stan, po której następuje początkowa zawartość rejestru. Pierwszy wiersz to stan początkowy. BNF dla linii stanu to:
line ::= inc_line
| dec_line
inc_line ::= label ' : ' reg_name ' + ' state_name
dec_line ::= label ' : ' reg_name ' - ' state_name ' ' state_name
state_name ::= label
| '"' message '"'
label ::= identifier
reg_name ::= identifier
Istnieje pewna elastyczność w definicji identyfikatora i komunikatu. Twój program musi zaakceptować niepusty łańcuch znaków alfanumerycznych jako identyfikator, ale jeśli wolisz, może zaakceptować bardziej ogólne ciągi znaków (np. Jeśli Twój język obsługuje identyfikatory z podkreślnikami i jest to łatwiejsze w pracy). Podobnie do wiadomości, którą musi zaakceptować niepusty ciąg znaków alfanumerycznych i przestrzeni, ale mogą przyjąć bardziej skomplikowanych ciągów znaków, które pozwalają uciekły nowe linie i znaki cudzysłowu, jeśli chcesz.
Ostatni wiersz danych wejściowych, który podaje początkowe wartości rejestru, to oddzielona spacjami lista przypisań identyfikator = int, które muszą być niepuste. Nie jest wymagane, aby inicjalizowało wszystkie rejestry nazwane w programie: zakłada się, że każdy, który nie został zainicjowany, ma wartość 0.
Twój program powinien odczytać dane wejściowe i zasymulować RM. Kiedy osiągnie stan końcowy, powinien wyemitować komunikat, nowy wiersz, a następnie wartości wszystkich rejestrów (w dowolnym dogodnym, czytelnym dla człowieka formacie i dowolnej kolejności).
Uwaga: formalnie rejestry powinny zawierać nieograniczone liczby całkowite. Możesz jednak założyć, że wartość rejestru nigdy nie przekroczy 2 ^ 30.
Kilka prostych przykładów
a + = b, a = 0s0 : a - s1 "Ok"
s1 : b + s0
a=3 b=4
Oczekiwane rezultaty:
Ok
a=0 b=7
b + = a, t = 0
init : t - init d0
d0 : a - d1 a0
d1 : b + d2
d2 : t + d0
a0 : t - a1 "Ok"
a1 : a + a0
a=3 b=4
Oczekiwane rezultaty:
Ok
a=3 b=7 t=0
Przypadki testowe dla maszyn trudniejszych do analizy
s0 : t - s0 s1
s1 : t + "t is 1"
t=17
Oczekiwane rezultaty:
t is 1
t=1
i
s0 : t - "t is nonzero" "t is zero"
t=1
Oczekiwane rezultaty:
t is nonzero
t=0
Bardziej skomplikowany przykład
Zaczerpnięte z wyzwania DailyWTF z kodem problemu Josephusa. Dane wejściowe to n (liczba żołnierzy) ik (postęp), a dane wyjściowe w r to pozycja (o indeksie zerowym) osoby, która przeżyła.
init0 : k - init1 init3
init1 : r + init2
init2 : t + init0
init3 : t - init4 init5
init4 : k + init3
init5 : r - init6 "ERROR k is 0"
init6 : i + init7
init7 : n - loop0 "ERROR n is 0"
loop0 : n - loop1 "Ok"
loop1 : i + loop2
loop2 : k - loop3 loop5
loop3 : r + loop4
loop4 : t + loop2
loop5 : t - loop6 loop7
loop6 : k + loop5
loop7 : i - loop8 loopa
loop8 : r - loop9 loopc
loop9 : t + loop7
loopa : t - loopb loop7
loopb : i + loopa
loopc : t - loopd loopf
loopd : i + loope
loope : r + loopc
loopf : i + loop0
n=40 k=3
Oczekiwane rezultaty:
Ok
i=40 k=3 n=0 r=27 t=0
Ten program jako obraz dla tych, którzy myślą wizualnie i uznaliby, że pomocne byłoby uchwycenie składni:
Jeśli podobał ci się ten golf, spójrz na kontynuację .