-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnumpskulls.py
146 lines (112 loc) · 3.94 KB
/
numpskulls.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
'Simple Brainfuck interpreter.'
from __future__ import print_function
import numpy as np
import argparse
import sys
import os
INSTRUCTION_SET = '+-<>,.[]'
TAPE_SIZE = 30000
# Memoize [] pairs
USE_MEMO = True
start_to_end = {}
end_to_start = {}
def build_parser():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
help='Name of program to run.',
type=str,
dest='filename'
)
return parser
def load_program(bf_filename):
with open(bf_filename) as fd:
program = fd.read()
program = [
instruction
for instruction in program
if instruction in INSTRUCTION_SET
]
return program
def inc(program, program_counter, data, data_pointer):
data[data_pointer] += 1
program_counter += 1
return program, program_counter, data, data_pointer
def dec(program, program_counter, data, data_pointer):
data[data_pointer] -= 1
program_counter += 1
return program, program_counter, data, data_pointer
def data_pointer_inc(program, program_counter, data, data_pointer):
data_pointer = (data_pointer + 1 % TAPE_SIZE)
program_counter += 1
return program, program_counter, data, data_pointer
def data_pointer_dec(program, program_counter, data, data_pointer):
data_pointer = (data_pointer - 1 % TAPE_SIZE)
program_counter += 1
return program, program_counter, data, data_pointer
def read_in(program, program_counter, data, data_pointer):
data[data_pointer] = ord(sys.stdin.read(1))
program_counter += 1
return program, program_counter, data, data_pointer
def print_out(program, program_counter, data, data_pointer):
print(chr(data[data_pointer]), end='', flush=True)
program_counter += 1
return program, program_counter, data, data_pointer
def loop_start(program, program_counter, data, data_pointer):
if data[data_pointer] == 0:
if USE_MEMO and program_counter in start_to_end.keys():
program_counter = start_to_end[program_counter]
else:
curr_pos = program_counter
open_brackets = 1
while open_brackets > 0:
curr_pos += 1
if program[curr_pos] == '[':
open_brackets += 1
elif program[curr_pos] == ']':
open_brackets -= 1
start_to_end[program_counter] = curr_pos
program_counter = curr_pos
program_counter += 1
return program, program_counter, data, data_pointer
def loop_end(program, program_counter, data, data_pointer):
if data[data_pointer] != 0:
if USE_MEMO and program_counter in end_to_start.keys():
program_counter = end_to_start[program_counter]
else:
curr_pos = program_counter - 1
open_brackets = 1
while open_brackets > 0:
curr_pos -= 1
if program[curr_pos] == '[':
open_brackets -= 1
elif program[curr_pos] == ']':
open_brackets += 1
end_to_start[program_counter] = curr_pos
program_counter = curr_pos
else:
program_counter += 1
return program, program_counter, data, data_pointer
def main(bf_filename):
assert os.path.isfile(bf_filename)
program = load_program(bf_filename)
program_counter = 0
data_pointer = 0
data = np.zeros(TAPE_SIZE, dtype=np.uint8)
instruction_lookup = {
'+': inc,
'-': dec,
'>': data_pointer_inc,
'<': data_pointer_dec,
',': read_in,
'.': print_out,
'[': loop_start,
']': loop_end
}
while program_counter < len(program):
instruction_function = instruction_lookup[program[program_counter]]
program, program_counter, data, data_pointer = instruction_function(
program, program_counter, data, data_pointer
)
if __name__ == '__main__':
args = build_parser().parse_args()
main(args.filename)