From 0c1844622862ba0874c16de8254f355c23fe09e9 Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Tue, 21 Dec 2021 11:12:58 -0600 Subject: [PATCH] Day 19 done --- 2021/nim/day19.nim | 113 +++++++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 45 deletions(-) diff --git a/2021/nim/day19.nim b/2021/nim/day19.nim index 47994c9..cdfd463 100644 --- a/2021/nim/day19.nim +++ b/2021/nim/day19.nim @@ -2,67 +2,90 @@ import ./common, std/[sequtils, algorithm, sugar, sets, strformat, strutils, tab type Vec3 = array[3, int] - BeaconPositions = seq[Vec3] - Sensors = seq[BeaconPositions] + Transform = array[3, (0..2, int)] + Beacons = seq[Vec3] + Scanner = (Option[Vec3], Beacons) Vec3Pair = array[2, Vec3] - DumbDistTable = TableRef[int, Vec3Pair] -iterator permuteTransforms(p: Vec3): seq[Vec3] = - # TODO: +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 dumbDist(a: Vec3, b: Vec3): int = - result = abs(a[0]-b[0]) + abs(a[1]-b[1]) + abs(a[2]-b[2]) - # echo &"dumbDist: {result} from {a} to {b}" +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]): Sensors = +proc parse(l: openArray[string]): seq[Scanner] = var sb: seq[Vec3] = @[] for line in l: if line == "": - result.add sb + result.add (none(Vec3), sb) continue elif line[0] == '-' and line[1] == '-': sb = @[] else: sb.add line.parse - result.add sb + result.add (none(Vec3), sb) -proc p1(input: Sensors): uint64 = - var sensorsDumbDistTable = newTable[int, DumbDistTable]() - for i,s in input.pairs: - echo s - var dumbDistTable: DumbDistTable = newTable[int, Vec3Pair]() - for pair in product([s, s]): - if pair[0] == pair[1]: continue - dumbDistTable[dumbDist(pair[0], pair[1])] = [pair[0], pair[1]] - sensorsDumbDistTable[i] = dumbDistTable - var sensorMatches = newTable[int, int]() - for s1, ddt1 in sensorsDumbDistTable: - var maxMatches = 0 - let kkeys = ddt1.keys.toSeq.sorted - echo &"Sorted {kkeys.len} Keys for Sensor {s1}: {kkeys}" - for s2, ddt2 in sensorsDumbDistTable: - if s1 == s2: continue - var ddMatches: seq[int] = @[] - for dd, vs in ddt1: - if ddt2.hasKey(dd): ddMatches.add dd - if ddMatches.len > maxMatches: - maxMatches = ddMatches.len - sensorMatches[s1] = s2 - echo &"{s1} and {s2} have {ddMatches.len} dd matches: {ddMatches}" - # TODO once we have a solid guess of which sensors overlap using the dumbDist - # method, we'll need to actual math (probably?) to figure out how figure out - # the relative translation and rotation of the overlapping sensor using the - # matched points. once we can do that, we can "correct" the points from each - # sensor's beacons and remove overlapping onces. - # barring "actual math", I hate to imagine that this ends with brute-forcing - echo sensorMatches - 0 +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) -proc p2(input: Sensors): uint64 = - 0'u64 +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, 0'u64) +doDayX 19, (n: int) => n.loadInput.parse, p1, p2, (input, 79'u64, 3621'u64)