import sys import os filename = sys.argv[1] # filename = 'simple1.arg' path = os.path.join(os.getcwd(), filename) file = open(path, 'r').readlines() class FSA(): def __init__(self): self.initial_state = '0' self.current_letter = None self.current_state = self.initial_state self.alphabet = set() self.transition_function = [] self.end_state = [] self.all_states = set() self.is_nfa = 0 def add_letter_to_alphabet(self, letter): self.alphabet.add(letter) def add_transition_to_transition_function(self, input_state, output_state, letter): self.all_states.add(input_state) self.all_states.add(output_state) if len(self.transition_function) > 0: for x, function in enumerate(self.transition_function): if function['in'] == input_state and function['letter'] == letter: self.transition_function[x]['out'].append(output_state) return obj = {'in': input_state, 'letter': letter, 'out': [output_state]} self.transition_function.append(obj) else: obj = {'in': input_state, 'letter': letter, 'out': [output_state]} self.transition_function.append(obj) # add letter to alphabet def specify_end_state(self, end_state): self.end_state.append(end_state) def nfa_to_dfa(self): nfa = dict() for x in FSA.all_states: nfa[x] = {} for a in FSA.alphabet: a_dict = {a: None} nfa[x].update(a_dict) for function in self.transition_function: nfa[function['in']][function['letter']] = function['out'] trap_state_in = str(int(sorted(FSA.all_states, reverse=True)[0]) + 1) trap_state = {trap_state_in: {}} for a in FSA.alphabet: a_dict = {a: trap_state_in} trap_state[trap_state_in].update(a_dict) dfa = {} dfa_keys = [] new_states_list = [] dfa.update(trap_state) # first row state = FSA.initial_state nfa_function = nfa[state] dfa_keys.append(state) dfa_function = dict() for letter in FSA.alphabet: if not nfa_function[letter]: dfa_function[letter] = trap_state_in continue if nfa_function[letter] and len(nfa_function[letter]) > 1: new_state_in = ''.join(nfa_function[letter]) for i in self.end_state: if i in nfa_function[letter]: self.specify_end_state(new_state_in) break dfa_function[letter] = new_state_in new_states_list.append(new_state_in) continue if len(nfa_function[letter]) == 1: new_state = nfa_function[letter][0] dfa_function[letter] = new_state if new_state not in new_states_list: new_states_list.append(new_state) continue dfa[state] = dfa_function while len(new_states_list) != 0: new_dfa_state = new_states_list.pop(0) dfa_function = dict() if len(new_dfa_state) == 1: nfa_function = nfa[new_dfa_state] for letter in FSA.alphabet: if not nfa_function[letter]: dfa_function[letter] = trap_state_in continue if nfa_function[letter] and len(nfa_function[letter]) > 1: new_state_in = ''.join(nfa_function[letter]) for i in self.end_state: if i in nfa_function[letter]: self.specify_end_state(new_state_in) break dfa_function[letter] = new_state_in if new_state_in not in dfa_keys and new_state_in not in new_states_list: new_states_list.append(new_state_in) continue if len(nfa_function[letter]) == 1: new_state_in = nfa_function[letter][0] dfa_function[letter] = new_state_in if new_state_in not in dfa_keys and new_state_in not in new_states_list: new_states_list.append(new_state_in) continue dfa[new_dfa_state] = dfa_function else: dfa_func = {} for letter in FSA.alphabet: dfa_func[letter] = None for let in FSA.alphabet: new_letter = '' for state in new_dfa_state: nfa_letter = nfa[state][let] if nfa_letter: x = ''.join(nfa_letter) new_letter += x if new_letter not in dfa_keys and new_letter not in new_states_list: dfa_keys.append(new_letter) new_states_list.append(new_letter) for i in self.end_state: if i in new_letter: self.specify_end_state(new_letter) break if new_letter == '': new_letter = trap_state_in dfa_func[let] = new_letter dfa[new_dfa_state] = dfa_func self.transition_function = dfa def check_text(self, text): if self.is_nfa == 0: for letter in text: if letter not in self.alphabet: return 'FALSE' found_function = None for func in self.transition_function: if func['in'] == self.current_state and func['letter'] == letter: found_function = func if not found_function: for func in self.transition_function: if func['in'] == self.current_state and func['letter'] == '': self.current_state = func['out'][0] for func in self.transition_function: if func['in'] == self.current_state and func['letter'] == letter: self.current_state = func['out'][0] break break else: return 'FALSE' else: self.current_state = found_function['out'][0] else: for letter in text: if letter not in self.alphabet: return 'FALSE' found_function = self.transition_function[self.current_state][letter] self.current_state = found_function if self.current_state in self.end_state: return 'TRUE' else: for func in self.transition_function: if func['in'] == self.current_state and func['letter'] == '': self.current_state = func['out'][0] break if self.current_state in self.end_state: return 'TRUE' else: return 'FALSE' FSA = FSA() for line in file: if '#' in line: continue line = line.rstrip('\n').split(' ') if len(line) > 1: FSA.add_transition_to_transition_function(line[0], line[1], line[2]) FSA.add_letter_to_alphabet(line[2]) else: FSA.specify_end_state(line[0]) for function in FSA.transition_function: if len(function['out']) > 1: FSA.is_nfa = 1 FSA.nfa_to_dfa() break lines = ['a', 'ab', 'abc', 'abcd', 'aaaaab', 'abc', 'xyz', '0' ] for line in sys.stdin: line = line.rstrip('\n') FSA.current_state = FSA.initial_state print("{} {}".format(FSA.check_text(line), line))