Hay muchos formalismos, por lo que si bien puede encontrar otras fuentes útiles, espero especificar esto con suficiente claridad como para que no sean necesarias.
Un RM consta de una máquina de estados finitos y un número finito de registros con nombre, cada uno de los cuales contiene un número entero no negativo. Para facilitar la entrada de texto, esta tarea requiere que también se nombren los estados.
Hay tres tipos de estado: incremento y decremento, que hacen referencia a un registro específico; y terminar. Un estado de incremento incrementa su registro y pasa el control a su único sucesor. Un estado decreciente tiene dos sucesores: si su registro no es cero, lo decrementa y pasa el control al primer sucesor; de lo contrario (es decir, el registro es cero) simplemente pasa el control al segundo sucesor.
Para "amabilidad" como lenguaje de programación, los estados de terminación toman una cadena codificada para imprimir (para que pueda indicar una terminación excepcional).
La entrada es de stdin. El formato de entrada consta de una línea por estado, seguido del contenido del registro inicial. La primera línea es el estado inicial. BNF para las líneas estatales es:
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
Existe cierta flexibilidad en la definición de identificador y mensaje. Su programa debe aceptar una cadena alfanumérica no vacía como identificador, pero puede aceptar cadenas más generales si lo prefiere (por ejemplo, si su idioma admite identificadores con guiones bajos y es más fácil trabajar con usted). De manera similar, para el mensaje debe aceptar una cadena no vacía de caracteres alfanuméricos y espacios, pero puede aceptar cadenas más complejas que permitan líneas salientes y comillas dobles si lo desea.
La última línea de entrada, que proporciona los valores de registro iniciales, es una lista separada por espacios de asignaciones identificador = int, que no debe estar vacía. No es necesario que inicialice todos los registros nombrados en el programa: se supone que cualquiera que no esté inicializado es 0.
Su programa debe leer la entrada y simular el RM. Cuando alcanza un estado de terminación, debe emitir el mensaje, una nueva línea y luego los valores de todos los registros (en cualquier formato conveniente, legible para humanos y en cualquier orden).
Nota: formalmente los registros deben contener enteros ilimitados. Sin embargo, si lo desea, puede suponer que el valor de ningún registro superará los 2 ^ 30.
Algunos ejemplos simples
a + = b, a = 0s0 : a - s1 "Ok"
s1 : b + s0
a=3 b=4
Resultados previstos:
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 previstos:
Ok
a=3 b=7 t=0
Casos de prueba para máquinas más difíciles de analizar
s0 : t - s0 s1
s1 : t + "t is 1"
t=17
Resultados previstos:
t is 1
t=1
y
s0 : t - "t is nonzero" "t is zero"
t=1
Resultados previstos:
t is nonzero
t=0
Un ejemplo mas complicado
Tomado del desafío del código del problema Josephus del DailyWTF. La entrada es n (número de soldados) yk (avance) y la salida en r es la posición (indexada a cero) de la persona 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 previstos:
Ok
i=40 k=3 n=0 r=27 t=0
Ese programa como una imagen, para aquellos que piensan visualmente y les sería útil comprender la sintaxis:
Si disfrutaste este golf, mira la secuela .
fuente
Respuestas:
Perl, 166
Corre con
perl -M5.010 file
.Comenzó muy diferente, pero me temo que convergió con la solución Ruby en muchas áreas hacia el final. Parece que la ventaja de Ruby es "sin sigilos" y la "mejor integración de expresiones regulares" de Perl.
Un poco de detalle de las entrañas, si no lees a Perl:
@p=<>
: lea la descripción completa de la máquina para@p
/=/,$_{$`}=$' for split$",pop@p
: para cada (for
) asignación (split$"
) en la última línea de descripción de la máquina (@p
), ubique el signo igual (/=/
) y luego asigne el valor$'
a la%_
clave$`
$o='\w+'
: el estado inicial sería el primero en coincidir con los "caracteres de palabras" de expresiones regulares de Perluntil/"/
: bucle hasta llegar a un estado de terminación:map{($r,$o,$,,$b)=$'=~/".*?"|\S+/g if/^$o :/}@p
: descripción del bucle en la máquina@p
: cuando estamos en la línea que coincide con el estado actual (if/^$o :/
), tokenize (/".*?"|\S+/g
) el resto de la línea$'
a las variables($r,$o,$,,$b)
. Truco: la misma variable$o
si se usa inicialmente para el nombre de la etiqueta y luego para el operador. Tan pronto como la etiqueta coincida, el operador la anula y, como una etiqueta no puede (razonablemente) llamarse + o -, nunca vuelve a coincidir.$_=$o=($_{$r}+=','cmp$o)<0?do{$_{$r}=0;$b}:$,
:- ajustar el registro objetivo
$_{$r}
hacia arriba o hacia abajo (ASCII magic:','cmp'+'
es 1 mientras que','cmp'-'
es -1);- si el resultado es negativo (
<0?
solo puede ocurrir para -), entonces permanezca en 0 (
$_{$r}=0
) y devuelva la segunda etiqueta$b
;- de lo contrario, devuelva la primera etiqueta (posiblemente única)
$,
$,
lugar de$a
por lo que se puede pegar al siguiente tokenuntil
sin espacios en blanco en el medio.say for eval,%_
: volcar informe (eval
) y contenido de registros en%_
fuente
/^$o :/
. El cuidado solo es suficiente para garantizar que solo esté mirando las etiquetas.$'
. Es un personaje en la expresión regular, serían tres$c,
para tener en cuenta desde el exterior. Alternativamente, algunos más grandes pero cambian a la expresión regular de tokenización.Python + C, 466 caracteres
Solo por diversión, un programa de Python que compila el programa RM en C, luego compila y ejecuta el C.
fuente
main
', 'if
', etc.Haskell, 444 caracteres
Hombre, eso fue duro! El manejo adecuado de los mensajes con espacios en ellos cuesta más de 70 caracteres. El formato de salida para ser más "legible para los humanos" y coincidir con los ejemplos cuesta otros 25.
fuente
where
en una sola línea separada por punto y coma podría ahorrarle 6 caracteres. Y supongo que podría guardar algunos caracteres en la definición deq
cambiar el verbose if-then-else a un patrón protector."-"
en la definiciónq
y use un guión bajo en su lugar.q[_,_,r,_,s,z]d|maybe t(==0)$lookup r d=n z d|t=n s$r%(-1)$d
. Pero de todos modos, este programa es muy bueno.lex
el Preludio. Por ejemplo, algo asíf[]=[];f s=lex s>>= \(t,r)->t:f r
dividirá una línea en tokens mientras maneja las cadenas entre comillas correctamente.Ruby 1.9,
214212211198195192181175173175fuente
Delfos, 646
Delphi no ofrece mucho con respecto a la división de cadenas y otras cosas. Afortunadamente, tenemos colecciones genéricas, lo que ayuda un poco, pero esta sigue siendo una solución bastante amplia:
Aquí la versión sangrada y comentada:
fuente
PHP,
446441402398395389371370366 caracteresSin golf
Registro de cambios
446 -> 441 : admite cadenas para el primer estado, y algo de compresión leve
441 -> 402 : comprime si / sino y asignaciones tanto como sea posible
402 -> 398 : los nombres de funciones se pueden usar como constantes que se pueden usar como cadenas
398 -> 395 : Utiliza operadores de cortocircuito
395 -> 389 : No necesita la parte más
389 -> 371 : No necesita usar array_key_exists ()
371 -> 370 : Espacio innecesario eliminado
370 -> 366 : Eliminado dos espacios innecesarios en el foreach
fuente
Groovy, 338
fuente
.sort()
)println
... ¡ah!Clojure (344 caracteres)
Con algunos saltos de línea para "legibilidad":
fuente
Postscript () ()
(852)(718)De verdad esta vez. Ejecuta todos los casos de prueba. Todavía requiere que el programa RM siga inmediatamente en la secuencia del programa.
Editar: más factoring, nombres de procedimientos reducidos.
Sangrado y comentado con el programa adjunto.
fuente
regline
? ¿No puedes ahorrar mucho llamándolos cosas asíR
?AWK - 447
Este es el resultado de la primera prueba:
fuente
Stax ,
115100 bytesEjecutar y depurarlo
fuente