Day 15
This commit is contained in:
229
day15/common/beacon.go
Normal file
229
day15/common/beacon.go
Normal file
@@ -0,0 +1,229 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
||||
type Tile byte
|
||||
|
||||
const (
|
||||
Sensor Tile = iota
|
||||
Beacon
|
||||
Covered
|
||||
Free
|
||||
)
|
||||
|
||||
|
||||
type Map struct {
|
||||
sensors []SensorPosition
|
||||
minX int
|
||||
maxX int
|
||||
minY int
|
||||
maxY int
|
||||
}
|
||||
|
||||
func NewMap() *Map {
|
||||
tileMap := Map{}
|
||||
tileMap.sensors = []SensorPosition{}
|
||||
tileMap.minX = 0
|
||||
tileMap.maxX = 0
|
||||
tileMap.minY = 0
|
||||
tileMap.maxY = 0
|
||||
return &tileMap
|
||||
}
|
||||
|
||||
func (tileMap *Map) GetTile(x, y int) Tile {
|
||||
for _, sensor := range tileMap.sensors {
|
||||
if sensor.x == x && sensor.y == y {
|
||||
return Sensor
|
||||
} else if sensor.xBeacon == x && sensor.yBeacon == y {
|
||||
return Beacon
|
||||
}
|
||||
}
|
||||
|
||||
for _, sensor := range tileMap.sensors {
|
||||
coverageX := sensor.x - sensor.xBeacon
|
||||
if coverageX < 0 {
|
||||
coverageX *= -1
|
||||
}
|
||||
coverageY := sensor.y - sensor.yBeacon
|
||||
if coverageY < 0 {
|
||||
coverageY *= -1
|
||||
}
|
||||
coverage := coverageX + coverageY
|
||||
|
||||
distanceX := sensor.x - x
|
||||
if distanceX < 0 {
|
||||
distanceX *= -1
|
||||
}
|
||||
distanceY := sensor.y - y
|
||||
if distanceY < 0 {
|
||||
distanceY *= -1
|
||||
}
|
||||
distance := distanceX + distanceY
|
||||
|
||||
if distance <= coverage {
|
||||
return Covered
|
||||
}
|
||||
}
|
||||
|
||||
return Free
|
||||
}
|
||||
|
||||
func (tileMap *Map) SetSensor(sensor SensorPosition) {
|
||||
tileMap.sensors = append(tileMap.sensors, sensor)
|
||||
|
||||
coverageX := sensor.x - sensor.xBeacon
|
||||
if coverageX < 0 {
|
||||
coverageX *= -1
|
||||
}
|
||||
coverageY := sensor.y - sensor.yBeacon
|
||||
if coverageY < 0 {
|
||||
coverageY *= -1
|
||||
}
|
||||
coverage := coverageX + coverageY
|
||||
|
||||
if sensor.x - coverage < tileMap.minX {
|
||||
tileMap.minX = sensor.x - coverage
|
||||
}
|
||||
if sensor.x + coverage > tileMap.maxX {
|
||||
tileMap.maxX = sensor.x + coverage
|
||||
}
|
||||
if sensor.y - coverage < tileMap.minY {
|
||||
tileMap.minY = sensor.y - coverage
|
||||
}
|
||||
if sensor.y + coverage > tileMap.maxY {
|
||||
tileMap.maxY = sensor.y + coverage
|
||||
}
|
||||
}
|
||||
|
||||
func (tileMap *Map) GetCoverageY(y int) int {
|
||||
return tileMap.GetCoverageYInXInterval(tileMap.minX, tileMap.maxX, y)
|
||||
}
|
||||
|
||||
func (tileMap *Map) GetCoverageYInXInterval(xMin, xMax, y int) int {
|
||||
coverages := []struct{min int; max int}{}
|
||||
nCovered := 0
|
||||
foundBeacons := make(map[int]struct{})
|
||||
|
||||
for _, sensor := range tileMap.sensors {
|
||||
if _, ok := foundBeacons[sensor.xBeacon]; !ok && sensor.yBeacon == y && sensor.xBeacon >= xMin && sensor.xBeacon <= xMax {
|
||||
foundBeacons[sensor.xBeacon] = struct{}{}
|
||||
nCovered--
|
||||
}
|
||||
|
||||
coverageX := sensor.x - sensor.xBeacon
|
||||
if coverageX < 0 {
|
||||
coverageX *= -1
|
||||
}
|
||||
coverageY := sensor.y - sensor.yBeacon
|
||||
if coverageY < 0 {
|
||||
coverageY *= -1
|
||||
}
|
||||
coverage := coverageX + coverageY
|
||||
|
||||
if y >= sensor.y - coverage && y <= sensor.y + coverage {
|
||||
distanceY := sensor.y - y
|
||||
if distanceY < 0 {
|
||||
distanceY *= -1
|
||||
}
|
||||
|
||||
distanceX := coverage - distanceY
|
||||
coverageXMin := sensor.x - distanceX
|
||||
if coverageXMin < xMin {
|
||||
coverageXMin = xMin
|
||||
}
|
||||
coverageXMax := sensor.x + distanceX
|
||||
if coverageXMax > xMax {
|
||||
coverageXMax = xMax
|
||||
}
|
||||
|
||||
coverages = append(coverages, struct{min int; max int}{coverageXMin, coverageXMax})
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < len(coverages); i++ {
|
||||
for j := 0; j < len(coverages); j++ {
|
||||
if j != i {
|
||||
found := false
|
||||
if coverages[j].min >= coverages[i].min && coverages[j].min <= coverages[i].max && coverages[j].max >= coverages[i].max {
|
||||
coverages[i].max = coverages[j].max
|
||||
found = true
|
||||
} else if coverages[j].min <= coverages[i].min && coverages[j].max >= coverages[i].min && coverages[j].max <= coverages[i].max {
|
||||
coverages[i].min = coverages[j].min
|
||||
found = true
|
||||
} else if coverages[j].min < coverages[i].min && coverages[j].max > coverages[i].max {
|
||||
coverages[i].min = coverages[j].min
|
||||
coverages[i].max = coverages[j].max
|
||||
found = true
|
||||
} else if coverages[j].min >= coverages[i].min && coverages[j].max <= coverages[i].max {
|
||||
found = true
|
||||
}
|
||||
if found {
|
||||
if j == 0 {
|
||||
coverages = coverages[1:]
|
||||
} else if j == len(coverages) - 1 {
|
||||
coverages = coverages[:len(coverages)-1]
|
||||
} else {
|
||||
coverages = append(coverages[0:j], coverages[j+1:]...)
|
||||
}
|
||||
j = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, coverage := range(coverages) {
|
||||
nCovered += coverage.max - coverage.min + 1
|
||||
}
|
||||
|
||||
return nCovered
|
||||
}
|
||||
|
||||
func (tileMap *Map) Print(xMin, xMax, yMin, yMax int) {
|
||||
for i := yMin; i <= yMax; i++ {
|
||||
for j := xMin; j <= xMax; j++ {
|
||||
switch tileMap.GetTile(j, i) {
|
||||
case Beacon:
|
||||
fmt.Print("B")
|
||||
case Sensor:
|
||||
fmt.Print("S")
|
||||
case Covered:
|
||||
fmt.Print("#")
|
||||
case Free:
|
||||
fmt.Print(".")
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type SensorPosition struct {
|
||||
x int
|
||||
y int
|
||||
xBeacon int
|
||||
yBeacon int
|
||||
}
|
||||
|
||||
|
||||
func Parse(scanner bufio.Scanner) []SensorPosition {
|
||||
sensors := []SensorPosition{}
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
splittedLine := strings.Split(line, " ")
|
||||
x, _ := strconv.Atoi(splittedLine[2][2:len(splittedLine[2])-1])
|
||||
y, _ := strconv.Atoi(splittedLine[3][2:len(splittedLine[3])-1])
|
||||
xBeacon, _ := strconv.Atoi(splittedLine[8][2:len(splittedLine[8])-1])
|
||||
yBeacon, _ := strconv.Atoi(splittedLine[9][2:])
|
||||
|
||||
sensors = append(sensors, SensorPosition{x, y, xBeacon, yBeacon})
|
||||
}
|
||||
|
||||
return sensors
|
||||
}
|
||||
19
day15/ex1/main.go
Normal file
19
day15/ex1/main.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"aoc2022/day15/common"
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sensors := common.Parse(*bufio.NewScanner(os.Stdin))
|
||||
tileMap := common.NewMap()
|
||||
|
||||
for _, sensor := range sensors {
|
||||
tileMap.SetSensor(sensor)
|
||||
}
|
||||
|
||||
fmt.Println(tileMap.GetCoverageY(2000000))
|
||||
}
|
||||
33
day15/ex2/main.go
Normal file
33
day15/ex2/main.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"aoc2022/day15/common"
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sensors := common.Parse(*bufio.NewScanner(os.Stdin))
|
||||
tileMap := common.NewMap()
|
||||
|
||||
for _, sensor := range sensors {
|
||||
tileMap.SetSensor(sensor)
|
||||
}
|
||||
|
||||
var frequency int
|
||||
found := false
|
||||
for i := 0; i <= 4000000 && !found; i++ {
|
||||
coverage := tileMap.GetCoverageYInXInterval(0, 4000000, i)
|
||||
if coverage <= 4000000 {
|
||||
for j := 0; j < 4000000 && !found; j++ {
|
||||
if tileMap.GetTile(j, i) == common.Free {
|
||||
frequency = j * 4000000 + i
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(frequency)
|
||||
}
|
||||
Reference in New Issue
Block a user