diff options
-rw-r--r-- | d11.nim | 76 |
1 files changed, 76 insertions, 0 deletions
@@ -0,0 +1,76 @@ +import std/os, std/sugar, std/strutils, std/sequtils + +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') + +proc solve(map: Map): tuple[part1, part2: int] = + var + current = map.map + flashed = new_seq[bool](current.len) + flash = new_seq[bool](current.len) + flashes = 0 + for step in 1..1000: + #print_map((current, map.width, map.height)) + #echo "" + flashed.apply(proc(_: bool): bool = false) + current.apply(proc(s: OctoState): OctoState = s + 1) + while true: + var any = false + flash.apply(proc(_: bool): bool = false) + for i, s in current: + if flashed[i] or s <= 9: continue + flashed[i] = true + flash[i] = true + any = true + if not any: break + for i, s in flash: + if not s: continue + let + x = i mod map.width + y = i div map.width + for dy in countup(-1, 1): + for dx in countup(-1, 1): + if dx == 0 and dy == 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 + inc current[x + map.width * y] + var sum = 0 + for i, s in flashed: + if not s: continue + current[i] = 0 + inc sum + 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 |