import ./common, std/[sequtils, algorithm, sugar, sets, strformat, strutils, tables, options, json, hashes] type Vec3 = array[3, int] Transform = array[3, (0..2, int)] Beacons = seq[Vec3] Scanner = (Option[Vec3], Beacons) Vec3Pair = array[2, Vec3] const TRANSFORMS: seq[Transform] = collect: let x: 0..2 = 0 let y: 0..2 = 1 let z: 0..2 = 2 for xs in [-1, 1]: for ys in [-1, 1]: for zs in [-1, 1]: for t in [[x, y, z], [x, z, y], [y, x, z], [y, z, x], [z, x, y], [z, y, x]]: [(t[0], xs), (t[1], ys), (t[2], zs)] proc `*`(v: Vec3, t: Transform): Vec3 = [v[t[0][0]] * t[0][1], v[t[1][0]] * t[1][1], v[t[2][0]] * t[2][1]] proc `+`(a: Vec3, b: Vec3): Vec3 = [a[0] + b[0], a[1] + b[1], a[2] + b[2]] proc `-`(a: Vec3, b: Vec3): Vec3 = [a[0] - b[0], a[1] - b[1], a[2] - b[2]] proc parse(s: string): Vec3 = let l = s.split(",", 3).map parseInt [l[0], l[1], l[2]] proc parse(l: openArray[string]): seq[Scanner] = var sb: seq[Vec3] = @[] for line in l: if line == "": result.add (none(Vec3), sb) continue elif line[0] == '-' and line[1] == '-': sb = @[] else: sb.add line.parse result.add (none(Vec3), sb) proc maybeGetScannerTransform(s1: Scanner, s2: Scanner): Option[(Vec3, Transform)] = let (knownPos, beacons1) = s1 let (_, beacons2) = s2 for t in TRANSFORMS: var dists = newCountTable[Vec3]() for b1 in beacons1: for b2 in beacons2: let dist = b1 - (b2*t) dists.inc dist if dists[dist] >= 12: return some (dist, t) none (Vec3, Transform) var scanners: seq[Scanner] = @[] proc p1(input: seq[Scanner]): uint64 = scanners = input scanners[0][0] = some [0, 0, 0] var known = @[0] var needTransform = toSeq(1.. 0: block checker: for ix in 0.. n.loadInput.parse, p1, p2, (input, 79'u64, 3621'u64)