From 8f12a7278c14062d1c2b8e98769f1329527daf1e Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Thu, 23 Dec 2021 14:08:01 -0600 Subject: [PATCH] Finally day22 done --- 2021/nim/day22.nim | 189 +++++++++++++-------------------------------- 1 file changed, 52 insertions(+), 137 deletions(-) diff --git a/2021/nim/day22.nim b/2021/nim/day22.nim index e0f0d68..99190ca 100644 --- a/2021/nim/day22.nim +++ b/2021/nim/day22.nim @@ -1,14 +1,10 @@ import ./common, std/[sequtils, algorithm, sugar, sets, strformat, strutils, tables, options, json, hashes, random, pegs] -const BOARD_POSITIONS = 10 - type - Vec3 = tuple[x: int, y: int, z: int] - Cuboid = tuple[pos: Vec3, size: Vec3] - CuboidGeometry = HashSet[Cuboid] - + Cuboid = (int, int, int, int, int, int) CuboidOperator = enum union, difference CuboidOperation = (CuboidOperator, Cuboid) + CuboidOperations = HashSet[CuboidOperation] let parser = peg""" grammar <- {'on' / 'off'} ' x=' range ',y=' range ',z=' range @@ -16,151 +12,72 @@ range <- {num} \. \. {num} num <- ('-' \d+) / \d+ """ -proc apply(a: Vec3, b: Vec3, f: (int, int) -> int): Vec3 = (x: f(a.x, b.x), y: f(a.y, b.y), z: f(a.z, b.z)) -proc `+`(a: Vec3, b: Vec3): Vec3 = a.apply(b, (a, b) => a + b) -proc `-`(a: Vec3, b: Vec3): Vec3 = a.apply(b, (a, b) => a - b) -proc `*`(a: Vec3, b: Vec3): Vec3 = a.apply(b, (a, b) => a * b) -proc volume(a: Vec3): uint64 = a.x.abs.uint64 * a.y.abs.uint64 * a.z.abs.uint64 -proc volume(c: CuboidGeometry): uint64 = - for cb in c: result += cb.size.volume -proc min(a: Vec3, b: Vec3): Vec3 = a.apply(b, (a, b) => min(a, b)) -proc max(a: Vec3, b: Vec3): Vec3 = a.apply(b, (a, b) => max(a, b)) -proc v3(x: int, y: int, z: int): Vec3 = (x: x, y: y, z: z) -proc cuboid(pos: Vec3, size: Vec3): Cuboid = (pos: pos, size: size) -proc cuboid(x: int, y: int, z: int, w: int, d: int, h: int): Cuboid = cuboid(v3(x, y, z), v3(w, d, h)) - proc parseCuboidOperator(s: string): CuboidOperator = if s[1] == 'n': union else: difference proc parse(s: string): Option[CuboidOperation] = if s =~ parser: - let - n = matches[1..6].map parseInt - pos = v3(min(n[0], n[1]), min(n[2], n[3]), min(n[4], n[5])) - size = v3(max(n[0], n[1]) + 1, max(n[2], n[3]) + 1, max(n[4], n[5]) + 1) - pos - result = some (matches[0].parseCuboidOperator, (pos, size)) + let n: seq[int] = matches[1..6].map(parseInt) + return some (matches[0].parseCuboidOperator, (n[0], n[1], n[2], n[3], n[4], n[5])) -proc vertices(c: Cuboid): array[6, Vec3] = - result[0] = c.pos - result[1] = c.pos + (c.size * v3(1, 0, 0)) - result[2] = c.pos + (c.size * v3(0, 1, 0)) - result[3] = c.pos + (c.size * v3(0, 0, 1)) - result[4] = c.pos + (c.size * v3(1, 1, 0)) - result[5] = c.pos + (c.size * v3(1, 1, 1)) +proc asOps(l: Lines): seq[CuboidOperation] = + for s in l: + let cop = s.parse + if cop.isNone: continue + result.add cop.get -proc contains(a: Cuboid, b: Vec3): bool = - b.x >= a.pos.x and b.x <= (a.pos.x + a.size.x) and - b.y >= a.pos.y and b.y <= (a.pos.y + a.size.y) and - b.z >= a.pos.z and b.z <= (a.pos.z + a.size.z) +proc intersection(n: Cuboid, p: Cuboid): Option[Cuboid] = + let (nx1, nx2, ny1, ny2, nz1, nz2) = n + let (px1, px2, py1, py2, pz1, pz2) = p + if nx1 <= px2 and px1 <= nx2 and ny1 <= py2 and py1 <= ny2 and nz1 <= pz2 and pz1 <= nz2: + return some (max(px1, nx1), min(px2, nx2), max(py1, ny1), min(py2, ny2), max(pz1, nz1), min(pz2, nz2)) -proc contains(a: Cuboid, b: Cuboid): bool = b.vertices.allIt a.contains it +proc merge(pastOps: var CuboidOperations, newOp: CuboidOperation) = + var toIncl = initHashSet[CuboidOperation]() + var toExcl = initHashSet[CuboidOperation]() + var included = false -proc intersect(a: Cuboid, b: Cuboid): Option[Cuboid] = - let amx = a.pos + a.size - let bmx = b.pos + b.size - if amx.x < b.pos.x or bmx.x < a.pos.x or - amx.y < b.pos.y or bmx.y < a.pos.y or - amx.z < b.pos.z or bmx.z < a.pos.z: - return none Cuboid - let pos = max(a.pos, b.pos) - some (pos: pos, size: min(amx, bmx) - pos) + for pastOp in pastOps: + let (pastOpType, pastCuboid) = pastOp + let intersect = pastCuboid.intersection newOp[1] + if intersect.isNone: continue + included = true + toExcl.incl pastOp -proc difference(a: Cuboid, b: Cuboid): HashSet[Cuboid] = - let amx = a.pos + a.size - let bmx = b.pos + b.size - var xx = [(b.pos.x, b.size.x)].toSeq - var yy = [(b.pos.y, b.size.y)].toSeq - var zz = [(b.pos.z, b.size.z)].toSeq - echo &"difference:\n ==> {a}\n ==> {b}\n -> {amx}, {bmx}" - if a.pos.x < b.pos.x: xx.add (a.pos.x, b.pos.x - a.pos.x) - if bmx.x < amx.x: xx.add (bmx.x, amx.x) - if a.pos.y < b.pos.y: yy.add (a.pos.y, b.pos.y - a.pos.y) - if bmx.y < amx.y: yy.add (bmx.y, amx.y) - if a.pos.z < b.pos.z: zz.add (a.pos.z, b.pos.z - a.pos.z) - if bmx.z < amx.z: zz.add (bmx.z, amx.z) - echo &"xyz diff: {xx}, {yy}, {zz}" - for xi in 0.. 50)): continue + ops.merge op + for op in ops: + let (t, c) = op + if t == union: + let (x1, x2, y1, y2, z1, z2) = c + result += (abs(x2 - x1 + 1) * abs(y2 - y1 + 1) * abs(z2 - z1 + 1)).uint64 proc p2(input: Lines): uint64 = + echo "p2" 0 -# const alt = (""" -# on x=0..9,y=0..9,z=0..9 -# on x=-4..3,y=5..6,z=7..8 -# """.strip().split('\n'), 1016'u64, 0'u64) - -const alt = (""" -on x=0..1,y=0..0,z=0..0 -off x=0..0,y=0..0,z=0..0 -""".strip().split('\n'), 1'u64, 0'u64) - -const input = """ -on x=-20..26,y=-36..17,z=-47..7 +const rt = ("""on x=-20..26,y=-36..17,z=-47..7 on x=-20..33,y=-21..23,z=-26..28 on x=-22..28,y=-29..23,z=-38..16 on x=-46..7,y=-6..46,z=-50..-1 @@ -181,7 +98,5 @@ on x=-49..-5,y=-3..45,z=-29..18 off x=18..30,y=-20..-8,z=-3..13 on x=-41..9,y=-7..43,z=-33..15 on x=-54112..-39298,y=-85059..-49293,z=-27449..7877 -on x=967..23432,y=45373..81175,z=27513..53682 -""".strip().split('\n') -const rt = (input, 590784'u64, 0'u64) -doDayX 22, (n: int) => n.loadInput, p1, p2, alt +on x=967..23432,y=45373..81175,z=27513..53682""".split('\n'), 590784'u64, 0'u64) +doDayX 22, (n: int) => n.loadInput, p1, p2, rt