2021 - Day 19
This commit is contained in:
parent
742c215867
commit
1e481db7f1
9
2021/19/go.mod
Normal file
9
2021/19/go.mod
Normal file
|
@ -0,0 +1,9 @@
|
|||
module AoC/2021/19
|
||||
|
||||
require AoC/2021/common v0.0.0
|
||||
|
||||
require github.com/joho/godotenv v1.4.0 // indirect
|
||||
|
||||
replace AoC/2021/common v0.0.0 => ../common
|
||||
|
||||
go 1.17
|
2
2021/19/go.sum
Normal file
2
2021/19/go.sum
Normal file
|
@ -0,0 +1,2 @@
|
|||
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
|
||||
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
410
2021/19/main.go
Normal file
410
2021/19/main.go
Normal file
|
@ -0,0 +1,410 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
aoc "AoC/2021/common"
|
||||
"bufio"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Vec struct {
|
||||
X int
|
||||
Y int
|
||||
Z int
|
||||
}
|
||||
|
||||
func intcos(i int) int {
|
||||
var cos int
|
||||
switch i {
|
||||
case 0:
|
||||
cos = 1
|
||||
case 1,3:
|
||||
cos = 0
|
||||
case 2:
|
||||
cos = -1
|
||||
default:
|
||||
panic("Invalid rotation")
|
||||
}
|
||||
|
||||
return cos
|
||||
}
|
||||
|
||||
func intsin(i int) int {
|
||||
var sin int
|
||||
switch i {
|
||||
case 0, 2:
|
||||
sin = 0
|
||||
case 1:
|
||||
sin = 1
|
||||
case 3:
|
||||
sin = -1
|
||||
default:
|
||||
panic("Invalid rotation")
|
||||
}
|
||||
|
||||
return sin
|
||||
}
|
||||
|
||||
// We only allow 90 degree rotations
|
||||
func (v Vec) rotate(r Vec) Vec {
|
||||
var out Vec
|
||||
|
||||
cosX := intcos(r.X)
|
||||
sinX := intsin(r.X)
|
||||
|
||||
cosY := intcos(r.Y)
|
||||
sinY := intsin(r.Y)
|
||||
|
||||
cosZ := intcos(r.Z)
|
||||
sinZ := intsin(r.Z)
|
||||
|
||||
Axx := cosZ*cosY
|
||||
Axy := cosZ*sinY*sinX - sinZ*cosX
|
||||
Axz := cosZ*sinY*cosX + sinZ*sinX
|
||||
|
||||
Ayx := sinZ*cosY
|
||||
Ayy := sinZ*sinY*sinX + cosZ*cosX
|
||||
Ayz := sinZ*sinY*cosX - cosZ*sinX
|
||||
|
||||
Azx := -sinY
|
||||
Azy := cosY*sinX
|
||||
Azz := cosY*cosX
|
||||
|
||||
out.X = Axx*v.X + Axy*v.Y + Axz*v.Z
|
||||
out.Y = Ayx*v.X + Ayy*v.Y + Ayz*v.Z
|
||||
out.Z = Azx*v.X + Azy*v.Y + Azz*v.Z
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (a Vec) add(b Vec) Vec {
|
||||
var out Vec
|
||||
|
||||
out.X = a.X + b.X
|
||||
out.Y = a.Y + b.Y
|
||||
out.Z = a.Z + b.Z
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (a Vec) subtract(b Vec) Vec {
|
||||
var out Vec
|
||||
|
||||
out.X = a.X - b.X
|
||||
out.Y = a.Y - b.Y
|
||||
out.Z = a.Z - b.Z
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (a Vec) equals(b Vec) bool {
|
||||
return a.X == b.X && a.Y == b.Y && a.Z == b.Z
|
||||
}
|
||||
|
||||
func (a Vec) distance(b Vec) int {
|
||||
x := a.X - b.X
|
||||
if x < 0 {
|
||||
x = -x
|
||||
}
|
||||
|
||||
y := a.Y - b.Y
|
||||
if y < 0 {
|
||||
y = -y
|
||||
}
|
||||
|
||||
z := a.Z - b.Z
|
||||
if z < 0 {
|
||||
z = -z
|
||||
}
|
||||
|
||||
return x + y + z
|
||||
}
|
||||
|
||||
type Scanner struct {
|
||||
ID int
|
||||
Position Vec
|
||||
Beacons []Vec
|
||||
}
|
||||
|
||||
func mapScanners(input *bufio.Scanner) []Scanner {
|
||||
var scanners []Scanner
|
||||
var scanner *Scanner
|
||||
for input.Scan() {
|
||||
line := input.Text()
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Contains(line, "scanner") {
|
||||
id := len(scanners)
|
||||
scanners = append(scanners, Scanner{ID: id})
|
||||
scanner = &scanners[id]
|
||||
} else {
|
||||
parts := strings.Split(line, ",")
|
||||
var coords [3]int
|
||||
for i, p := range parts {
|
||||
coords[i], _ = strconv.Atoi(p)
|
||||
}
|
||||
|
||||
scanner.Beacons = append(scanner.Beacons, Vec{X: coords[0], Y: coords[1], Z: coords[2]})
|
||||
}
|
||||
}
|
||||
|
||||
var known []*Scanner
|
||||
known = append(known, &scanners[0])
|
||||
|
||||
for j := 0; j < len(known); j++ {
|
||||
ref := known[j]
|
||||
fmt.Printf("Scanner %d is reference\n", ref.ID)
|
||||
|
||||
outer:
|
||||
for i := range scanners {
|
||||
for k := range known {
|
||||
if scanners[i].ID == known[k].ID {
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
|
||||
matcher:
|
||||
// Pick a reference point for each beacon
|
||||
for _, pref := range ref.Beacons {
|
||||
for _, pi := range scanners[i].Beacons {
|
||||
counter := 0
|
||||
|
||||
// Go through all the points in the beacons
|
||||
for _, bref := range ref.Beacons {
|
||||
for _, bi := range scanners[i].Beacons {
|
||||
// If the distance to the respective beacon is the same it is an indaction that they might be the same point
|
||||
if bref.distance(pref) == bi.distance(pi) {
|
||||
counter++
|
||||
|
||||
// If we find 12 points of overlap we can assume that they overlap
|
||||
if counter >= 12 {
|
||||
// Since the beacons overlap compared to their respective reference point,
|
||||
// we know that bref should be equal bi and pref should be equal to pi
|
||||
// So we can form two vectors, these should have the same magnitude and direction
|
||||
l1 := bref.subtract(pref)
|
||||
l2 := bi.subtract(pi)
|
||||
|
||||
var rot Vec
|
||||
|
||||
// In order to find the correct rotation we just apply all 24 rotations
|
||||
// and figure out which result in l1 = l2
|
||||
rotate:
|
||||
for rx := 0; rx < 4; rx++ {
|
||||
for ry := 0; ry < 4; ry++ {
|
||||
for rz := 0; rz < 4; rz++ {
|
||||
rot = Vec{rx, ry, rz}
|
||||
if l1.equals(l2.rotate(rot)) {
|
||||
fmt.Printf("Rotation is %v\n", rot)
|
||||
break rotate
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the postion of the scanner and all the beacons
|
||||
scanners[i].Position = bref.subtract(bi.rotate(rot))
|
||||
for k := range scanners[i].Beacons {
|
||||
scanners[i].Beacons[k] = scanners[i].Position.add(scanners[i].Beacons[k].rotate(rot))
|
||||
}
|
||||
|
||||
known = append(known, &scanners[i])
|
||||
|
||||
fmt.Printf("Scanner %d is positioned at %v\n", scanners[i].ID, scanners[i].Position)
|
||||
break matcher
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return scanners
|
||||
}
|
||||
|
||||
func main() {
|
||||
challenge := aoc.New(2021, 19)
|
||||
|
||||
challenge.Test(`--- scanner 0 ---
|
||||
404,-588,-901
|
||||
528,-643,409
|
||||
-838,591,734
|
||||
390,-675,-793
|
||||
-537,-823,-458
|
||||
-485,-357,347
|
||||
-345,-311,381
|
||||
-661,-816,-575
|
||||
-876,649,763
|
||||
-618,-824,-621
|
||||
553,345,-567
|
||||
474,580,667
|
||||
-447,-329,318
|
||||
-584,868,-557
|
||||
544,-627,-890
|
||||
564,392,-477
|
||||
455,729,728
|
||||
-892,524,684
|
||||
-689,845,-530
|
||||
423,-701,434
|
||||
7,-33,-71
|
||||
630,319,-379
|
||||
443,580,662
|
||||
-789,900,-551
|
||||
459,-707,401
|
||||
|
||||
--- scanner 1 ---
|
||||
686,422,578
|
||||
605,423,415
|
||||
515,917,-361
|
||||
-336,658,858
|
||||
95,138,22
|
||||
-476,619,847
|
||||
-340,-569,-846
|
||||
567,-361,727
|
||||
-460,603,-452
|
||||
669,-402,600
|
||||
729,430,532
|
||||
-500,-761,534
|
||||
-322,571,750
|
||||
-466,-666,-811
|
||||
-429,-592,574
|
||||
-355,545,-477
|
||||
703,-491,-529
|
||||
-328,-685,520
|
||||
413,935,-424
|
||||
-391,539,-444
|
||||
586,-435,557
|
||||
-364,-763,-893
|
||||
807,-499,-711
|
||||
755,-354,-619
|
||||
553,889,-390
|
||||
|
||||
--- scanner 2 ---
|
||||
649,640,665
|
||||
682,-795,504
|
||||
-784,533,-524
|
||||
-644,584,-595
|
||||
-588,-843,648
|
||||
-30,6,44
|
||||
-674,560,763
|
||||
500,723,-460
|
||||
609,671,-379
|
||||
-555,-800,653
|
||||
-675,-892,-343
|
||||
697,-426,-610
|
||||
578,704,681
|
||||
493,664,-388
|
||||
-671,-858,530
|
||||
-667,343,800
|
||||
571,-461,-707
|
||||
-138,-166,112
|
||||
-889,563,-600
|
||||
646,-828,498
|
||||
640,759,510
|
||||
-630,509,768
|
||||
-681,-892,-333
|
||||
673,-379,-804
|
||||
-742,-814,-386
|
||||
577,-820,562
|
||||
|
||||
--- scanner 3 ---
|
||||
-589,542,597
|
||||
605,-692,669
|
||||
-500,565,-823
|
||||
-660,373,557
|
||||
-458,-679,-417
|
||||
-488,449,543
|
||||
-626,468,-788
|
||||
338,-750,-386
|
||||
528,-832,-391
|
||||
562,-778,733
|
||||
-938,-730,414
|
||||
543,643,-506
|
||||
-524,371,-870
|
||||
407,773,750
|
||||
-104,29,83
|
||||
378,-903,-323
|
||||
-778,-728,485
|
||||
426,699,580
|
||||
-438,-605,-362
|
||||
-469,-447,-387
|
||||
509,732,623
|
||||
647,635,-688
|
||||
-868,-804,481
|
||||
614,-800,639
|
||||
595,780,-596
|
||||
|
||||
--- scanner 4 ---
|
||||
727,592,562
|
||||
-293,-554,779
|
||||
441,611,-461
|
||||
-714,465,-776
|
||||
-743,427,-804
|
||||
-660,-479,-426
|
||||
832,-632,460
|
||||
927,-485,-438
|
||||
408,393,-506
|
||||
466,436,-512
|
||||
110,16,151
|
||||
-258,-428,682
|
||||
-393,719,612
|
||||
-211,-452,876
|
||||
808,-476,-593
|
||||
-575,615,604
|
||||
-485,667,467
|
||||
-680,325,-822
|
||||
-627,-443,-432
|
||||
872,-547,-609
|
||||
833,512,582
|
||||
807,604,487
|
||||
839,-516,451
|
||||
891,-625,532
|
||||
-652,-548,-490
|
||||
30,-46,-14`, []int{79, 3621})
|
||||
|
||||
challenge.Solution(1, func (input *bufio.Scanner) int {
|
||||
scanners := mapScanners(input)
|
||||
|
||||
var beacons []Vec
|
||||
for _, scanner := range scanners {
|
||||
findUnique:
|
||||
for _, beacon := range scanner.Beacons {
|
||||
for _, b := range beacons {
|
||||
if beacon.equals(b) {
|
||||
continue findUnique
|
||||
}
|
||||
}
|
||||
|
||||
beacons = append(beacons, beacon)
|
||||
}
|
||||
}
|
||||
|
||||
return len(beacons)
|
||||
})
|
||||
|
||||
challenge.Solution(2, func (input *bufio.Scanner) int {
|
||||
scanners := mapScanners(input)
|
||||
|
||||
largest := 0
|
||||
for _, a := range scanners {
|
||||
for _, b := range scanners {
|
||||
if a.ID == b.ID {
|
||||
continue
|
||||
}
|
||||
|
||||
distance := a.Position.distance(b.Position)
|
||||
|
||||
if distance > largest {
|
||||
fmt.Printf("Scanner %d and %d are the farthest apart\n", a.ID, b.ID)
|
||||
largest = distance
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return largest
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user