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
|
import std/os, std/sugar, std/sequtils, std/deques
type
OctoState = Natural
Map = tuple[map: seq[OctoState], width: int, height: int]
proc read_map(filename: string): Map =
let f = open(filename)
defer: f.close()
result.map = collect:
for line in f.lines():
result.width = line.len
result.height += 1
for c in line:
(c.ord - '0'.ord).OctoState
proc print_map(map: Map) =
for y in countup(0, map.height - 1):
for x in countup(0, map.width - 1):
stdout.write(('0'.ord + map.map[x + map.width * y]).char)
stdout.write('\n')
iterator neighbours(map: Map, i: int): int =
let
x = i mod map.width
y = i div map.width
for dy in countup(-1, 1):
for dx in countup(-1, 1):
if dy == 0 and dx == 0: continue
let
x = x + dx
y = y + dy
if x < 0 or x >= map.width: continue
if y < 0 or y >= map.height: continue
yield x + map.width * y
proc solve(map: Map): tuple[part1, part2: int] =
var
current = map.map
flashed = new_seq[bool](current.len)
pending = init_deque[int](current.len)
flashes = 0
for step in 1..1000:
flashed.apply(proc(_: bool): bool = false)
for i, s in current.mpairs:
inc s
if s > 9: pending.add_first(i)
var sum = 0
while pending.len() > 0:
let i = pending.pop_last()
if flashed[i]: continue
flashed[i] = true
current[i] = 0
inc sum
for i in neighbours(map, i):
if flashed[i]: continue
inc current[i]
if current[i] > 9:
pending.add_first(i)
flashes += sum
if step == 100:
result.part1 = flashes
if sum == map.width * map.height:
result.part2 = step
break
when is_main_module:
var filename: string = "11.in"
if param_count() == 1:
filename = param_str(1)
let map = read_map(filename)
let (part1, part2) = solve(map)
echo part1
echo part2
|