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ę .
źródło
Odpowiedzi:
Perl, 166
Uruchom z
perl -M5.010 file
.Zaczęło się zupełnie inaczej, ale obawiam się, że pod koniec zbiegło się z rozwiązaniem Ruby w wielu obszarach. Wydaje się, że zaletą Ruby jest „brak pieczęci”, a „lepsza integracja wyrażeń regularnych Perla”.
Trochę szczegółów z wnętrza, jeśli nie czytasz Perla:
@p=<>
: przeczytaj cały opis maszyny do@p
/=/,$_{$`}=$' for split$",pop@p
: dla każdegofor
przypisania (split$"
) w ostatnim wierszu opisu maszyny (@p
) zlokalizuj znak równości (/=/
), a następnie przypisz wartość$'
do%_
klucza skrótu$`
$o='\w+'
: stan początkowy byłby pierwszym, który będzie pasował do wyrażenia regularnego Perla „wyrażenie słowne”until/"/
: pętla, aż osiągniemy stan zakończenia:map{($r,$o,$,,$b)=$'=~/".*?"|\S+/g if/^$o :/}@p
: zapętlenie opisu maszyny@p
: gdy jesteśmy w linii dopasowującej aktualny stan (if/^$o :/
), tokenize (/".*?"|\S+/g
) resztę linii$'
do zmiennych($r,$o,$,,$b)
. Sztuczka: ta sama zmienna,$o
jeśli początkowo jest używana dla nazwy etykiety, a następnie dla operatora. Gdy tylko etykieta się zgadza, operator ją zastępuje, a ponieważ etykieta nie może (rozsądnie) nazywać się + lub -, nigdy więcej nie pasuje.$_=$o=($_{$r}+=','cmp$o)<0?do{$_{$r}=0;$b}:$,
:- dostosuj rejestr docelowy w
$_{$r}
górę lub w dół (magia ASCII:','cmp'+'
wynosi 1, a','cmp'-'
-1);- jeśli wynik jest ujemny (
<0?
, może się zdarzyć tylko dla -)- to pozostań na 0 (
$_{$r}=0
) i zwróć drugą etykietę$b
;- w przeciwnym razie zwróć pierwszą (prawdopodobnie jedyną) etykietę
$,
$,
zamiast$a
tego można go przykleić do następnego tokenauntil
bez odstępów między nimi.say for eval,%_
: zrzut raportu (eval
) i zawartość rejestrów w%_
źródło
/^$o :/
. Samo daszek wystarczy, abyś patrzył tylko na etykiety.$'
. Jest jedną postacią w wyrażeniu regularnym, którą można przypisać$c,
do trzech z zewnątrz. Na przemian niektóre większe, ale jeszcze zmienione wyrażenia regularne.Python + C, 466 znaków
Dla zabawy program w języku Python, który kompiluje program RM do C, a następnie kompiluje i uruchamia C.
źródło
main
”, „if
” itp.Haskell, 444 znaki
Człowieku, to było trudne! Prawidłowa obsługa wiadomości ze spacjami kosztuje ponad 70 znaków. Formatowanie wyjściowe, aby było bardziej „czytelne dla człowieka”, i pasujące do przykładów kosztowało kolejne 25.
źródło
where
w jednym wierszu oddzielonym średnikami może zaoszczędzić 6 znaków. I myślę, że możesz zaoszczędzić trochę znaków w definicjiq
, zmieniając pełne słowo „jeśli-to-jeszcze” na strażnika wzorów."-"
w definicjiq
i użyj zamiast tego podkreślenia.q[_,_,r,_,s,z]d|maybe t(==0)$lookup r d=n z d|t=n s$r%(-1)$d
. Ale tak czy inaczej, ten program jest bardzo dobry w golfa.lex
z Preludium. Na przykład coś podobnegof[]=[];f s=lex s>>= \(t,r)->t:f r
podzieli linię na tokeny, poprawnie obsługując cytowane ciągi.Ruby 1.9,
214212211198195192181175173175źródło
Delphi, 646
Delphi nie oferuje wiele w odniesieniu do dzielenia ciągów znaków i innych rzeczy. Na szczęście mamy kolekcje ogólne, co trochę pomaga, ale wciąż jest to dość duże rozwiązanie:
Tutaj wersja z wcięciem i komentarzem:
źródło
PHP,
446441402398395389371370366 znakówNie golfił
Dziennik zmian
446 -> 441 : Obsługuje ciągi znaków dla pierwszego stanu i niewielką kompresję
441 -> 402 : Skompresowane jeśli / else i instrukcje przypisania w jak największym stopniu
402 -> 398 : Nazwy funkcji mogą być użyte jako stałe, które mogą być użyte jako ciągi
398 -> 395 : Wykorzystuje operatory zwarć
395 -> 389 : Nie ma potrzeby korzystania z drugiej części
389 -> 371 : Nie trzeba używać array_key_exists ()
371 -> 370 : Usunięto niepotrzebne miejsce
370 -> 366 : Usunięto dwa niepotrzebne spacje w foreach
źródło
Groovy, 338
źródło
.sort()
)println
- no cóż!Clojure (344 znaków)
Z kilkoma liniami podziału dla „czytelności”:
źródło
Postscript () ()
(852)(718)Tym razem dla reali. Wykonuje wszystkie przypadki testowe. Nadal wymaga, aby program RM natychmiast podążał za strumieniem programu.
Edycja: Więcej faktoringu, skrócone nazwy procedur.
Wcięte i skomentowane dołączonym programem.
źródło
regline
? Czy nie możesz dużo zaoszczędzić, nazywając je takimi rzeczamiR
?AWK - 447
To jest wynik pierwszego testu:
źródło
Stax ,
115100 bajtówUruchom i debuguj
źródło