25_turingmachine.py 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. #!/usr/bin/env python3
  2. import sys
  3. class TuringMachine:
  4. def __init__(self, f):
  5. def last_word(linenr):
  6. return lines[linenr].split()[-1][:-1]
  7. def state_index(state):
  8. return (ord(state) - ord('A')) * 2
  9. def transition(start):
  10. write_val = int(last_word(start))
  11. move = 1 if last_word(start + 1) == 'left' else -1
  12. next_state = state_index(last_word(start + 2))
  13. return write_val, move, next_state
  14. lines = f.read().split('\n')
  15. self.state = state_index(last_word(0))
  16. self.steps = int(lines[1].split()[-2])
  17. self.trans = []
  18. self.tape = 0
  19. self.index = 0
  20. for start in range(3, len(lines), 10):
  21. in_state = state_index(last_word(start))
  22. assert in_state == len(self.trans)
  23. self.trans.append(transition(start + 2))
  24. self.trans.append(transition(start + 6))
  25. def step(self):
  26. read_val = (self.tape >> self.index) & 1
  27. write_val, move, next_state = self.trans[self.state + read_val]
  28. if write_val != read_val:
  29. mask = 1 << self.index
  30. if write_val:
  31. self.tape |= mask
  32. else:
  33. self.tape &= ~mask
  34. self.index += move
  35. if self.index == -1:
  36. self.tape <<= 1
  37. self.index = 0
  38. self.state = next_state
  39. self.steps -= 1
  40. def diag(self):
  41. while self.steps > 0:
  42. self.step()
  43. checksum = 0
  44. tape = self.tape
  45. while tape > 0:
  46. checksum += tape & 1
  47. tape >>= 1
  48. return checksum
  49. print(TuringMachine(sys.stdin).diag())