Existem muitos formalismos, portanto, embora você possa encontrar outras fontes úteis, espero especificar isso com clareza suficiente para que não sejam necessárias.
Um RM consiste em uma máquina de estados finitos e um número finito de registros nomeados, cada um dos quais contém um número inteiro não negativo. Para facilitar a entrada de texto, esta tarefa requer que os estados também sejam nomeados.
Existem três tipos de estado: incremento e decremento, que referenciam um registro específico; e terminar. Um estado de incremento incrementa seu registro e passa o controle para seu sucessor. Um estado de decréscimo possui dois sucessores: se seu registro é diferente de zero, ele o diminui e passa o controle para o primeiro sucessor; caso contrário (ou seja, o registro é zero), ele simplesmente passa o controle para o segundo sucessor.
Para "gentileza" como linguagem de programação, os estados de terminação levam uma string codificada para imprimir (para que você possa indicar uma terminação excepcional).
A entrada é de stdin. O formato de entrada consiste em uma linha por estado, seguida pelo conteúdo inicial do registro. A primeira linha é o estado inicial. O BNF para as linhas de estado é:
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
Há alguma flexibilidade na definição de identificador e mensagem. Seu programa deve aceitar uma sequência alfanumérica não vazia como identificador, mas pode aceitar sequências mais genéricas, se você preferir (por exemplo, se o seu idioma suportar identificadores com sublinhados e for mais fácil trabalhar com ele). Da mesma forma, para a mensagem, você deve aceitar uma sequência não-vazia de alfanuméricos e espaços, mas pode aceitar sequências mais complexas que permitam novas linhas de escape e aspas duplas, se desejar.
A linha final de entrada, que fornece os valores iniciais do registro, é uma lista separada por espaços das atribuições identifier = int, que devem estar não vazias. Não é necessário que ele inicialize todos os registros nomeados no programa: qualquer um que não seja inicializado será assumido como 0.
Seu programa deve ler a entrada e simular o RM. Quando atingir um estado final, deve emitir a mensagem, uma nova linha e, em seguida, os valores de todos os registros (em qualquer formato conveniente, legível por humanos, e em qualquer ordem).
Nota: formalmente os registradores devem conter números inteiros ilimitados. No entanto, você pode, se desejar, assumir que o valor de nenhum registro excederá 2 ^ 30.
Alguns exemplos simples
a + = b, a = 0s0 : a - s1 "Ok"
s1 : b + s0
a=3 b=4
Resultados esperados:
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
Resultados esperados:
Ok
a=3 b=7 t=0
Casos de teste para máquinas mais difíceis de analisar
s0 : t - s0 s1
s1 : t + "t is 1"
t=17
Resultados esperados:
t is 1
t=1
e
s0 : t - "t is nonzero" "t is zero"
t=1
Resultados esperados:
t is nonzero
t=0
Um exemplo mais complicado
Retirado do desafio de código de problema Josephus do DailyWTF. A entrada é n (número de soldados) ek (avanço) e a saída em r é a posição (indexada a zero) da pessoa que sobrevive.
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
Resultados esperados:
Ok
i=40 k=3 n=0 r=27 t=0
Esse programa como uma imagem, para aqueles que pensam visualmente e acham útil entender a sintaxe:
Se você gostou deste golfe, dê uma olhada na sequência .