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