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