Advertisement
Lesnic

Untitled

Apr 24th, 2020
601
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.57 KB | None | 0 0
  1. import java.io.*;
  2. import java.util.*;
  3.  
  4. public class Main {
  5.  
  6.     public static void main(String[] args) throws FileNotFoundException {
  7.         Scanner scanner = new Scanner(new File("fsa.txt"));
  8.         PrintWriter result = new PrintWriter("result.txt");
  9.  
  10.         Validator fsaValid = new Validator(scanner, result);
  11.         fsaValid.start();
  12.  
  13.         RegexBuilder regexBuilder = new RegexBuilder(fsaValid.getStates(), fsaValid.getInitState(),
  14.                 fsaValid.getFinStates());
  15.         String regex = regexBuilder.build();
  16.  
  17.         result.print(regex);
  18.  
  19.         scanner.close();
  20.         result.close();
  21.     }
  22. }
  23.  
  24. class State {
  25.     State(String name) {
  26.         this.name = name;
  27.         this.transition = new LinkedList<>();
  28.     }
  29.  
  30.     private String name;
  31.     private LinkedList<Transition> transition;
  32.  
  33.     public String getName() {
  34.         return name;
  35.     }
  36.  
  37.     public void addTrans(String letter, State state) {
  38.         transition.add(new Transition(letter, state));
  39.     }
  40.  
  41.     public LinkedList<Transition> getTrans() {
  42.         return transition;
  43.     }
  44. }
  45.  
  46. class Validator {
  47.     private PrintWriter result;
  48.     private LinkedList<State> states; // states of FSA
  49.     private LinkedList<String> alpha; // alphabet of FSA
  50.     private State initState; // initial state of FSA
  51.     private LinkedList<State> finState; // final state of FSA
  52.     private LinkedList<Transition> transitions; // transitions of FSA
  53.  
  54.     Validator(Scanner scanner, PrintWriter result) {
  55.         this.result = result;
  56.  
  57.         HashMap fileData = formatInFile(scanner);
  58.  
  59.         this.states = (LinkedList<State>) fileData.get("states");
  60.         this.alpha = (LinkedList<String>) fileData.get("alpha");
  61.         this.initState = (State) fileData.get("initState");
  62.         this.finState = (LinkedList<State>) fileData.get("finState");
  63.         this.transitions = (LinkedList<Transition>) fileData.get("trans");
  64.     }
  65.  
  66.     private HashMap formatInFile(Scanner scanner) {
  67.         HashMap fileData = new HashMap<>();
  68.  
  69.         String statesString = scanner.nextLine(); // input strings
  70.         String alphaString = scanner.nextLine();
  71.         String initStateString = scanner.nextLine();
  72.         String finStateString = scanner.nextLine();
  73.         String transString = scanner.nextLine();
  74.  
  75.         if (fileIsMalformed(statesString, alphaString, initStateString, finStateString, transString)) {
  76.             result.print("Error:\nE5: Input file is malformed"); // E5 check
  77.             result.close();
  78.             System.exit(0);
  79.         }
  80.  
  81.         LinkedList<State> states = formatStates(statesString); // reformat lines
  82.         LinkedList<String> alpha = formatAlpha(alphaString);
  83.         State initState = formatInitState(initStateString, states);
  84.         LinkedList<State> finStates = formatFinStates(finStateString, states);
  85.         LinkedList<Transition> trans = formatTrans(transString, states, alpha);
  86.  
  87.         fileData.put("states", states);
  88.         fileData.put("alpha", alpha);
  89.         fileData.put("initState", initState);
  90.         fileData.put("finState", finStates);
  91.         fileData.put("trans", trans);
  92.  
  93.         return fileData;
  94.     }
  95.  
  96.     private boolean fileIsMalformed(String statesString, String alphaString, String initStateString,
  97.             String finStateString, String transString) {
  98.         if ((!(statesString.contains("[") && statesString.contains("]")) || !statesString.contains("=")
  99.                 || statesString.contains(" "))
  100.                 || (!(alphaString.contains("[") && alphaString.contains("]")) || !alphaString.contains("=")
  101.                         || alphaString.contains(" "))
  102.                 || (!(initStateString.contains("[") && initStateString.contains("]")) || !initStateString.contains("=")
  103.                         || initStateString.contains(" "))
  104.                 || (!(finStateString.contains("[") && finStateString.contains("]")) || !finStateString.contains("=")
  105.                         || finStateString.contains(" "))
  106.                 || (!(transString.contains("[") && transString.contains("]")) || !transString.contains("=")
  107.                         || transString.contains(" ")))
  108.             return true;
  109.  
  110.         if (!(statesString.substring(0, 8).equals("states=[") & statesString.charAt(statesString.length() - 1) == ']'
  111.                 & alphaString.substring(0, 7).equals("alpha=[") & alphaString.charAt(alphaString.length() - 1) == ']'
  112.                 & initStateString.substring(0, 9).equals("init.st=[")
  113.                 & initStateString.charAt(initStateString.length() - 1) == ']'
  114.                 & finStateString.substring(0, 8).equals("fin.st=[")
  115.                 & finStateString.charAt(finStateString.length() - 1) == ']'
  116.                 & transString.substring(0, 7).equals("trans=[") & transString.charAt(transString.length() - 1) == ']'))
  117.             return true;
  118.  
  119.         return false;
  120.     }
  121.  
  122.     private LinkedList<State> formatStates(String statesStr) {
  123.         LinkedList<State> resStates = new LinkedList<>();
  124.         String[] states = statesStr.substring(8, statesStr.length() - 1).split(",");
  125.  
  126.         for (String stateName : states)
  127.             resStates.add(new State(stateName));
  128.  
  129.         return resStates;
  130.     }
  131.  
  132.     // convert string according alphabet
  133.     private LinkedList<String> formatAlpha(String alphaStr) {
  134.         LinkedList<String> resAlpha = new LinkedList<>();
  135.         String[] alpha = alphaStr.substring(7, alphaStr.length() - 1).split(",");
  136.  
  137.         resAlpha.addAll(Arrays.asList(alpha));
  138.  
  139.         return resAlpha;
  140.     }
  141.  
  142.     // convert string according initial states
  143.     private State formatInitState(String initStateStr, LinkedList<State> states) {
  144.         String initStateName = initStateStr.substring(9, initStateStr.length() - 1);
  145.  
  146.         return findByName(initStateName, states);
  147.     }
  148.  
  149.     // convert string according final states
  150.     private LinkedList<State> formatFinStates(String finStateStr, LinkedList<State> states) {
  151.         LinkedList<State> resFinStates = new LinkedList<>();
  152.         String[] finStates = finStateStr.substring(8, finStateStr.length() - 1).split(",");
  153.  
  154.         for (String finState : finStates)
  155.             if (!finState.equals(""))
  156.                 resFinStates.add(findByName(finState, states));
  157.  
  158.         return resFinStates;
  159.     }
  160.  
  161.     // convert string according alphabet transitions
  162.     private LinkedList<Transition> formatTrans(String transStr, LinkedList<State> states, LinkedList<String> alpha) {
  163.         LinkedList<Transition> resTrans = new LinkedList<>();
  164.         String[] trans = transStr.substring(7, transStr.length() - 1).split(",");
  165.  
  166.         for (String transitionStr : trans) {
  167.             String[] transSep = transitionStr.split(">");
  168.             State state1 = findByName(transSep[0], states);
  169.             State state2 = findByName(transSep[2], states);
  170.  
  171.             if (!alpha.contains(transSep[1])) { // E3 check
  172.                 result.print("Error:\nE3: A transition '" + transSep[1] + "' is not represented in the alphabet");
  173.                 result.close();
  174.                 System.exit(0);
  175.             }
  176.  
  177.             if (state1 != null & state2 != null)
  178.                 state1.addTrans(transSep[1], state2);
  179.  
  180.             resTrans.add(new Transition(transSep[1], state1, state2));
  181.         }
  182.  
  183.         return resTrans;
  184.     }
  185.  
  186.     // find state according the name
  187.     private State findByName(String name, LinkedList<State> states) {
  188.         for (State state : states)
  189.             if (state.getName().equals(name))
  190.                 return state;
  191.  
  192.         if (!name.equals("")) { // E1 check
  193.             result.print("Error:\nE1: A state '" + name + "' is not in set of states");
  194.             result.close();
  195.             System.exit(0);
  196.         }
  197.         return null;
  198.     }
  199.  
  200.     public void start() {
  201.         if (initState == null) { // E4 check
  202.             result.print("Error:\nE4: Initial state is not defined");
  203.             result.close();
  204.             System.exit(0);
  205.         }
  206.  
  207.         LinkedList<State> undirectedStates = makeUndirected(deepClone(states));
  208.         LinkedList<State> reachedStates = getReachableStatesFrom(undirectedStates.get(0), new LinkedList<>());
  209.  
  210.         if (reachedStates.size() != states.size()) { // check E2
  211.             result.print("Error:\nE2: Some states are disjoint");
  212.             result.close();
  213.             System.exit(0);
  214.         }
  215.  
  216.         if (fsaIsNondeterministic()) { // check E6
  217.             result.print("Error:\nE6: FSA is nondeterministic");
  218.             result.close();
  219.             System.exit(0);
  220.         }
  221.  
  222.         if (finState.size() == 0) {
  223.             result.print("{}");
  224.             result.close();
  225.             System.exit(0);
  226.         }
  227.     }
  228.  
  229.     private LinkedList<State> deepClone(LinkedList<State> states) {
  230.         LinkedList<State> newStates = new LinkedList<>();
  231.  
  232.         for (State state : states)
  233.             newStates.add(new State(state.getName()));
  234.  
  235.         for (int i = 0; i < states.size(); i++)
  236.             for (Transition trans : states.get(i).getTrans()) {
  237.                 State state = findByName(trans.getTarget().getName(), newStates);
  238.                 newStates.get(i).addTrans(trans.getLetter(), state);
  239.             }
  240.  
  241.         return newStates;
  242.     }
  243.  
  244.     private LinkedList<State> makeUndirected(LinkedList<State> states) {
  245.         for (State state : states)
  246.             for (Transition trans : state.getTrans())
  247.                 if (state != trans.getTarget()
  248.                         & !trans.getTarget().getTrans().contains(new Transition(trans.getLetter(), state)))
  249.                     trans.getTarget().addTrans(trans.getLetter(), state);
  250.         return states;
  251.     }
  252.  
  253.     private LinkedList<State> getReachableStatesFrom(State state, LinkedList<State> result) {
  254.         result.add(state);
  255.         for (Transition trans : state.getTrans())
  256.             if (!result.contains(trans.getTarget()))
  257.                 result = getReachableStatesFrom(trans.getTarget(), result);
  258.         return result;
  259.     }
  260.  
  261.     private boolean fsaIsNondeterministic() {
  262.         LinkedList<String> localTrans = new LinkedList<>();
  263.  
  264.         for (Transition trn : transitions) {
  265.             if (localTrans.contains(trn.getLetter() + ">" + trn.getSource().getName()))
  266.                 return true;
  267.             localTrans.add(trn.getLetter() + ">" + trn.getSource().getName());
  268.         }
  269.  
  270.         return false;
  271.     }
  272.  
  273.     public LinkedList<State> getStates() {
  274.         return states;
  275.     }
  276.  
  277.     public State getInitState() {
  278.         return initState;
  279.     }
  280.  
  281.     public LinkedList<State> getFinStates() {
  282.         return finState;
  283.     }
  284. }
  285.  
  286. class RegexBuilder {
  287.     private LinkedList<State> states; // states of FSA
  288.     private State initState; // initial state of FSA
  289.     private LinkedList<State> finStates; // final state of FSA
  290.     private int initIndex; // index of initial state in states list
  291.     private LinkedList<Integer> finIndexes; // indexes of final states in states list
  292.  
  293.     RegexBuilder(LinkedList<State> states, State initState, LinkedList<State> finStates) {
  294.         this.states = states;
  295.         this.initState = initState;
  296.         this.finStates = finStates;
  297.  
  298.         this.initIndex = 0;
  299.         this.finIndexes = new LinkedList<>();
  300.     }
  301.  
  302.     public String build() {
  303.         String[][] R = getInitRegex();
  304.  
  305.         for (int i = 0; i < states.size(); i++) {
  306.             String[][] newR = new String[states.size()][states.size()];
  307.  
  308.             for (int j = 0; j < states.size(); j++)
  309.                 for (int k = 0; k < states.size(); k++)
  310.                     newR[j][k] = "(" + R[j][i] + ")(" + R[i][i] + ")*(" + R[i][k] + ")|(" + R[j][k] + ")";
  311.  
  312.             R = newR;
  313.         }
  314.  
  315.         String result = "";
  316.         for (int j : finIndexes)
  317.             result = result.concat(R[initIndex][j]) + "|";
  318.  
  319.         return result.substring(0, result.length() - 1);
  320.     }
  321.  
  322.     private String[][] getInitRegex() {
  323.         String[][] initRegex = new String[states.size()][states.size()];
  324.  
  325.         for (int j = 0; j < states.size(); j++)
  326.             if (finStates.contains(states.get(j)))
  327.                 finIndexes.add(j);
  328.  
  329.         for (int i = 0; i < states.size(); i++) {
  330.             State state1 = states.get(i);
  331.  
  332.             if (state1 == initState)
  333.                 initIndex = i;
  334.  
  335.             for (int j = 0; j < states.size(); j++) {
  336.                 State state2 = states.get(j);
  337.                 String reg = "";
  338.  
  339.                 for (Transition trans : state1.getTrans())
  340.                     if (trans.getTarget() == state2)
  341.                         reg = reg.concat(trans.getLetter() + "|");
  342.  
  343.                 if (state1 == state2)
  344.                     reg = reg.concat("eps");
  345.                 if (reg.isEmpty())
  346.                     reg = "{}";
  347.                 if (reg.charAt(reg.length() - 1) == '|')
  348.                     reg = reg.substring(0, reg.length() - 1);
  349.  
  350.                 initRegex[i][j] = reg;
  351.             }
  352.         }
  353.  
  354.         return initRegex;
  355.     }
  356. }
  357.  
  358. class Transition {
  359.     Transition(String letter, State source, State target) {
  360.         this.letter = letter;
  361.         this.source = source;
  362.         this.target = target;
  363.     }
  364.  
  365.     Transition(String letter, State target) {
  366.         this.letter = letter;
  367.         this.source = null;
  368.         this.target = target;
  369.     }
  370.  
  371.     private String letter;
  372.     private State source;
  373.     private State target;
  374.  
  375.     public String getLetter() {
  376.         return letter;
  377.     }
  378.  
  379.     public State getSource() {
  380.         return source;
  381.     }
  382.  
  383.     public State getTarget() {
  384.         return target;
  385.     }
  386. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement