2021-12-19 22:09:26 +01:00
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 ] } )
}
}
2021-12-20 02:04:00 +01:00
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 ] } )
}
2021-12-19 22:09:26 +01:00
2021-12-20 02:04:00 +01:00
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 )
2021-12-19 22:09:26 +01:00
}
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 {
2021-12-20 02:04:00 +01:00
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 )
2021-12-19 22:09:26 +01:00
}
}
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 )
2021-12-20 02:04:00 +01:00
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 )
2021-12-19 22:09:26 +01:00
}
2021-12-20 02:04:00 +01:00
scanner1 . points = append ( scanner1 . points , pointsOfScanner2inRelationToScanner1 ... )
return true
2021-12-19 22:09:26 +01:00
}
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
}