Ein nicht deterministischer endlicher Automat ist eine endliche Zustandsmaschine, bei der ein Tupel auf mehrere Zustände abgebildet wird. Dh Wir ersetzen die übliche Übergangsfunktion eines DFA durch eine andere Funktion .
Wenn Sie wissen, was eine NFA ist, können Sie den nächsten Abschnitt überspringen.
Formale Definition
Eine NFA wird von eindeutig beschrieben
- eine endliche Menge von Zuständen
- eine endliche Menge von Symbolen
- die Übergangsfunktion
- der Ausgangszustand
- eine Menge von Endzuständen
Die Maschine beginnt in und liest eine endliche Kette von Symbolen w ∈ & Sigma; * , für jedes Symbol wird es gleichzeitig die Übergangsfunktion Funktion mit einem aktuellen Zustand anzuwenden und jeden neuen Satz von Zuständen auf den Satz von aktuellen Zuständen hinzuzufügen.
Herausforderung
Für diese Aufgabe werden wir ignorieren , um sie zu vereinfachen. Außerdem besteht das Alphabet immer aus den (Klein-) Buchstaben a bis z und die Menge der Zustände für eine nicht negative ganze Zahl N ist { 0 … N } . Der Ausgangszustand ist immer 0 .
Mit einem gegebenen Wort und einer Beschreibung der NFA besteht Ihre Aufgabe darin, alle Endzustände zu bestimmen.
Beispiel
Betrachten Sie die Zeichenfolge und die folgende Beschreibung:
state, symbol, new-states
0, 'a', [1]
1, 'a', [0]
1, 'b', [1,2]
Die Maschine startet in :
- lese ein : neue Staaten { 1 }
- lese a : neue Staaten { 1 , 2 }
- lese ein : new states { 0 }
- lese ein : neue Staaten { 1 }
- lese a : neue Staaten { 1 , 2 }
Die Endzustände und damit die Ausgabe wären also .
Hinweis: In Schritt (2) wird der Übergang von Zustand auf ∅ abgebildet, da die Beschreibung nur Übergänge zu nicht leeren Mengen enthält.
Regeln
Die Eingabe besteht aus einem String und einer Beschreibung der NFA (ohne -Übergänge):
- Die Eingabezeichenfolge ist immer ein Element von
- gültige Eingaben (nicht beschränkt auf):
- Liste / Array von Tupeln / Listen
- durch neue Zeile getrennte Eingabe
- Die Beschreibung des NFA enthält nur Übergänge mit nicht leeren Mengen als Ergebnis
- Sie können Regeln mit den gleichen Zeichen abkürzen , wenn deren Ergebnis das gleiche ist (z. B. Regeln
0,'a',[1,2]
und0,'b',[1,2]
könnte mit abgekürzt0,"ab",[1,2]
- Sie können jede Regel separat nehmen (zB Regel
0,'a',[1,2]
kann0,'a',[1]
und sein0,'a',[2]
)
- Sie können Regeln mit den gleichen Zeichen abkürzen , wenn deren Ergebnis das gleiche ist (z. B. Regeln
- Sie können auch Großbuchstaben wählen, wenn Sie möchten
- Sie können die Anzahl der Zustände als Eingabe verwenden
- Sie können davon ausgehen, dass die Eingaben in einer bestimmten Reihenfolge vorliegen (z. B. sortiert nach Bundesstaat oder Symbolen).
Die Ausgabe ist eine Liste / Menge / durch neue Zeilen getrennte Ausgabe usw. der Endzustände
- Ordnung spielt keine Rolle
- keine Duplikate (als Set)
Testfälle
Diese Beispiele werden in dem Format sein , description word -> states
wo Sie description
eine Liste von Tupeln (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]
Antworten:
Haskell , 66 Bytes
Probieren Sie es online!
quelle
nub
wenn Sie annehmen, dass die Zustände sind[Int]
, dann können Sie jedes überprüfen,[0..]
das endlich ist: 60 BytesInt
s und über alle aktuellen Zustände und erzeugt daher immer noch doppelte Zustände. Beispiel ([0..]
zu[0..3]
Testzwecken geändert , aber das sollte keinen Unterschied machen, oder?)Brachylog , 42 Bytes
Eingabe als [string, nfa] wobei nfa eine Liste von Zustandsübergängen ist [Anfangszustand, Buchstabe, neue Zustände als Liste]
Erläuterung
Probieren Sie es online!
quelle
Brachylog v2, 31 Bytes
Probieren Sie es online!( oder mit einem komplexeren Beispiel )
Brachylog ist wirklich gut in dieser Art von Problemen und wirklich schlecht in Problemen, die zwei separate Eingänge und einen Ausgang erfordern. Fast das ganze Programm ist nur Sanitär.
Das Eingabeformat ist eine Liste mit zwei Elementen: Das erste ist die Liste der Statusübergänge (
[oldState, symbol, newState]
) und das zweite ist die Liste der Symbole. Ursprünglich plante ich dieses Programm, um mit Zeichencodes für Symbole zu arbeiten (da Brachylogs Umgang mit Zeichenfolgen manchmal etwas seltsam sein kann), aber es stellt sich heraus, dass Zeichen auch funktionieren (obwohl Sie die Eingabezeichenfolge als Liste von Zeichen schreiben müssen, nicht als ein Faden). Wenn ein Zustand-Symbol-Paar in mehrere verschiedene Zustände übergehen kann, schreiben Sie mehrere Übergänge, um damit umzugehen.Erläuterung
Es ist wahrscheinlich einfacher, dies zu verfolgen, indem Sie sich ansehen, was einige Teilversionen des Programms hervorbringen würden. Verwenden Sie jedes Mal die folgenden Eingaben:
wir können die Ausgaben einiger Präfixe dieses Programms beobachten:
Für das erste Beispiel ist hier
L
zunächst ein unbekanntes Element, aber wenn wir es über transponieren\
, erkennt Brachylog, dass die einzige Möglichkeit eine Liste mit der gleichen Länge wie die Eingabe ist. Das letzte Beispiel ist hier nicht deterministisch; Wir modellieren den Nichtdeterminismus in der NFA mithilfe des Nichtdeterminismus in Brachylog.Mögliche Verbesserungen
Ein Teil der Syntax hier, wie
↔,0↔
und vor allem das DurcheinanderH&hg;Hz{…ᵈ}ᵐ
, ist ziemlich klobig. Es würde mich nicht überraschen, wenn es einen genaueren Weg gäbe, dies auszudrücken.{∋ᵈ}ᵐ
ist an sich eine ziemlich verdächtige Struktur - man würde erwarten, dass man nur schreiben kann∋ᵈᵐ
- aber sie wird aus irgendeinem Grund nicht analysiert.quelle
∋ᵈᵐ
Analysiert nicht, da es so implementiert ist, dass theoretisch Namen mit Meta-Prädikaten aus mehreren Zeichen verwendet werden können (wenn uns die Möglichkeiten für einzelne Symbole ausgehen). In der Praxis wird es derzeit nicht verwendet.Python 3,
10380 Bytesdanke an @BWO
TIO
Vorheriges "elegantes" Listenverständnis (103 Bytes):
quelle
reduce
. Die Verwendung von Rekursions- und tatsächlichen Mengen bringt Sie jedoch immer noch auf 80 Byte .if''<f
mitif f
.JavaScript (ES6), 99 Byte
Übernimmt die Eingabe als
(nfa)(string)
. Gibt ein Set zurück.Probieren Sie es online!
quelle
R , 81 Bytes
Probieren Sie es online!
Einfache Antwort mit
Reduce
. Nimmt Regeln als drei Vektoren vonstate, symbol, new-states
aufgerufena,b,e
.Regeln sind getrennt (zB Regel
0,'a',[1,2]
ist0,'a',1
und0,'a',2
).quelle
Kokosnuss , 64 Bytes
Probieren Sie es online!
quelle
Sauber , 68 Bytes
Diese, die auf der Haskell-Lösung von ovs basiert, ist etwas kürzer als mein ursprünglicher Ansatz.
Enthält jetzt ein Testgeschirr
Probieren Sie es online!
quelle
Kohle , 44 Bytes
Probieren Sie es online! Link ist eine ausführliche Version des Codes. Erläuterung:
Drücken Sie{ 0 } .
0
auf die vordefinierte leere Liste, um den Anfangszustand auf zu setzenSchleife über den Eingang.
Kopieren Sie den Zustand.
Setzen Sie den Zustand zurück.
Schleife über die Kopie des Staates.
Schleife über die NFA-Einträge.
Wenn der Eintrag übereinstimmt, dann ...
... Schleife über die neuen Staaten ...
.... wenn sie noch nicht in der Liste sind ...
... füge sie der Liste hinzu.
Konvertieren Sie die Liste der Status in eine Zeichenfolge für die implizite Ausgabe in separaten Zeilen.
quelle
Perl 6 ,
6154 BytesProbieren Sie es online!
Nimmt eine Liste von Statusübergängen und eine Eingabezeichenfolge als Liste von Zeichen.
quelle
Japt , 31 Bytes
Versuch es!
2 Bytes gespart, wobei Japts Fähigkeit, aus einigen Eingaben implizit eine Funktion zu bilden, besser genutzt wurde
Erläuterung:
Der neue Code "Zustände initialisieren" könnte etwas detaillierter sein. Japt initialisiert
W
auf 0 , wenn es weniger als 3 - Eingänge sind, so auf dem ersten Durchlauf[W]
ist[0]
, undc
„abflacht“ ein Array.[0]
ist schon so flach wie es nur geht, also wird es nicht verändert. Bei nachfolgenden LäufenW
hat beispielsweise ein anderer Wert[1,2]
. In diesem Fall[W]
wird[[1,2]]
ein Einzelelement-Array, bei dem dieses Element ein Array ist. Dieses Malc
packt es aus und geht zurück zu[1,2]
. So ist es im ersten LaufW=[0]
und in den nachfolgenden LäufenW=W
.quelle