adventOfCode/challenges/2021/20-trenchMap/nim/challenge.nim
AKU 59ed9b27d2
nimpretty
Signed-off-by: AKU <tom@tdpain.net>
2021-12-20 20:46:28 +00:00

102 lines
2.4 KiB
Nim

import std/tables
import std/strutils
import std/sequtils
import std/enumerate
const
LIT = '#'
UNLIT = '.'
type
Point = (int, int)
Image = Table[Point, char]
proc parse(instr: string): (string, Image) =
let
sp = instr.strip.split("\n\n")
algo = sp[0]
image = sp[1]
var imageTable = Image()
for y, line in enumerate(image.splitLines):
for x, pixel in line[0..^1]:
if pixel == LIT:
imageTable[(x, y)] = pixel
return (algo, imageTable)
proc getAdjacentPoints(centerPoint: Point): array[0..8, Point] =
let (x, y) = centerPoint
return [
(x - 1, y - 1),
(x, y - 1),
(x + 1, y - 1),
(x - 1, y),
(x, y),
(x + 1, y),
(x - 1, y + 1),
(x, y + 1),
(x + 1, y + 1),
]
proc enhanceN(image: Image, algorithm: string, n: int): Image =
result = image
for i in 0..<n:
let
keysSeq = toSeq(result.keys)
xVals = map(keysSeq, (proc(p: Point): int = p[0]))
yVals = map(keysSeq, (proc(p: Point): int = p[1]))
minX = min(xVals)
maxX = max(xVals)
minY = min(yVals)
maxY = max(yVals)
var changes = Image()
for y in minY - 2 ..< maxY + 2:
for x in minX - 2 ..< maxX + 2:
let p = (x, y)
var n: int
for point in getAdjacentPoints(p):
let (px, py) = point
var isLit: bool
if algorithm[0] == LIT and not (minX <= px and px <=
maxX and minY <= py and py <= maxY):
isLit = i mod 2 != 0
else:
isLit = result.getOrDefault(point, UNLIT) == LIT
n = n shl 1
if isLit:
n = n or 0b1
changes[p] = algorithm[n]
for point, change in changes.pairs:
if change == UNLIT and point in result:
result.del(point)
elif change == LIT:
result[point] = LIT
proc core(instr: string, n: int): int =
let
parsed = parse(instr)
algorithm = parsed[0]
var image = parsed[1]
image = enhanceN(image, algorithm, n)
return len(image)
proc partOne*(instr: string): int =
return core(instr, 2)
proc partTwo*(instr: string): int =
return core(instr, 50)