Advertisement
Guest User

AoC 2024/19 NFA

a guest
Dec 19th, 2024
16
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.25 KB | Source Code | 0 0
  1. from collections import defaultdict
  2.  
  3. class State:
  4.  
  5.     def __init__(self, name, transitions=None):
  6.         self.name = name
  7.         self.transitions = transitions or defaultdict(list)
  8.  
  9.     def add_transition(self, symbol, state):
  10.         self.transitions[symbol].append(state)
  11.  
  12.     def __repr__(self):
  13.         return f"State {self.name}"
  14.  
  15.     def __str__(self):
  16.         return self.name
  17.  
  18. class NFA:
  19.     def __init__(self):
  20.         self.start_state = State("Start")
  21.  
  22.     def accepts(self, string):
  23.         current_states = [(1, state) for state in self.start_state.transitions[None]]
  24.         for symbol in string:
  25.             next_states = []
  26.             #how many start states do we pass this round?
  27.             start_state_count = sum([count for count, state in current_states if state == self.start_state])
  28.             while current_states:
  29.                 count, state = current_states.pop()
  30.                 # all new patterns start with the start state count, but only once
  31.                 if state == self.start_state and start_state_count > 0:
  32.                     current_states.extend([(start_state_count, state) for state in self.start_state.transitions[None]])
  33.                     start_state_count = 0
  34.                 else:
  35.                     transitions = state.transitions[symbol]
  36.                     next_states.extend([(count, state) for state in transitions])
  37.             current_states = next_states
  38.         result = sum([count for count, state in current_states if state == self.start_state])
  39.         return result
  40.  
  41.     def add_pattern(self, pattern):
  42.         next_state = self.start_state
  43.         state = self.start_state
  44.         for i in range(len(pattern)-1, -1, -1):
  45.             symbol = pattern[i]
  46.             state = State(pattern[:i]+"["+symbol+"]" +pattern[i+1:])
  47.             state.add_transition(symbol, next_state)
  48.             next_state = state
  49.         self.start_state.add_transition(None, state)
  50.  
  51. if __name__ == "__main__":
  52.     nfa = NFA()
  53.     nfa.add_pattern("a")
  54.     nfa.add_pattern("ab")
  55.     nfa.add_pattern("c")
  56.     nfa.add_pattern("bc")
  57.     nfa.add_pattern("d")
  58.  
  59.     assert nfa.accepts("ab") == 1
  60.     assert nfa.accepts("abc") == 2
  61.     assert nfa.accepts("abcd") == 2
  62.     assert nfa.accepts("bcd") == 1
Tags: NFA
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement