import java.util.Arrays;
import java.util.Vector;
/**
* @author joakimlilja
* Hyper String Finite State Automata
* Object holding all possible combinations of first letter capitalization and punctuation symbols .,?
*
*/
public class HyperStringFSA {
public static final String[] TRANSITIONS = { " " + (char) 7 + " ", " , ", " . ",
" ? " };
public static final int TRANSITION_COUNT = 4;
public static final int STATES_COUNT = 2;
Vector<String[]> outputs;
/**
* Constructor creating a FSA based on the specified String array consisting of words
* @param s Array of words
*/
public HyperStringFSA(String[] s) {
outputs = new Vector<String[]>();
constructFSA(s, outputs);
}
/**
* Construct the FSA with all possible outputs
* @param s Array of words
* @param outputs Vector holding all possible outputs
*/
private void constructFSA(String[] s, Vector<String[]> outputs) {
Node root = new Node("");
root = generateNodes(s, root);
generateOutputs(root, outputs);
}
/**
* Generate the outputs using a tree structure
* @param node
* @param outputs
*/
private void generateOutputs(Node node, Vector<String[]> outputs) {
if (node.children.size() == 0) {
String s = backTrack(node, "");
//System.out.println(s);
String[] a = s.split(" ");
for (int i = 0; i < a.length; i++) {
a[i] = a[i].replace("E", " ");
}
outputs.add(a);
} else {
for (int i = 0; i < node.children.size(); i++) {
generateOutputs(node.children.elementAt(i), outputs);
}
}
}
/**
* Backtrack from end node to generate the output of that path
* @param node
* @param s
* @return output
*/
private String backTrack(Node node, String s) {
if (node.parent == null) {
return node.value + s.substring(0, s.length()-1);
} else {
return backTrack(node.parent, node.value + s);
}
}
/**
* Generate children
* @param s
* @param parent
* @return
*/
private Node generateNodes(String[] s, Node parent) {
Node unCapNode = new Node(s[0]);
unCapNode.parent = parent;
generateTransitions(unCapNode);
Node capNode = new Node(capitalizeWord(s[0]));
capNode.parent = parent;
generateTransitions(capNode);
parent.children.add(capNode);
parent.children.add(unCapNode);
if (s.length != 1) {
for (int i = 0; i < unCapNode.children.size(); i++) {
unCapNode.children.set(i, generateNodes(Arrays.copyOfRange(s, 1, s.length), unCapNode.children.get(i)));
capNode.children.set(i, generateNodes(Arrays.copyOfRange(s, 1, s.length), capNode.children.get(i)));
}
}
return parent;
}
/**
* Generate the possible punctuation transitions
* @param node
*/
private void generateTransitions(Node node) {
for (int i = 0; i < TRANSITION_COUNT; i++) {
Node transNode = new Node(TRANSITIONS[i]);
transNode.parent = node;
node.children.add(transNode);
}
}
public String toString() {
return outputs.toString();
}
private String capitalizeWord(String input) {
return input.substring(0, 1).toUpperCase() + input.substring(1);
}
public static void main(String... args) {
String[] words = {"mars", "scientists"};
HyperStringFSA fsa = new HyperStringFSA(words);
for(String[] s:fsa.outputs) {
System.out.println(Arrays.toString(s));
}
}
private class Node {
String value;
Node parent;
Vector<Node> children;
public Node(String value) {
children = new Vector<Node>();
this.value = value;
}
public String toString() {
return value;
}
}
}