Coverage for interpreter.py: 98%

83 statements  

« prev     ^ index     » next       coverage.py v7.5.1, created at 2024-05-24 03:21 +0000

1from collections import deque 

2from time import sleep 

3from sys import stdin 

4import argparse 

5 

6 

7def encode(s): 

8 result = [] 

9 for x in s: 

10 result += [1, 1 if x else 0] 

11 return result + [0, 0] 

12 

13 

14def decode(s, start = 0): 

15 result = [] 

16 i = start 

17 while True: 

18 pair = (1 if s[i] else 0, 1 if s[i + 1] else 0) 

19 assert pair != (0, 1) 

20 if pair == (0, 0): 

21 return result 

22 result.append(pair[1]) 

23 i += 2 

24 

25 

26def move_left(): 

27 global current_pos 

28 if current_pos == 0: 

29 cells.appendleft(0) 

30 else: 

31 current_pos -= 1 

32 

33 

34def move_right(): 

35 global current_pos 

36 if current_pos == len(cells) - 1: 

37 cells.append(0) 

38 current_pos += 1 

39 

40 

41def mark(): 

42 cells[current_pos] = 1 

43 

44 

45def unmark(): 

46 cells[current_pos] = 0 

47 

48 

49def dump(): 

50 print(*cells, sep='') 

51 print(" " * current_pos + "^") 

52 

53 

54if __name__ == "__main__": 

55 parser = argparse.ArgumentParser(description="PTM interpreter") 

56 parser.add_argument('program', type=argparse.FileType('r'), nargs='*', 

57 help='file with a PTM program to interpret', default=stdin) 

58 parser.add_argument('--input', type=str, help='input binary string', default='') 

59 args = parser.parse_args() 

60 

61 cells = deque(encode([1 if c == "1" else 0 for c in args.input])) 

62 current_pos = 0 

63 cnt_ops = 0 

64 

65 for current_program in args.program: 

66 with current_program as program_file: 

67 original_lines = program_file.readlines() 

68 lines = [line.split("#", 1)[0].split() for line in original_lines] 

69 

70 current_line = 0 

71 current_cmd = 0 

72 

73 while current_line < len(lines): 

74 prev_line = current_line 

75 # print(original_lines[current_line], end='') 

76 move_occured = False 

77 while current_cmd < len(lines[current_line]): 

78 cmd = lines[current_line][current_cmd] 

79 cnt_ops += 1 

80 if cmd == "?": 

81 assert current_cmd + 2 < len(lines[current_line]) 

82 arg1 = lines[current_line][current_cmd + 1] 

83 arg2 = lines[current_line][current_cmd + 2] 

84 move_occured = True 

85 current_line = (int(arg1) if cells[current_pos] else int(arg2)) - 1 

86 current_cmd = 0 

87 break 

88 if cmd == "1": 

89 mark() 

90 elif cmd == "0": 

91 unmark() 

92 elif cmd == "<": 

93 move_left() 

94 elif cmd == ">": 

95 move_right() 

96 elif cmd == "!": 

97 current_line = len(lines) 

98 move_occured = True 

99 break 

100 current_cmd += 1 

101 

102 if lines[prev_line]: 

103 # dump() 

104 pass 

105 

106 if move_occured: 

107 continue 

108 

109 current_line += 1 

110 current_cmd = 0 

111 # print(*decode(cells, current_pos), sep='') 

112 

113 

114 print(*decode(cells, current_pos), sep='') 

115 print(f"Finished in {cnt_ops} operations")