
class NFA(start: String, transitions: List[(String, Char, String)], finals: Set[String]) {...}
You may make this a case class if you like. It should have the
methodsdef solveByBacktracking(input: String): Option[List[String]]
and either one or the other of the two methodsFor each method, thedef solveBySetOfStates(input: String): Option[List[String]]ordef solveBySetOfPaths(input: String): Option[List[String]]
input is a string containing a sequence
of characters to be input to the NFA. For the user's convenience, input
may contain spaces, which the method should ignore. The method
attempts to find some one path from the start node to a finish node and, if
successful, returns the sequence of states that were visited along this
path, including both the start and finish node. (Special case: if the start
node is itself a finish node, the returned list should contain only that one
node.) Note that all of input must be used; it isn't enough to just pass through a final state, a solution requires that the NFA end up in a final state.ε (small Greek letter
epsilon). NFA containing a main
method. The object should read and process NFAs from a file named nfa.txt,
process them, and print the results. Since Scala is not homoiconic, I have
to specify the format of the input. It should consist of these parts, in
order:START (all caps) and, on
the same line, the name of the start state.FINAL and, on the same
line, the names of all the final states.TRANSITIONS
followed by any number of state character state
triples, using whitespace as the only delimiter.INPUT followed
by one or more characters. The characters may, but need not be,
separated by whitespace (any whitespace should be discarded). Multiple INPUT
lines represent multiple independent runs of the NFA.END, and nothing else.As a reminder, here is how backtracking works:
def explore(N) {
If N is a goal node, return “success”
If N is a leaf node, return “failure”
For each child C of N,
If explore(C) return
“success”
Return “failure”
}
In this assignment, of course, we want more than just a binary
success/failure; we want the sequence of nodes visited when successful.
Therefore, this approach must be augmented with additional code.011, we would start in {A}, that is, a set
containing only node A. Upon reading a 0, we could stay in A
or go to B, that is, {A, B}. If the next input is 1,
then from A we can stay in A or go to C; from B we cannot go anywhere, so
this path "dies", and the places we can be are {A, C}. Then if
the next input is another 1, from A we can stay in A or go to
C, and from C we can go to D; so the places we can be are {A, C, D}.
Since we have used all the input and ended in D, which is a final state, we can stop.011, we would start in {[A]}, that is, a set
containing a list containing A. Here, [A] represents a zero-length path. Upon reading a 0, we could stay in A
or go to B, that is, {[A,A], [A,B]}. If the next input is 1,
then from path [A,A] we can stay in A or go to C--so the path [A,A] splits into [A,A,A] and [A,A,C], while from [A,B] we cannot go anywhere, so this path "dies", and the possible paths so far are {[A,A,A],[A,A,C]}. Then if
the next input is another 1, from [A,A,A] we can stay in A or go to
C, and from [A,A,C] we can go to D; so the paths we can follow are {[A,A,A,A], [A,A,A,C], [A,A,C,D]}. Since we have used all the input and ended in D, which is a final state, we can stop.