Un autómata finito no determinista es una máquina de estados finitos donde una tupla se asigna a múltiples estados. Es decir. reemplazamos la función de transición habitual de un DFA con otra función .δ : Q × Σ → Q
Si sabe qué es un NFA, puede saltear la siguiente sección.
Definicion formal
Un NFA se describe únicamente por
- un conjunto finito de estados
- un conjunto finito de símbolos
- la función de transición
- el estado inicial
- un conjunto de estados finales
La máquina comienza en y lee una cadena finita de símbolos , para cada símbolo aplicará simultáneamente la función de función de transición con un estado actual y agregará cada nuevo conjunto de estados al conjunto de estados actuales. w ∈ Σ ∗
Desafío
Para este desafío, ignoraremos para simplificarlo, además, el alfabeto siempre será las letras (minúsculas) to \ texttt {z} \ y el conjunto de estados será \ {0 \ puntos N \} para algunos no negativo número entero N . El estado inicial siempre será 0 .a z { 0 ... N } N 0
Dada una palabra y una descripción de la NFA, su tarea es determinar todos los estados finales.
Ejemplo
Considere la cadena y la siguiente descripción:
state, symbol, new-states
0, 'a', [1]
1, 'a', [0]
1, 'b', [1,2]
La máquina comenzará en :
- leer un : nuevos estados { 1 }
- lea a : nuevos estados
- leer un : nuevos estados
- leer un : nuevos estados
- lea a : nuevos estados
Entonces, los estados finales y, por lo tanto, la salida serían .
Nota: En el paso (2), la transición del estado asigna a ya que la descripción solo incluye transiciones a conjuntos no vacíos.
Reglas
La entrada consistirá en una cadena y algún tipo de descripción de la NFA (sin transiciones ):
- la cadena de entrada siempre será elemento de
- entradas válidas (no limitadas a):
- lista / conjunto de tuplas / listas
- entrada separada de nueva línea
- la descripción de la NFA solo contendrá transiciones con conjuntos no vacíos como resultado
- puede abreviar reglas con los mismos caracteres si su resultado es el mismo (por ejemplo, reglas
0,'a',[1,2]
y0,'b',[1,2]
podría abreviarse con0,"ab",[1,2]
- puede tomar cada regla por separado (por ejemplo, la regla
0,'a',[1,2]
puede ser0,'a',[1]
y0,'a',[2]
)
- puede abreviar reglas con los mismos caracteres si su resultado es el mismo (por ejemplo, reglas
- puedes elegir letras mayúsculas si quieres
- puede tomar el número de estados como entrada
- puede asumir algún tipo de orden de las entradas (por ejemplo, ordenado por estado o símbolos)
La salida será una salida separada por lista / conjunto / nueva línea, etc. de los estados finales
- el orden no importa
- sin duplicados (ya que es un conjunto)
Casos de prueba
Estos ejemplos estarán en el formato description word -> states
donde description
hay una lista de tuplas (state,symbol,new-states)
:
[] "x" -> []
[] "" -> [0]
[(0,'a',[1]),(1,'a',[0]),(1,'b',[1,2])] "abaab" -> [1,2]
[(0,'a',[1]),(1,'a',[0]),(1,'b',[1,2])] "abc" -> []
[(0,'p',[0,1]),(0,'g',[2]),(1,'c',[1]),(1,'g',[4]),(1,'p',[2]),(2,'c',[0])] "ppcg" -> [2,4]
[(0,'f',[1]),(1,'o',[1,2]),(2,'b',[3]),(3,'a',[4]),(4,'r',[0,4])] "foobar" -> [0,4]
[(0,'f',[1]),(1,'o',[1,2]),(2,'b',[3]),(3,'a',[4]),(4,'r',[0,4])] "fooooooobar" -> [0,4]
[(0,'f',[1]),(1,'o',[1,2]),(2,'b',[3]),(3,'a',[4]),(4,'r',[0,4])] "fobarfo" -> [1,2]
[(0,'f',[1]),(1,'o',[1,2]),(2,'b',[3]),(3,'a',[4]),(4,'r',[0,4])] "foobarrf" -> [1]
[(0,'d',[1,2]),(1,'u',[2]),(2,'u',[2,3]),(2,'p',[3]),(3,'p',[3])] "dup" -> [3]
[(0,'a',[0,2]),(0,'b',[3]),(1,'a',[1]),(1,'b',[1]),(2,'b',[1,4]),(4,'b',[2])] "aab" -> [3,1,4]
[(0,'a',[0,2]),(0,'b',[3]),(1,'a',[1]),(1,'b',[1]),(2,'b',[1,4]),(4,'b',[2])] "abb" -> [1,2]
Respuestas:
Haskell , 66 bytes
Pruébalo en línea!
fuente
nub
si asume que los estados son[Int]
, luego puede usar verificar cada uno[0..]
que es finito: 60 bytesInt
s y más de todos los estados actuales y, por tanto, todavía produce estados duplicados. Ejemplo (cambió[0..]
a[0..3]
para propósitos de prueba, pero esto no debe hacer una diferencia, ¿verdad?)Brachylog , 42 bytes
entrada como [cadena, nfa] donde nfa es una lista de transiciones de estado [estado inicial, letra, nuevos estados como lista]
Explicación
Pruébalo en línea!
fuente
Brachylog v2, 31 bytes
Pruébalo en línea! ( o con un ejemplo más complejo )
Brachylog es realmente bueno en este tipo de problemas, y realmente malo en problemas que requieren dos entradas separadas y una salida. Casi todo este programa es solo fontanería.
El formato de entrada es una lista que contiene dos elementos: el primero es la lista de transiciones de estado (
[oldState, symbol, newState]
) y el segundo es la lista de símbolos. Originalmente planeé este programa para trabajar con códigos de caracteres para símbolos (porque el manejo de cadenas de Brachylog puede ser un poco extraño a veces), pero resulta que los caracteres también funcionan (aunque debe escribir la cadena de entrada como una lista de caracteres, no como una cuerda). Si un par de estado-símbolo puede hacer la transición a varios estados diferentes, debe escribir varias transiciones para lidiar con eso.Explicación
Probablemente sea más fácil seguir esto mirando lo que producirían algunas versiones parciales del programa. Usando la siguiente entrada cada vez:
Podemos observar los resultados de algunos prefijos de este programa:
Para el primer ejemplo aquí,
L
inicialmente es un elemento desconocido, pero cuando lo transponemos vía\
, Brachylog se da cuenta de que la única posibilidad es una lista con la misma longitud que la entrada. El último ejemplo aquí es no determinista; estamos modelando el no determinismo en la NFA usando el no determinismo en Brachylog.Posibles mejoras.
Parte de la sintaxis aquí, como
↔,0↔
y especialmente el desordenH&hg;Hz{…ᵈ}ᵐ
, es bastante torpe. No me sorprendería si hubiera una forma más tersa de expresar esto.{∋ᵈ}ᵐ
es, por derecho propio, una estructura bastante sospechosa (es de esperar que solo pueda escribir)∋ᵈᵐ
, pero no se analiza por alguna razón.fuente
∋ᵈᵐ
no se analiza porque está implementado de tal manera que en teoría podrían usarse nombres de meta-predicados de varios caracteres (si nos quedamos sin posibilidades de un solo símbolo). En la práctica no se usa actualmente.Python 3,
10380 bytesgracias a @BWO
TIO
Anterior comprensión de la lista "elegante" (103 bytes):
fuente
reduce
tenga ... Pero el uso de conjuntos de recursión y reales todavía te lleva a 80 bytes .if''<f
conif f
.JavaScript (ES6), 99 bytes
Toma entrada como
(nfa)(string)
. Devuelve un conjunto.Pruébalo en línea!
fuente
R , 81 bytes
Pruébalo en línea!
Respuesta directa usando
Reduce
. Toma las reglas como tres vectores destate, symbol, new-states
llamadasa,b,e
.Las reglas son separadas (por ejemplo, la regla
0,'a',[1,2]
es0,'a',1
y0,'a',2
).fuente
Coco , 64 bytes
Pruébalo en línea!
fuente
Limpio , 68 bytes
Esta basada en la solución Haskell de ovs es un poco más corta que mi enfoque inicial.
ahora incluye un arnés de prueba
Pruébalo en línea!
fuente
Carbón , 44 bytes
Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:
0
Pase sobre la entrada.
Copia el estado.
Restablecer el estado.
Pase sobre la copia del estado.
Recorrer las entradas de NFA.
Si la entrada coincide, entonces ...
... recorrer los nuevos estados ...
.... si aún no están en la lista ...
... agregarlos a la lista.
Transmita la lista de estados a una cadena para la salida implícita en líneas separadas.
fuente
Perl 6 ,
6154 bytesPruébalo en línea!
Toma una lista de transiciones de estado y una cadena de entrada como lista de caracteres.
fuente
Japt , 31 bytes
¡Intentalo!
Se guardaron 2 bytes con un mejor uso de la capacidad de Japt para formar implícitamente una función a partir de algunas entradas
Explicación:
El nuevo código "inicializar estados" podría usar un poco más de detalle. Japt se inicializa
W
a 0 si hay menos de 3 entradas, por lo que en la primera ejecución[W]
es[0]
, yc
"aplana" una matriz.[0]
ya es tan plano como se pone, por lo que no se cambia. En ejecuciones posterioresW
tiene un valor diferente, por ejemplo[1,2]
. En ese caso se[W]
convierte en[[1,2]]
una matriz de un solo elemento donde ese elemento es una matriz. Esta vezc
desenvuelve eso y vuelve a[1,2]
. Por lo tanto, en la primera ejecución esW=[0]
y en las ejecuciones posteriores esW=W
.fuente