204 lines
5.5 KiB
Go
204 lines
5.5 KiB
Go
package main
|
|
|
|
import (
|
|
"AOC2021/src/helper"
|
|
"fmt"
|
|
"math"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
type scanner struct {
|
|
points [][3]int
|
|
position [3]int
|
|
}
|
|
|
|
func main() {
|
|
args := os.Args[1:]
|
|
input, err := helper.GetInput(args[0])
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
var scanners []scanner
|
|
for _, row := range input {
|
|
if row[1] == '-' {
|
|
scanners = append(scanners, scanner{[][3]int{}, [3]int{}})
|
|
} else {
|
|
tmpPoint, _ := helper.MapToNumber(strings.Split(row, ","))
|
|
scanners[len(scanners)-1].points = append(scanners[len(scanners)-1].points, [3]int{tmpPoint[0], tmpPoint[1], tmpPoint[2]})
|
|
}
|
|
}
|
|
hitScanners := []int{0}
|
|
run := true
|
|
for run {
|
|
run = runUntilFirstHit(&scanners, &hitScanners)
|
|
}
|
|
|
|
inputTestResult, _ := helper.GetInput("day19TestResultPoints.txt")
|
|
resultPoints := [][3]int{}
|
|
for _, row := range inputTestResult {
|
|
tmpPoint, _ := helper.MapToNumber(strings.Split(row, ","))
|
|
resultPoints = append(resultPoints, [3]int{tmpPoint[0], tmpPoint[1], tmpPoint[2]})
|
|
}
|
|
|
|
var max float64
|
|
for i, _ := range scanners {
|
|
for j, _ := range scanners {
|
|
if i != j {
|
|
diff := diffBetweenVectors(scanners[i].position, scanners[j].position)
|
|
manhattan := math.Abs(float64(diff[0])) + math.Abs(float64(diff[1])) + math.Abs(float64(diff[2]))
|
|
if manhattan > max {
|
|
max = manhattan
|
|
}
|
|
}
|
|
}
|
|
}
|
|
fmt.Println(len(scanners[0].points))
|
|
fmt.Println(max)
|
|
}
|
|
|
|
func runUntilFirstHit(scanners *[]scanner, hitScanners *[]int) bool {
|
|
for i := 0; i < len(*scanners); i++ {
|
|
if !helper.Contains(i, *hitScanners) && runFor(scanners, 0, i) {
|
|
*hitScanners = append(*hitScanners, i)
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func runFor(scanners *[]scanner, i int, j int) bool {
|
|
returnBool := checkIfScannersHaveMatchingBeacons(scanners, 0, j)
|
|
if returnBool {
|
|
pointSet := make(map[[3]int]struct{})
|
|
for _, point := range (*scanners)[0].points {
|
|
pointSet[point] = struct{}{}
|
|
}
|
|
(*scanners)[0].points = [][3]int{}
|
|
for key, _ := range pointSet {
|
|
(*scanners)[0].points = append((*scanners)[0].points, key)
|
|
}
|
|
}
|
|
return returnBool
|
|
}
|
|
|
|
func checkIfScannersHaveMatchingBeacons(scanners *[]scanner, i int, j int) bool {
|
|
scanner1 := &(*scanners)[i]
|
|
scanner2 := &(*scanners)[j]
|
|
pointMapper := getOverlappingPoints(*scanner1, *scanner2)
|
|
if len(pointMapper) >= 12 {
|
|
rotationsForScanner := getAllPossibleRotationsForScanner(*scanner2)
|
|
i, diff := getRightRotation(scanner1, pointMapper, rotationsForScanner)
|
|
scanner2.position = diff
|
|
var pointsOfScanner2inRelationToScanner1 [][3]int
|
|
for x := 0; x < len(rotationsForScanner); x++ {
|
|
point := rotationsForScanner[x][i]
|
|
pointWithDiff := [3]int{point[0] + diff[0], point[1] + diff[1], point[2] + diff[2]}
|
|
pointsOfScanner2inRelationToScanner1 = append(pointsOfScanner2inRelationToScanner1, pointWithDiff)
|
|
}
|
|
scanner1.points = append(scanner1.points, pointsOfScanner2inRelationToScanner1...)
|
|
return true
|
|
|
|
}
|
|
return false
|
|
}
|
|
|
|
func getRightRotation(scanner1 *scanner, pointMapper [][2]int, rotationsForScanner [][][3]int) (int, [3]int) {
|
|
for i := 0; i < 24; i++ {
|
|
firstDiff := diffBetweenVectors(rotationsForScanner[pointMapper[0][1]][i], scanner1.points[pointMapper[0][0]])
|
|
different := false
|
|
for n := 1; n < len(pointMapper); n++ {
|
|
rotation := rotationsForScanner[pointMapper[n][1]][i]
|
|
diff := diffBetweenVectors(rotation, scanner1.points[pointMapper[n][0]])
|
|
if firstDiff != diff {
|
|
different = true
|
|
}
|
|
}
|
|
if different == false {
|
|
return i, firstDiff
|
|
}
|
|
}
|
|
return -1, [3]int{0, 0, 0}
|
|
}
|
|
|
|
func getOverlappingPoints(sc1 scanner, sc2 scanner) (pointPairs [][2]int) {
|
|
distances0 := getallDistancesBetweenPointsForScanner(sc1)
|
|
distances1 := getallDistancesBetweenPointsForScanner(sc2)
|
|
for i, _ := range distances0 {
|
|
for j, _ := range distances1 {
|
|
if len(helper.OverlapFloatArray(distances0[i], distances1[j])) >= 11 {
|
|
pointPairs = append(pointPairs, [2]int{i, j})
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func turn(point *[3]int) {
|
|
*point = [3]int{-point[1], point[0], point[2]}
|
|
}
|
|
|
|
func roll(point *[3]int) {
|
|
*point = [3]int{point[0], point[2], -point[1]}
|
|
}
|
|
|
|
func getAllPossibleRotationsForPoint(point *[3]int) (points [][3]int) {
|
|
rotationOrder := "RTTTRTTTRTTT"
|
|
switchRotationOrder := "RTR"
|
|
executeRotationOrder(point, rotationOrder, &points)
|
|
executeRotationOrder(point, switchRotationOrder, &[][3]int{})
|
|
executeRotationOrder(point, rotationOrder, &points)
|
|
return
|
|
}
|
|
|
|
func executeRotationOrder(point *[3]int, order string, points *[][3]int) {
|
|
for _, char := range order {
|
|
switch char {
|
|
case 'R':
|
|
roll(point)
|
|
case 'T':
|
|
turn(point)
|
|
}
|
|
*points = append(*points, *point)
|
|
}
|
|
return
|
|
}
|
|
|
|
func getAllPossibleRotationsForScanner(scanner scanner) [][][3]int {
|
|
permutations := [][][3]int{}
|
|
for _, point := range scanner.points {
|
|
permutations = append(permutations, getAllPossibleRotationsForPoint(&point))
|
|
}
|
|
return permutations
|
|
}
|
|
|
|
func getallDistancesBetweenPointsForScanner(scanner scanner) [][]float64 {
|
|
var distances [][]float64
|
|
for i, point1 := range scanner.points {
|
|
var distancesForPoint []float64
|
|
for j, point2 := range scanner.points {
|
|
if i != j {
|
|
distancesForPoint = append(distancesForPoint, distanceBetweenVectors(point1, point2))
|
|
}
|
|
}
|
|
distances = append(distances, distancesForPoint)
|
|
}
|
|
return distances
|
|
}
|
|
|
|
func distanceBetweenVectors(v1 [3]int, v2 [3]int) float64 {
|
|
var diffs [3]float64
|
|
for i, _ := range v1 {
|
|
diffs[i] = float64(v2[i] - v1[i])
|
|
}
|
|
return math.Sqrt(math.Pow(diffs[0], 2) + math.Pow(diffs[1], 2) + math.Pow(diffs[2], 2))
|
|
}
|
|
|
|
func diffBetweenVectors(v1 [3]int, v2 [3]int) [3]int {
|
|
var diff [3]int
|
|
for i, _ := range v1 {
|
|
diff[i] = v2[i] - v1[i]
|
|
}
|
|
return diff
|
|
}
|