aoc/2023/nim/11/day11.nim

77 lines
1.8 KiB
Nim

import std/sequtils
import std/strutils
import tables
type Point = tuple
x: int
y: int
type Area* = ref object
data: seq[string]
x, y: int
proc charAt(a: Area, p: Point): char =
a.data[p.x][p.y]
iterator eachPChar(a: Area): (Point, char) =
for x in 0..a.x - 1:
for y in 0..a.y - 1:
let p = (x, y)
yield (p, a.charAt(p))
iterator column(a: Area, y: int): char =
for x in 0..a.x - 1:
yield a.charAt((x, y))
proc realPosition(t: Table[Point, Point], g: Point): Point =
let offset = t[g]
(g.x + offset.x, g.y + offset.y)
proc solve(a: Area, galaxies: Table[Point, Point], offset: int): int =
var galaxies = galaxies
let offset = offset - 1
for x in 0..a.x - 1:
if a.data[x].allIt(it == '.'):
for pos, off in galaxies:
if pos.x > x:
galaxies[pos] = (off.x + offset, off.y)
for y in 0..a.y - 1:
if a.column(y).toSeq.allIt(it == '.'):
for pos, off in galaxies:
if pos.y > y:
galaxies[pos] = (off.x, off.y + offset)
var distances = initTable[(Point, Point), int]()
for g1 in galaxies.keys:
for g2 in galaxies.keys:
if g1 != g2 and (g1, g2) notin distances and (g2, g1) notin distances:
let r1 = realPosition(galaxies, g1)
let r2 = realPosition(galaxies, g2)
let d = abs(r1.x - r2.x) + abs(r1.y - r2.y)
distances[(g1, g2)] = d
distances.values.toSeq.foldl(a + b)
proc main() =
let s = readAll(stdin)
var lines = splitLines(s)
let a = Area(data: lines, x: (len lines) - 1, y: len lines[0])
var galaxies = initTable[Point, Point]()
for p, c in a.eachPChar:
if c == '#':
galaxies[p] = (0, 0)
let p1 = solve(a, galaxies, 2)
let p2 = solve(a, galaxies, 1000000)
echo "Part 1: $1" % [$p1]
echo "Part 2: $1" % [$p2]
when isMainModule:
main()