129 lines
4.2 KiB
Go
129 lines
4.2 KiB
Go
package main
|
|
|
|
import (
|
|
"AOC2022/helper"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
func main() {
|
|
args := os.Args[1:]
|
|
lines := helper.ReadTextFile(args[0])
|
|
points := getPoints(lines)
|
|
//scannedXPoints := make(map[int]bool)
|
|
scannedPoints := getScannedPointsForTagetY(points, [2]int{2000000, 2000000}, [2]int{-100000000, 100000000})
|
|
fmt.Println(len(scannedPoints) - 1)
|
|
part2(points)
|
|
}
|
|
|
|
// Fichtes Solution
|
|
func part2(points [][2][2]int) {
|
|
scannerWithDistances := [][3]int{}
|
|
for _, scannedPoint := range points {
|
|
distance := helper.ManHattanDistance(scannedPoint[0], scannedPoint[1])
|
|
scannerWithDistances = append(scannerWithDistances, [3]int{scannedPoint[0][0], scannedPoint[0][1], distance})
|
|
}
|
|
startPoint := [2]int{0, 0}
|
|
finish := false
|
|
for !finish {
|
|
scanner := checkIfPointIsInScannerReach(startPoint, scannerWithDistances)
|
|
if scanner[2] == -1 {
|
|
finish = true
|
|
} else {
|
|
distanceToTargetY := helper.Abs(scanner[1] - startPoint[1])
|
|
widthOnTargetY := helper.Abs(distanceToTargetY - scanner[2])
|
|
newXValue := scanner[0] + widthOnTargetY + 1
|
|
if newXValue > 4000000 {
|
|
startPoint = [2]int{0, startPoint[1] + 1}
|
|
} else {
|
|
startPoint[0] = newXValue
|
|
}
|
|
}
|
|
}
|
|
fmt.Println(startPoint[0]*4000000 + startPoint[1])
|
|
}
|
|
|
|
func checkIfPointIsInScannerReach(point [2]int, scanners [][3]int) [3]int {
|
|
for _, scannerWithDistance := range scanners {
|
|
if helper.ManHattanDistance(point, [2]int{scannerWithDistance[0], scannerWithDistance[1]}) <= scannerWithDistance[2] {
|
|
return scannerWithDistance
|
|
}
|
|
}
|
|
return [3]int{0, 0, -1}
|
|
}
|
|
|
|
func getScannedPointsForTagetY(points [][2][2]int, targetyRange [2]int, targetxRange [2]int) map[[2]int]bool {
|
|
scannedYPoints := make(map[[2]int]bool)
|
|
for _, pointPair := range points {
|
|
sensor := pointPair[0]
|
|
beacon := pointPair[1]
|
|
distanceToSensor := helper.ManHattanDistance(sensor, beacon)
|
|
distanceToTargetYLowest := helper.Abs(sensor[1] - targetyRange[0])
|
|
distanceToTargetYHighest := helper.Abs(sensor[1] - targetyRange[1])
|
|
if sensor[1] >= targetyRange[1] && distanceToSensor >= distanceToTargetYHighest {
|
|
i := targetyRange[1]
|
|
for i >= targetyRange[1]-(distanceToSensor-distanceToTargetYHighest) && i >= targetyRange[0] {
|
|
setPointsForTargetY(distanceToSensor, i, targetxRange, sensor, &scannedYPoints)
|
|
i--
|
|
}
|
|
}
|
|
if sensor[1] <= targetyRange[0] && distanceToSensor >= distanceToTargetYLowest {
|
|
i := targetyRange[0]
|
|
for i <= targetyRange[0]+(distanceToSensor-distanceToTargetYLowest) && i <= targetyRange[1] {
|
|
setPointsForTargetY(distanceToSensor, i, targetxRange, sensor, &scannedYPoints)
|
|
i++
|
|
}
|
|
}
|
|
if sensor[1] >= targetyRange[0] && sensor[1] <= targetyRange[1] {
|
|
i := sensor[1]
|
|
for i <= targetyRange[1] && i <= sensor[1]+distanceToSensor {
|
|
setPointsForTargetY(distanceToSensor, i, targetxRange, sensor, &scannedYPoints)
|
|
i++
|
|
}
|
|
i = sensor[1]
|
|
for i >= targetyRange[0] && i >= sensor[1]-distanceToSensor {
|
|
setPointsForTargetY(distanceToSensor, i, targetxRange, sensor, &scannedYPoints)
|
|
i--
|
|
}
|
|
}
|
|
}
|
|
return scannedYPoints
|
|
}
|
|
|
|
func setPointsForTargetY(distanceToSensor, targetY int, targetxRange, sensor [2]int, scannedYPoints *map[[2]int]bool) {
|
|
distanceToTargetY := helper.Abs(sensor[1] - targetY)
|
|
widthOnTargetY := helper.Abs(distanceToTargetY - distanceToSensor)
|
|
i := sensor[0] - widthOnTargetY
|
|
if i < targetxRange[0] {
|
|
i = targetxRange[0]
|
|
}
|
|
for i <= sensor[0]+widthOnTargetY && i <= targetxRange[1] {
|
|
(*scannedYPoints)[[2]int{i, targetY}] = true
|
|
i++
|
|
}
|
|
}
|
|
|
|
func getPoints(lines []string) [][2][2]int {
|
|
points := make([][2][2]int, len(lines))
|
|
for i, line := range lines {
|
|
intPair := [2][2]int{}
|
|
stringParts := strings.Split(line[12:], ":")
|
|
sensorStringNumbers := stringSliceToIntSlice(strings.Split(stringParts[0], ", y="))
|
|
beaconStringNumbers := stringSliceToIntSlice(strings.Split(strings.ReplaceAll(stringParts[1], " closest beacon is at x=", ""), ", y="))
|
|
intPair[0] = [2]int{sensorStringNumbers[0], sensorStringNumbers[1]}
|
|
intPair[1] = [2]int{beaconStringNumbers[0], beaconStringNumbers[1]}
|
|
points[i] = intPair
|
|
}
|
|
return points
|
|
}
|
|
|
|
func stringSliceToIntSlice(input []string) []int {
|
|
intSlice := []int{}
|
|
for _, str := range input {
|
|
intSlice = append(intSlice, helper.RemoveError(strconv.Atoi(str)))
|
|
}
|
|
return intSlice
|
|
}
|