Существует много формализмов, поэтому, хотя вы можете найти другие источники полезными, я надеюсь указать это достаточно четко, чтобы они не были необходимы.
RM состоит из конечного автомата и конечного числа именованных регистров, каждый из которых содержит неотрицательное целое число. Для простоты ввода текста эта задача требует, чтобы также были названы состояния.
Существует три типа состояний: увеличение и уменьшение, которые оба ссылаются на конкретный регистр; и прекратить. Состояние приращения увеличивает свой регистр и передает управление своему единственному преемнику. Состояние декремента имеет два преемника: если его регистр ненулевой, то он уменьшает его и передает управление первому преемнику; в противном случае (т. е. регистр равен нулю) он просто передает управление второму преемнику.
Для «правильности» в качестве языка программирования конечные состояния принимают жестко запрограммированную строку для печати (так что вы можете указать исключительное завершение).
Ввод от стандартного ввода. Формат ввода состоит из одной строки на состояние, за которой следует начальное содержимое регистра. Первая строка - это начальное состояние. БНФ для государственных линий это:
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
Существует некоторая гибкость в определении идентификатора и сообщения. Ваша программа должна принимать непустую буквенно-цифровую строку в качестве идентификатора, но она может принимать более общие строки, если вы предпочитаете (например, если ваш язык поддерживает идентификаторы с подчеркиванием, и с вами легче работать). Точно так же для сообщения вы должны принять непустую строку буквенно-цифровых символов и пробелов, но вы можете принять более сложные строки, которые позволяют экранированные символы новой строки и двойные кавычки, если хотите.
Последняя строка ввода, которая дает начальные значения регистра, представляет собой разделенный пробелами список присваиваний идентификатора = int, который должен быть непустым. Не требуется, чтобы он инициализировал все регистры, названные в программе: любые, которые не инициализированы, предполагаются равными 0.
Ваша программа должна читать входные данные и моделировать RM. Когда он достигает состояния завершения, он должен выдать сообщение, символ новой строки, а затем значения всех регистров (в любом удобном для человека формате или в любом порядке).
Примечание: формально регистры должны содержать неограниченные целые числа. Однако вы можете, если хотите, предположить, что значение регистра не будет превышать 2 ^ 30.
Несколько простых примеров
a + = b, a = 0s0 : a - s1 "Ok"
s1 : b + s0
a=3 b=4
Ожидаемые результаты:
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
Ожидаемые результаты:
Ok
a=3 b=7 t=0
Тестовые случаи для более сложных машин
s0 : t - s0 s1
s1 : t + "t is 1"
t=17
Ожидаемые результаты:
t is 1
t=1
а также
s0 : t - "t is nonzero" "t is zero"
t=1
Ожидаемые результаты:
t is nonzero
t=0
Более сложный пример
Взято из проблемы кода проблемы DailyWTF Джозефуса. Входными данными являются n (количество солдат) и k (продвижение), а выходными данными r является (индексированная нулями) позиция выжившего человека.
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
Ожидаемые результаты:
Ok
i=40 k=3 n=0 r=27 t=0
Эта программа в виде картинки для тех, кто мыслит визуально и считает полезным понять синтаксис:
Если вам понравился этот гольф, посмотрите на продолжение .