adventofcode/2021/day19/structs.go

127 lines
2.9 KiB
Go

package main
import (
"errors"
"fmt"
"strings"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
type scanner struct {
number int
region map[h.Coordinate]bool
beacons []beacon
}
func NewScanner(b []beacon) scanner {
return scanner{beacons: b}
}
func NewScannerFromInput(inp []string) (scanner, error) {
s := scanner{}
r := strings.NewReader(inp[0])
_, err := fmt.Fscanf(r, "--- scanner %d ---", &s.number)
if err != nil {
return s, errors.New("No Scanner ID")
}
for _, v := range inp[1:] {
r = strings.NewReader(v)
b := beacon{}
_, err := fmt.Fscanf(r, "%d,%d,%d", &b.x, &b.y, &b.z)
if err == nil {
s.beacons = append(s.beacons, b)
}
}
return s, nil
}
func (s scanner) allRotations() []scanner {
var ret []scanner
var beacons [][]beacon
for i := range s.beacons {
beacons = append(beacons, s.beacons[i].allRotations())
}
for i := range beacons {
ret = append(ret, NewScanner(beacons[i]))
}
return ret
}
func (s scanner) getTransformedIfOverlap(w scanner) (transformedScanner, error) {
for _, otherReoriented := range w.allRotations() {
for _, first := range s.beacons {
for _, second := range otherReoriented.beacons {
otherPosition := first.sub(second)
var otherTransformed []beacon
for _, it := range otherReoriented.beacons {
otherTransformed = append(otherTransformed, otherPosition.add(it))
}
// Check if otherTransformed has at least 12 beacons in common with s
var count int
for _, chkI := range otherTransformed {
for _, chkJ := range s.beacons {
if chkI.equals(chkJ) {
count++
if count >= 12 {
return transformedScanner{
beacons: otherTransformed,
position: otherPosition,
}, nil
}
}
}
}
}
}
}
return transformedScanner{}, errors.New("Scanners don't overlap")
}
func (s scanner) String() string {
return fmt.Sprintf("-- Scanner %d (%d beacons) ---", s.number, len(s.beacons))
}
type beacon struct {
x, y, z int
}
func (b beacon) sub(c beacon) beacon {
return beacon{
x: b.x - c.x,
y: b.y - c.y,
z: b.z - c.z,
}
}
func (b beacon) add(c beacon) beacon {
return beacon{
x: b.x + c.x,
y: b.y + c.y,
z: b.z + c.z,
}
}
func (b beacon) equals(c beacon) bool {
return b.x == c.x && b.y == c.y && b.z == c.z
}
func (b beacon) allRotations() []beacon {
return []beacon{
{b.x, b.y, b.z}, {b.x, -b.z, b.y}, {b.x, -b.y, -b.z}, {b.x, b.z, -b.y}, {-b.x, -b.y, b.z},
{-b.x, -b.z, -b.y}, {-b.x, b.y, -b.z}, {-b.x, b.z, b.y}, {-b.z, b.x, -b.y}, {b.y, b.x, -b.z},
{b.z, b.x, b.y}, {-b.y, b.x, b.z}, {b.z, -b.x, -b.y}, {b.y, -b.x, b.z}, {-b.z, -b.x, b.y},
{-b.y, -b.x, -b.z}, {-b.y, -b.z, b.x}, {b.z, -b.y, b.x}, {b.y, b.z, b.x}, {-b.z, b.y, b.x},
{b.z, b.y, -b.x}, {-b.y, b.z, -b.x}, {-b.z, -b.y, -b.x}, {b.y, -b.z, -b.x},
}
}
func (b beacon) String() string {
return fmt.Sprintf("{%d,%d,%d}", b.x, b.y, b.z)
}
type transformedScanner struct {
beacons []beacon
position beacon
}