Существует много формализмов, поэтому, хотя вы можете найти другие источники полезными, я надеюсь указать это достаточно четко, чтобы они не были необходимы.
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
Эта программа в виде картинки для тех, кто мыслит визуально и считает полезным понять синтаксис:
Если вам понравился этот гольф, посмотрите на продолжение .
источник
Ответы:
Perl, 166
Беги с
perl -M5.010 file
.Все началось совершенно по-другому, но я боюсь, что во многих областях к концу оно слилось с решением Ruby. Похоже, преимущество Руби в том, что «нет сигил», а в Perl «лучшая интеграция с регулярными выражениями».
Немного подробностей изнутри, если вы не читаете Perl:
@p=<>
: прочитайте полное описание машины@p
/=/,$_{$`}=$' for split$",pop@p
: для каждого (for
) assignment (split$"
) в последней строке описания машины (@p
) найдите знак равенства (/=/
), затем присвойте значение ключу$'
hask%_
$`
$o='\w+'
: начальное состояние будет первым, чтобы соответствовать регулярному выражению Perl "символы слова"until/"/
: loop, пока мы не достигнем состояния завершения:map{($r,$o,$,,$b)=$'=~/".*?"|\S+/g if/^$o :/}@p
: loop на машинном описании@p
: когда мы находимся в строке, совпадающей с текущим состоянием (if/^$o :/
), tokenize (/".*?"|\S+/g
) оставшейся части строки$'
для переменных($r,$o,$,,$b)
. Трюк: та же самая переменная,$o
если используется первоначально для имени метки, а затем для оператора. Как только метка совпадает, оператор переопределяет ее, и поскольку метка не может (разумно) быть названа + или -, она никогда не совпадает снова.$_=$o=($_{$r}+=','cmp$o)<0?do{$_{$r}=0;$b}:$,
:- настроить регистр цели
$_{$r}
вверх или вниз (магия ASCII:','cmp'+'
1, а','cmp'-'
-1);- если результат отрицательный (
<0?
может произойти только для -)- оставайтесь в 0 (
$_{$r}=0
) и верните вторую метку$b
;- иначе верните первый (возможно, единственный) ярлык
$,
$,
вместо того,$a
чтобы его можно было приклеить к следующему токенуuntil
без пробелов между ними.say for eval,%_
: dump report (eval
) и содержимое регистров в%_
источник
/^$o :/
. Одной каретки достаточно, чтобы вы смотрели только на ярлыки.$'
. Это один символ в регулярном выражении, это будет три$c,
для учета извне. Поочередно некоторые большие, но все же меняются в регулярных выражениях.Python + C, 466 символов
Просто для удовольствия, программа на Python, которая компилирует программу RM в C, затем компилирует и запускает C.
источник
main
', 'if
' и т. Д.Хаскель, 444 персонажа
Чувак, это было тяжело! Правильная обработка сообщений с пробелами в них стоит более 70 символов. Форматирование вывода, чтобы быть более «читабельным» человеком и соответствовать примерам, стоит еще 25.
источник
where
в одну строку, разделенную точкой с запятой, вы можете сэкономить 6 символов. И я полагаю, вы можете сохранить некоторые символы в определенииq
, изменив многословный if-then-else на шаблонную защиту."-"
в определенииq
и используйте вместо этого подчеркивание.q[_,_,r,_,s,z]d|maybe t(==0)$lookup r d=n z d|t=n s$r%(-1)$d
. Но в любом случае, эта программа очень хорошая.lex
Prelude. Например, что-то подобноеf[]=[];f s=lex s>>= \(t,r)->t:f r
разделит строку на токены при правильной обработке строк в кавычках.Рубин 1.9,
214212211198195192181175173175источник
Дельфи, 646
Delphi не предлагает ничего особенного в отношении разделения строк и прочего. К счастью, у нас есть общие коллекции, которые немного помогают, но это все еще довольно простое решение:
Здесь версия с отступом и комментариями:
источник
PHP,
446441402398395389371370366 символовUngolfed
Изменения
446 -> 441 : поддерживает строки для первого состояния и некоторое небольшое сжатие.
441 -> 402 : сжатие if / else и операторы присваивания в максимально возможной степени
402 -> 398 : имена функций могут использоваться в качестве констант, которые могут использоваться как строки
398 -> 395 : использует операторы короткого замыкания
395 -> 389 : нет необходимости в остальной части
389 -> 371 : нет необходимости использовать array_key_exists ()
371 -> 370 : удалено ненужное пространство
370 -> 366 : удалено два ненужных пробела в foreach
источник
Groovy, 338
источник
.sort()
)println
- ну, хорошо!Clojure (344 символа)
С несколькими переносами строк для «читабельности»:
источник
Постскриптум () ()
(852)(718)На самом деле на этот раз. Выполняет все контрольные примеры. Это все еще требует, чтобы программа RM немедленно следовала в потоке программы.
Изменить: больше факторинга, сокращенные имена процедур.
Отступы и комментарии с добавленной программой.
источник
regline
? Разве вы не можете сэкономить много, называя их такими вещамиR
?AWK - 447
Это вывод для первого теста:
источник
Stax ,
115100 байтЗапустите и отладьте его
источник