progs/nfa.scala
changeset 487 a697421eaa04
parent 485 bd6d999ab7b6
child 488 598741d39d21
--- a/progs/nfa.scala	Tue Apr 25 12:33:16 2017 +0100
+++ b/progs/nfa.scala	Fri Apr 28 11:01:25 2017 +0100
@@ -2,6 +2,16 @@
 // sets of states)
 import scala.util.Try
 
+// states class
+abstract class State
+case object Q0 extends State
+case object Q1 extends State
+case object Q2 extends State
+case object Q3 extends State
+case object Q4 extends State
+
+
+
 // type abbreviation for partial functions
 type :=>[A, B] = PartialFunction[A, B]
 
@@ -11,9 +21,9 @@
 
 
 // NFAs
-case class NFA[A, C](starts: Set[A],            // starting states
-                     delta: (A, C) :=> Set[A],  // transition function
-                     fins:  A => Boolean) {     // final states 
+case class NFA[A, C](starts: Set[A],           // starting states
+                     delta: (A, C) :=> Set[A], // transition function
+                     fins:  A => Boolean) {    // final states 
 
   // given a state and a character, what is the set of 
   // next states? if there is none => empty set
@@ -33,4 +43,39 @@
   // is a string accepted by an NFA?
   def accepts(s: List[C]) : Boolean = 
     deltas(starts, s).exists(fins)
+
+  // depth-first version of accepts
+  def search(q: A, s: List[C]) : Boolean = s match {
+    case Nil => fins(q)
+    case c::cs => next(q, c).exists(search(_, cs))
+  }
+
+  def accepts2(s: List[C]) : Boolean =
+    starts.exists(search(_, s))
 }
+
+
+
+// NFA examples
+
+val nfa_trans1 : (State, Char) :=> Set[State] = 
+  { case (Q0, 'a') => Set(Q0, Q1) 
+    case (Q0, 'b') => Set(Q2) 
+    case (Q1, 'a') => Set(Q1) 
+    case (Q2, 'b') => Set(Q2) }
+
+val nfa1 = NFA(Set[State](Q0), nfa_trans1, Set[State](Q2))
+
+nfa1.accepts("aa".toList)             // false
+nfa1.accepts("aaaaa".toList)          // false
+nfa1.accepts("aaaaab".toList)         // true
+nfa1.accepts("aaaaabbb".toList)       // true
+nfa1.accepts("aaaaabbbaaa".toList)    // false
+nfa1.accepts("ac".toList)             // false
+
+nfa1.accepts2("aa".toList)             // false
+nfa1.accepts2("aaaaa".toList)          // false
+nfa1.accepts2("aaaaab".toList)         // true
+nfa1.accepts2("aaaaabbb".toList)       // true
+nfa1.accepts2("aaaaabbbaaa".toList)    // false
+nfa1.accepts2("ac".toList)             // false