-
Notifications
You must be signed in to change notification settings - Fork 7
/
grid.rb
131 lines (110 loc) · 3.19 KB
/
grid.rb
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
require_relative 'coords'
class Grid
attr_reader :size
OPERATORS = {
'!' => [:output_int],
'"' => [:mp_rev_left],
'#' => [:choose_ip],
'$' => [:jump],
'%' => [:mod],
'&' => [:mem_cpy],
'\'' => [:mp_rev_right],
'(' => [:dec],
')' => [:inc],
'*' => [:mul],
'+' => [:add],
',' => [:input_char],
'-' => [:sub],
'.' => [:nop],
'/' => [:mirror_diag_up],
'0' => [:digit, 0], '1' => [:digit, 1], '2' => [:digit, 2], '3' => [:digit, 3], '4' => [:digit, 4], '5' => [:digit, 5], '6' => [:digit, 6], '7' => [:digit, 7], '8' => [:digit, 8], '9' => [:digit, 9],
':' => [:div],
';' => [:output_char],
'<' => [:branch_left],
'=' => [:mp_reverse],
'>' => [:branch_right],
'?' => [:input_int],
'@' => [:terminate],
#'A' ,
# ... These will not be assigned and will set their ASCII value to the current memory cell.
#'Z' ,
'[' => [:prev_ip],
'\\' => [:mirror_diag_down],
']' => [:next_ip],
'^' => [:mp_branch],
'_' => [:mirror_hori],
#'`' , This will not be assigned as it's used for debug annotations.
#'a' ,
# ... These will not be assigned and will set their ASCII value to the current memory cell.
#'z' ,
'{' => [:mp_left],
'|' => [:mirror_vert],
'}' => [:mp_right],
'~' => [:neg],
}
OPERATORS.default_proc = proc do |hash, key|
[:mem_set, key.ord]
end
def initialize size
@size = size
@grid = Array.new(2*@size-1) {|j|
[[[:nop]]]*(2*@size-1 - (@size-1 - j).abs)
}
end
def self.from_string(string)
src_dbg = string.gsub(/\s/,'')
src = src_dbg.gsub(/`/,'')
# Find size of the grid as the smallest regular hexagon which
# is not smaller than the source code.
size = 1
size += 1 while 3*size*(size-1) + 1 < src.size
src_dbg += '.'*(3*size*(size-1) + 1 - src.size)
grid = Grid.new(size)
debug = false
ops = []
src_dbg.each_char {|c|
if c == '`'
debug = true
else
ops << [OPERATORS[c], debug]
debug = false
end
}
grid.fill! ops
grid
end
def fill! data
i = -1
@grid.map! { |line|
line.map! {
data[i+=1]
}
}
end
def get coords
i, j = axial_to_index coords
if i && j
@grid[i][j]
else
nil
end
end
def set coords, value
i, j = axial_to_index coords
@grid[i][j] = value if i && j
end
def axial_to_index coords
x = coords.q
z = coords.r
y = -x-z
return nil if [x.abs, y.abs, z.abs].max >= @size
i = z + @size-1
j = x + [i, @size-1].min
return [i, j]
end
def to_s
@grid.map{|line|
' '*(2*@size-1 - line.size) + line.map{|c,d| (d ? '`' : ' ') + (OPERATORS.invert[c]||c[1].chr(Encoding::UTF_8))}*''
}*$/
end
end