adventofcode/2021/day19/structs.go.old.2

193 lines
3.4 KiB
Groff

package main
import (
"errors"
"fmt"
"sort"
"strings"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
type Pair struct {
a int
b int
}
type Translation struct {
orig, foreign, rotID int
}
type Triangle struct {
a, b, c Beacon
circumference, area int
}
func NewTriangle(a, b, c Beacon) Triangle {
t := Triangle{a: a, b: b, c: c}
t.circumference = findCircumference(a, b, c)
t.area = findArea(a, b, c)
return t
}
type Scanner struct {
number int
beacons []Beacon
prints []Triangle
}
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)
}
}
prints := make([]Triangle, 0, len(s.beacons))
dupes := make(map[Pair]struct{})
for _, b := range s.beacons {
c1, c2 := b.findNearestTwo(s.beacons)
t := NewTriangle(b, c1, c2)
p := Pair{t.area, t.circumference}
if _, ok := dupes[p]; !ok {
prints = append(prints, t)
}
dupes[p] = struct{}{}
}
return s, nil
}
type Beacon struct {
x, y, z int
}
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) Sub(c Beacon) Beacon {
return Beacon{
x: b.x - c.x,
y: b.y - c.y,
z: b.z - c.z,
}
}
func (b Beacon) Negate() Beacon {
return Beacon{
x: -b.x,
y: -b.y,
z: -b.z,
}
}
func (b Beacon) Equals(c Beacon) bool {
return b.x == c.x && b.y == c.y && b.z == c.z
}
func (b Beacon) RotateX90() Beacon {
return Beacon{
x: b.x,
y: -b.z,
z: b.y,
}
}
func (b Beacon) RotateY90() Beacon {
return Beacon{
x: -b.z,
y: b.y,
z: b.x,
}
}
func (b Beacon) RotateZ90() Beacon {
return Beacon{
x: b.y,
y: -b.x,
z: b.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) Rotate(rid int) Beacon {
l := b.AllRotations()
if rid < len(l) {
return l[rid]
}
return b
}
func (b Beacon) Distance(c Beacon) int {
return h.Abs(b.x-c.x) + h.Abs(b.y-c.y) + h.Abs(b.z-c.z)
}
func (b Beacon) findNearestTwo(list []Beacon) (Beacon, Beacon) {
var distances []Pair
for k, v := range list {
if !b.Equals(v) {
distances = append(distances, Pair{a: b.Distance(v), b: k})
}
}
sort.Slice(distances, func(i, j int) bool { return distances[i].a < distances[j].a })
return list[distances[0].b], list[distances[1].b]
}
func findCircumference(a, b, c Beacon) int {
return a.Distance(b) + b.Distance(c) + c.Distance(a)
}
func findArea(a, b, c Beacon) int {
wrk := crossProduct(b.Sub(a), c.Sub(a))
return h.Abs(wrk.x) + h.Abs(wrk.y) + h.Abs(wrk.z)
}
func crossProduct(a, b Beacon) Beacon {
return Beacon{
x: a.y*b.z - a.z*b.y,
y: a.z*b.x - a.x*b.z,
z: a.x*b.y - a.y*b.x,
}
}