136 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from collections import defaultdict
 | |
| from sortedcontainers import SortedDict
 | |
| from copy import copy, deepcopy
 | |
| from enum import IntEnum
 | |
| 
 | |
| 
 | |
| class Movemement(IntEnum):
 | |
|     R = 1
 | |
|     L = -1
 | |
|     E = 0
 | |
| 
 | |
| 
 | |
| class Action:
 | |
|     def __init__(
 | |
|         self,
 | |
|         state,
 | |
|         symbol: chr,
 | |
|         movement: Movemement
 | |
|     ) -> None:
 | |
|         self.state = state
 | |
|         self.symbol = symbol
 | |
|         self.movement = movement
 | |
| 
 | |
| 
 | |
| class Program:
 | |
|     data = dict()
 | |
| 
 | |
|     state_count = 0
 | |
|     symbol_count = 0
 | |
|     symbol_dict = dict()
 | |
| 
 | |
|     blank_symbol = 'λ'
 | |
| 
 | |
|     def __init__(self, blank_symbol: chr = 'λ') -> None:
 | |
|         self.blank_symbol = blank_symbol
 | |
| 
 | |
|     def is_blank(self, symbol) -> bool:
 | |
|         return symbol == self.blank_symbol
 | |
| 
 | |
|     def set(self, state, symbol, action) -> None:
 | |
|         if state not in self.data:
 | |
|             self.data[state] = dict()
 | |
|             self.state_count += 1
 | |
| 
 | |
|         self.symbol_dict[symbol] = None
 | |
|         self.data[state][symbol] = action
 | |
| 
 | |
|     def get(self, state, symbol) -> Action or None:
 | |
|         if symbol not in self.data[state]:
 | |
|             return None
 | |
| 
 | |
|         return self.data[state][symbol]
 | |
| 
 | |
|     def get_symbols(self):
 | |
|         return list(self.symbol_dict.keys())
 | |
| 
 | |
| 
 | |
| class Emulator():
 | |
|     """
 | |
|     A class used to emulate an Turing machine
 | |
|     """
 | |
| 
 | |
|     class Tape:
 | |
| 
 | |
|         l_index = 0
 | |
|         r_index = 0
 | |
| 
 | |
|         def __init__(self, input_string: str, blank_symbol: str) -> None:
 | |
|             self.tape = SortedDict(dict(enumerate(input_string)))
 | |
|             self.blank_symbol = blank_symbol
 | |
| 
 | |
|             r_index = len(input_string)
 | |
|             pass
 | |
| 
 | |
|         def __deepcopy__(self, memo):
 | |
|             id_self = id(self)
 | |
|             _copy = memo.get(id_self)
 | |
|             if _copy is None:
 | |
|                 _copy = type(self)('', self.blank_symbol)
 | |
| 
 | |
|                 _copy.tape = deepcopy(self.tape)
 | |
|                 _copy.blank_symbol = self.blank_symbol
 | |
|                 _copy.l_index = self.l_index
 | |
|                 _copy.r_index = self.r_index
 | |
| 
 | |
|                 memo[id_self] = _copy
 | |
|             return _copy
 | |
| 
 | |
|         def __setitem__(self, key, value):
 | |
|             self.tape[key] = value
 | |
|             self.l_index = min(self.l_index, key)
 | |
|             self.r_index = max(self.r_index, key)
 | |
| 
 | |
|         def __getitem__(self, key):
 | |
|             if key not in self.tape:
 | |
|                 return self.blank_symbol
 | |
| 
 | |
|             return self.tape[key]
 | |
| 
 | |
|         def values(self):
 | |
|             return self.tape.values()
 | |
| 
 | |
|     def __init__(self, program: Program, input_string: str = ''):
 | |
|         self.head = 0
 | |
|         self.state = 0
 | |
|         self.stopped = False
 | |
| 
 | |
|         self.program = program
 | |
|         self.tape = Emulator.Tape(input_string, program.blank_symbol)
 | |
| 
 | |
|     def step(self):
 | |
|         if self.stopped is True:
 | |
|             raise RuntimeError('Turing machine is stopped!')
 | |
| 
 | |
|         try:
 | |
|             action = self.program.get(self.state, self.tape[self.head])
 | |
| 
 | |
|             self.tape[self.head] = action.symbol
 | |
|             self.state = action.state
 | |
|             self.head += int(action.movement)
 | |
|             self.tape[self.head] = self.tape[self.head]
 | |
| 
 | |
|             if self.state == -1:
 | |
|                 self.stopped = True
 | |
| 
 | |
|         except Exception as err:
 | |
|             self.stopped = True
 | |
|             print('Error', err)
 | |
| 
 | |
|     def info(self):
 | |
|         return [
 | |
|             self.head,
 | |
|             self.state,
 | |
|             deepcopy(self.tape),
 | |
|         ]
 |