-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path11.koto
168 lines (144 loc) · 4.42 KB
/
11.koto
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# https://adventofcode.com/2020/day/11
from enum import make_enum
cell = make_enum "floor", "empty", "occupied"
directions =
(-1, -1), (0, -1), (1, -1),
(-1, 0), (1, 0),
(-1, 1), (0, 1), (1, 1),
make_floor_grid = |input|
grid, row_count, row_size = input
.lines()
.fold ([], 0, 0), |(grid, row_count, _), line|
row = line
.chars()
.each |c|
match c
"." then cell.floor
"L" then cell.empty
"#" then cell.occupied
.to_list()
(grid.extend(row), row_count + 1, row.size())
return
grid: grid
temp_grid: copy grid
row_size: row_size
row_count: row_count
fill_seats_part_one: ||
grid, temp_grid = self.grid, self.temp_grid
row_size, row_count = self.row_size, self.row_count
state_changed = false
batch_start = 0
for y in 0..row_count
y_index = y * row_size
for x in 0..row_size
index = y_index + x
state = grid[index]
if state == cell.floor then continue
occupied_count = 0
for direction in directions
dx = x + direction[0]
if not (0 <= dx < row_size)
continue
dy = y + direction[1]
if not (0 <= dy < row_count)
continue
if grid[dy * row_size + dx] == cell.occupied
occupied_count += 1
temp_grid[index] = match state
cell.empty if occupied_count == 0 then
state_changed = true
cell.occupied
cell.occupied if occupied_count >= 4 then
state_changed = true
cell.empty
else state
grid.swap temp_grid
state_changed
fill_seats_part_two: ||
grid, temp_grid = self.grid, self.temp_grid
row_size, row_count = self.row_size, self.row_count
state_changed = false
for y in 0..row_count
y_index = y * row_size
for x in 0..row_size
index = y_index + x
state = grid[index]
if state == cell.floor then continue
occupied_count = 0
for direction in directions
dx, dy = x, y
loop
dx += direction[0]
if not 0 <= dx < row_size
break
dy += direction[1]
if not 0 <= dy < row_count
break
match grid[dy * row_size + dx]
cell.empty then break
cell.occupied then
occupied_count += 1
break
temp_grid[index] = match state
cell.empty if occupied_count == 0 then
state_changed = true
cell.occupied
cell.occupied if occupied_count >= 5 then
state_changed = true
cell.empty
else state
grid.swap temp_grid
state_changed
fill_seats_until_stable_part_one: ||
result = 0
while self.fill_seats_part_one()
result += 1
fill_seats_until_stable_part_two: ||
result = 0
while self.fill_seats_part_two()
result += 1
occupied_seats_count: ||
self.grid
.keep |position| position == cell.occupied
.count()
to_string: ||
result = ""
for y in 0..self.row_count
for x in 0..self.row_size
result += match self.grid[y * self.row_size + x]
cell.floor then "."
cell.empty then "L"
cell.occupied then "#"
result += "\n"
@main = ||
grid = io.extend_path koto.script_dir, "input", "11"
>> io.read_to_string
>> make_floor_grid
part_one = deep_copy grid
print "Part one"
print "- seats stabilised in ${part_one.fill_seats_until_stable_part_one()} steps"
print "- occupied seats: ${part_one.occupied_seats_count()}" # 2261
part_two = grid
print "Part two"
print "- seats stabilised in ${part_two.fill_seats_until_stable_part_two()} steps"
print "- occupied seats: ${part_two.occupied_seats_count()}" # 2039
@tests =
@pre_test: ||
self.grid = make_floor_grid "\
L.LL.LL.LL
LLLLLLL.LL
L.L.L..L..
LLLL.LL.LL
L.LL.LL.LL
L.LLLLL.LL
..L.L.....
LLLLLLLLLL
L.LLLLLL.L
L.LLLLL.LL
"
@test part_one: ||
assert_eq self.grid.fill_seats_until_stable_part_one(), 5
assert_eq self.grid.occupied_seats_count(), 37
@test part_two: ||
assert_eq self.grid.fill_seats_until_stable_part_two(), 6
assert_eq self.grid.occupied_seats_count(), 26