Tapping out on Day 19

This commit is contained in:
2021-12-19 21:12:48 +00:00
parent 34c3b2da7e
commit 0c7c723b40
7 changed files with 464 additions and 0 deletions

View File

@@ -191,3 +191,23 @@ The solution for "eighteen" is:
The magnitude of the final sum is 4202 The magnitude of the final sum is 4202
The largest magnitude of any two snail numbers is 4779 The largest magnitude of any two snail numbers is 4779
``` ```
### Day nineteen
```sh
$ ./aoc2021 --nineteen
The solution for "nineteen" is:
nineteen part 1 answer for map
nineteen part 2 answer for map
```
### Day nineteen
```sh
$ ./aoc2021 --nineteen
The solution for "nineteen" is:
nineteen part 1 answer for mapping
nineteen part 2 answer for mapping
```

View File

@@ -13,6 +13,7 @@ import (
"unsupervised.ca/aoc2021/four" "unsupervised.ca/aoc2021/four"
"unsupervised.ca/aoc2021/fourteen" "unsupervised.ca/aoc2021/fourteen"
"unsupervised.ca/aoc2021/nine" "unsupervised.ca/aoc2021/nine"
"unsupervised.ca/aoc2021/nineteen"
"unsupervised.ca/aoc2021/one" "unsupervised.ca/aoc2021/one"
"unsupervised.ca/aoc2021/seven" "unsupervised.ca/aoc2021/seven"
"unsupervised.ca/aoc2021/seventeen" "unsupervised.ca/aoc2021/seventeen"
@@ -76,6 +77,8 @@ func main() {
day = seventeen.Init("seventeen/input.txt") day = seventeen.Init("seventeen/input.txt")
case "eighteen": case "eighteen":
day = eighteen.Init("eighteen/input.txt") day = eighteen.Init("eighteen/input.txt")
case "nineteen":
day = nineteen.Init("nineteen/input.txt")
default: default:
fmt.Printf("%q does not have a solution.\n", flagParts[1]) fmt.Printf("%q does not have a solution.\n", flagParts[1])
help() help()

0
nineteen/input.txt Normal file
View File

23
nineteen/main.go Normal file
View File

@@ -0,0 +1,23 @@
package nineteen
type Nineteen struct {
mapping mapping
}
func Init(filepath string) *Nineteen {
nineteen := &Nineteen{
mapping: mapping{},
}
nineteen.mapping.load(filepath)
return nineteen
}
func (d *Nineteen) Answer() string {
return "nineteen part 1 answer for mapping"
}
func (d *Nineteen) FollowUp() string {
return "nineteen part 2 answer for mapping"
}

227
nineteen/mapping.go Normal file
View File

@@ -0,0 +1,227 @@
package nineteen
import (
"bufio"
"fmt"
"math"
"os"
"strconv"
"strings"
)
type offset struct {
label string
x int
y int
z int
}
type point struct {
x int
y int
z int
}
type distance struct {
first string
second string
magnitude float64
}
type pair struct {
aIndex int
a distance
bIndex int
b distance
}
type beacon struct {
references map[int]string
}
type scanner struct {
id int
location point
distances []distance
beacons []offset
}
type mapping struct {
scanners []*scanner
beacons []beacon
}
func (m *mapping) load(filename string) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
s := bufio.NewScanner(file)
m.scanners = []*scanner{}
newScanner := true
var scan *scanner
for s.Scan() {
if s.Text() == "" {
newScanner = true
m.scanners = append(m.scanners, scan)
continue
}
if newScanner {
scan = &scanner{}
header := strings.Split(s.Text(), " ")
newScannerID, _ := strconv.Atoi(header[2])
scan.id = newScannerID
newScanner = false
continue
}
coords := strings.Split(s.Text(), ",")
xVal, _ := strconv.Atoi(coords[0])
yVal, _ := strconv.Atoi(coords[1])
zVal, _ := strconv.Atoi(coords[2])
scan.beacons = append(scan.beacons, offset{
label: s.Text(),
x: xVal,
y: yVal,
z: zVal,
})
}
m.scanners = append(m.scanners, scan)
return nil
}
func (m *mapping) initialize() {
// For each scanner initialize the distances between points
for _, s := range m.scanners {
// For each beacon in the scanner find its distance to all others
for i := 0; i < len(s.beacons)-1; i++ {
// We don't need to check i == j ever and don't need to do a full double loop
for j := i + 1; j < len(s.beacons); j++ {
s.distances = append(s.distances, distance{
first: s.beacons[i].label,
second: s.beacons[j].label,
magnitude: distanceMagnitude(s.beacons[i], s.beacons[j]),
})
}
}
}
// Check each scanner for overlap
for i := 0; i < len(m.scanners)-1; i++ {
for j := i + 1; j < len(m.scanners); j++ {
overlapMagnitudes := []pair{}
for _, iDist := range m.scanners[i].distances {
for _, jDist := range m.scanners[j].distances {
if iDist.magnitude == jDist.magnitude {
overlapMagnitudes = append(overlapMagnitudes, pair{
aIndex: i,
a: iDist,
bIndex: j,
b: jDist,
})
}
}
}
if len(overlapMagnitudes) >= 6 {
fmt.Println("Overlap between scanners", i, "and", j)
}
if len(overlapMagnitudes) >= 6 {
for _, p := range overlapMagnitudes {
// Check if we have seen this on another scanner
found := false
var newBeacon *beacon
for _, b := range m.beacons {
if b.references[p.aIndex] == p.a.first {
b.references[p.bIndex] = p.b.first
newBeacon = &beacon{
references: map[int]string{
p.aIndex: p.a.second,
p.bIndex: p.b.second,
},
}
found = true
} else if b.references[p.aIndex] == p.a.second {
b.references[p.bIndex] = p.b.second
newBeacon = &beacon{
references: map[int]string{
p.aIndex: p.a.first,
p.bIndex: p.b.first,
},
}
found = true
}
if b.references[p.bIndex] == p.b.first {
b.references[p.aIndex] = p.a.first
if found {
newBeacon = nil
} else {
newBeacon = &beacon{
references: map[int]string{
p.aIndex: p.a.second,
p.bIndex: p.b.second,
},
}
}
found = true
} else if b.references[p.bIndex] == p.b.second {
b.references[p.bIndex] = p.b.second
if found {
newBeacon = nil
} else {
newBeacon = &beacon{
references: map[int]string{
p.aIndex: p.a.first,
p.bIndex: p.b.first,
},
}
}
found = true
}
if found {
break
}
}
if found {
if newBeacon != nil {
m.beacons = append(m.beacons, *newBeacon)
}
continue
}
b1 := beacon{
references: map[int]string{
p.aIndex: p.a.first,
p.bIndex: p.b.first,
},
}
b2 := beacon{
references: map[int]string{
p.aIndex: p.a.second,
p.bIndex: p.b.second,
},
}
m.beacons = append(m.beacons, b1, b2)
}
}
}
}
}
func distanceMagnitude(a offset, b offset) float64 {
return math.Sqrt(float64(((b.x - a.x) * (b.x - a.x)) + ((b.y - a.y) * (b.y - a.y)) + ((b.z - a.z) * (b.z - a.z))))
}

55
nineteen/mapping_test.go Normal file
View File

@@ -0,0 +1,55 @@
package nineteen
import "testing"
func Test_read(t *testing.T) {
m := mapping{}
if err := m.load("test_input.txt"); err != nil {
t.Log(err)
t.FailNow()
}
if len(m.scanners) != 5 {
t.Logf("Expected 5 scanners, found %d", len(m.scanners))
t.Fail()
}
if len(m.scanners[0].beacons) != 25 {
t.Logf("Expected 25 beacons on scanner %d, found %d", m.scanners[0].id, len(m.scanners[0].beacons))
t.Fail()
}
if len(m.scanners[1].beacons) != 25 {
t.Logf("Expected 25 beacons on scanner %d, found %d", m.scanners[1].id, len(m.scanners[1].beacons))
t.Fail()
}
if len(m.scanners[2].beacons) != 26 {
t.Logf("Expected 26 beacons on scanner %d, found %d", m.scanners[2].id, len(m.scanners[2].beacons))
t.Fail()
}
if len(m.scanners[3].beacons) != 25 {
t.Logf("Expected 25 beacons on scanner %d, found %d", m.scanners[3].id, len(m.scanners[3].beacons))
t.Fail()
}
if len(m.scanners[4].beacons) != 26 {
t.Logf("Expected 26 beacons on scanner %d, found %d", m.scanners[4].id, len(m.scanners[4].beacons))
t.Fail()
}
}
func Test_initialize(t *testing.T) {
m := mapping{}
m.load("test_input.txt")
m.initialize()
beaconCount := len(m.beacons)
if beaconCount != 79 {
t.Logf("Expected 79 beacons, found %d", beaconCount)
t.Fail()
}
}

136
nineteen/test_input.txt Normal file
View File

@@ -0,0 +1,136 @@
--- 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