def allRotations (a : Array (Int × Int × Int)) : Array (Array (Int × Int × Int)) := do
rots := rots.push $ a.map (λ(x,y,z) => (x, -z, y))
rots := rots.push $ a.map (λ(x,y,z) => (z, y, -x))
rots := rots.push $ a.map (λ(x,y,z) => (-y, x, z))
def allCombinations (a : Array (Int × Int × Int)) : Array (Array (Int × Int × Int)) := do
for a1 in allRotations a do
for a2 in allRotations a1 do
for a3 in allRotations a2 do
for a4 in allRotations a3 do
if combs.contains a4 then pure () else
def allCombinationsFun : List ((Int × Int × Int) -> (Int × Int × Int)) :=
λ(a, b, c) => (c, b, -a),
λ(a, b, c) => (b, a, -c),
λ(a, b, c) => (a, c, -b),
λ(a, b, c) => (a, -b, -c),
λ(a, b, c) => (b, -c, -a),
λ(a, b, c) => (c, -a, -b),
λ(a, b, c) => (c, -b, a),
λ(a, b, c) => (b, -a, c),
λ(a, b, c) => (a, -c, b),
λ(a, b, c) => (-a, b, -c),
λ(a, b, c) => (-b, c, -a),
λ(a, b, c) => (-c, a, -b),
λ(a, b, c) => (-c, b, a),
λ(a, b, c) => (-b, a, c),
λ(a, b, c) => (-a, c, b),
λ(a, b, c) => (-a, -b, c),
λ(a, b, c) => (-b, -c, a),
λ(a, b, c) => (-c, -a, b),
λ(a, b, c) => (-c, -b, -a),
λ(a, b, c) => (-b, -a, -c),
λ(a, b, c) => (-a, -c, -b)
def allCombinationsAlt (a : Array (Int × Int × Int)) : Array (Array (Int × Int × Int)) := do
for f in allCombinationsFun do
array := array.push $ a.map f
def sharedPoints (a b : Array (Int × Int × Int)) : (Nat × Array (Int × Int × Int)) := do
contained := contained + 1
def findOverLap (a b : Array (Int × Int × Int)) : Option ((Int × Int × Int) × Array (Int × Int × Int)) := do
for f in allCombinationsFun do
for i in [:b.size - 11] do
let (b1, b2, b3) := bp[i]
let d@(d1, d2, d3) := (a1-b1, a2-b2, a3-b3)
let nb := bp.map $ λ(x, y, z) => (x+d1, y+d2, z+d3)
let (contained, union) := sharedPoints a nb
if contained < 12 then pure () else do
if sol == none then pure () else break
if sol == none then pure () else break
def merge (a b: Array (Int × Int × Int)) : Array (Int × Int × Int) :=
match findOverLap a b with
| none => dbgTrace "No overlap" $ fun _ => a
partial def mergeAll (acc: Array (Int × Int × Int)) : List (Array (Int × Int × Int)) → Array (Int × Int × Int)
| (x :: ys) => match findOverLap acc x with
| none => dbgTrace [ys.length + 1].toString $ fun _ => mergeAll acc (ys ++ [x])
| some (offset, b) => mergeAll b ys
def scanTriple (x:String) : (Int × Int × Int) :=
let ls := ((x.splitOn ",").map (String.toInt!)).toArray
def main (args : List String) : IO UInt32 :=
let input ← IO.FS.lines "input.txt"
let mut currentScanner := #[]
scanners := scanners.push currentScanner
else if line.startsWith "--- scanner" then
let triple := scanTriple line
currentScanner := currentScanner.push triple
scanners := scanners.push currentScanner
let ground := mergeAll scanners[0] scanners.toList.tail!