169 lines
4.1 KiB
Go
169 lines
4.1 KiB
Go
package day08
|
|
|
|
import (
|
|
"adventofcode2024/utils/grid2d"
|
|
"adventofcode2024/utils/inputs"
|
|
"fmt"
|
|
)
|
|
|
|
type loc struct {
|
|
x int
|
|
y int
|
|
}
|
|
|
|
type pt struct {
|
|
display rune
|
|
antinodes int
|
|
paired map[loc]pt
|
|
visited map[rune]bool
|
|
}
|
|
|
|
func Part1(input string) int {
|
|
grid := inputs.ToGrid2D(input, "\n", "", pt{display: '.'}, func(c string) pt { return pt{display: rune(c[0]), paired: make(map[loc]pt), visited: make(map[rune]bool)} })
|
|
for x1 := 0; x1 < grid.SizeX(); x1++ {
|
|
for y1 := 0; y1 < grid.SizeY(); y1++ {
|
|
pt1 := grid.Get(x1, y1)
|
|
if pt1.display != '.' {
|
|
for x2 := 0; x2 < grid.SizeX(); x2++ {
|
|
for y2 := 0; y2 < grid.SizeY(); y2++ {
|
|
pt2 := grid.Get(x2, y2)
|
|
if x1 != x2 && y1 != y2 && pt1.display == pt2.display && !isPaired(x1, y1, pt1, pt2) {
|
|
pt1.paired[loc{x: x2, y: y2}] = pt2
|
|
pt2.paired[loc{x: x1, y: y1}] = pt1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for x := 0; x < grid.SizeX(); x++ {
|
|
for y := 0; y < grid.SizeY(); y++ {
|
|
pt1 := grid.Get(x, y)
|
|
if pt1.display != '.' {
|
|
for ploc := range pt1.paired {
|
|
addAntiNodes(x, y, ploc.x, ploc.y, grid)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
antinodes := 0
|
|
for x := 0; x < grid.SizeX(); x++ {
|
|
for y := 0; y < grid.SizeY(); y++ {
|
|
pt := grid.Get(x, y)
|
|
if pt.antinodes > 0 {
|
|
antinodes++
|
|
}
|
|
}
|
|
}
|
|
return antinodes
|
|
}
|
|
|
|
func Part2(input string) int {
|
|
grid := inputs.ToGrid2D(input, "\n", "", pt{display: '.'}, func(c string) pt { return pt{display: rune(c[0]), paired: make(map[loc]pt), visited: make(map[rune]bool)}})
|
|
for x1 := 0; x1 < grid.SizeX(); x1++ {
|
|
for y1 := 0; y1 < grid.SizeY(); y1++ {
|
|
pt1 := grid.Get(x1, y1)
|
|
if pt1.display != '.' {
|
|
for x2 := 0; x2 < grid.SizeX(); x2++ {
|
|
for y2 := 0; y2 < grid.SizeY(); y2++ {
|
|
pt2 := grid.Get(x2, y2)
|
|
if x1 != x2 && y1 != y2 && pt1.display == pt2.display && !isPaired(x1, y1, pt1, pt2) {
|
|
pt1.paired[loc{x: x2, y: y2}] = pt2
|
|
pt2.paired[loc{x: x1, y: y1}] = pt1
|
|
pt1.antinodes++
|
|
pt2.antinodes++
|
|
grid.Set(x1, y1, pt1)
|
|
grid.Set(x2, y2, pt2)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for x := 0; x < grid.SizeX(); x++ {
|
|
for y := 0; y < grid.SizeY(); y++ {
|
|
pt1 := grid.Get(x, y)
|
|
if pt1.display != '.' {
|
|
for ploc := range pt1.paired {
|
|
addAntiNodes_p2(pt1.display, x, y, ploc.x, ploc.y, grid)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
antinodes := 0
|
|
fmt.Printf("%v\n", grid.StringWithFormatter(formatter))
|
|
for x := 0; x < grid.SizeX(); x++ {
|
|
for y := 0; y < grid.SizeY(); y++ {
|
|
pt := grid.Get(x, y)
|
|
if pt.antinodes > 0 {
|
|
antinodes++
|
|
} else {
|
|
if pt.display != '.' { antinodes++ }
|
|
}
|
|
}
|
|
}
|
|
return antinodes
|
|
}
|
|
|
|
func formatter(p pt, x int, y int) string {
|
|
if p.antinodes > 0 {
|
|
return "#"
|
|
}
|
|
return "."
|
|
}
|
|
|
|
func isPaired(x int, y int, p1 pt, pt2 pt) bool {
|
|
return p1.paired[loc{x: x, y: y}].display == pt2.display
|
|
}
|
|
|
|
func addAntiNodes(x1 int, y1 int, x2 int, y2 int, grid *grid2d.Grid[pt]) {
|
|
px1, py1, px2, py2 := offsetPoints(x1, y1, x2, y2)
|
|
|
|
if px1 < 0 || px1 >= grid.SizeX() || py1 < 0 || py1 >= grid.SizeY() {
|
|
return
|
|
}
|
|
pt1 := grid.Get(px1, py1)
|
|
pt1.antinodes++
|
|
grid.Set(px1, py1, pt1)
|
|
if px2 < 0 || px2 >= grid.SizeX() || py2 < 0 || py2 >= grid.SizeY() {
|
|
return
|
|
}
|
|
pt2 := grid.Get(px2, py2)
|
|
pt2.antinodes++
|
|
grid.Set(px2, py2, pt2)
|
|
}
|
|
|
|
func addAntiNodes_p2(frequency rune, x1 int, y1 int, x2 int, y2 int, grid *grid2d.Grid[pt]) {
|
|
px1, py1, px2, py2 := offsetPoints(x1, y1, x2, y2)
|
|
if !(px1 < 0 || px1 >= grid.SizeX() || py1 < 0 || py1 >= grid.SizeY()) {
|
|
pt1 := grid.Get(px1, py1)
|
|
if !pt1.visited[frequency] {
|
|
pt1.antinodes++
|
|
pt1.visited[frequency] = true
|
|
grid.Set(px1, py1, pt1)
|
|
addAntiNodes_p2(frequency, x1, y1, px1, py1, grid)
|
|
}
|
|
}
|
|
if !(px2 < 0 || px2 >= grid.SizeX() || py2 < 0 || py2 >= grid.SizeY()) {
|
|
pt2 := grid.Get(px2, py2)
|
|
if !pt2.visited[frequency] {
|
|
pt2.antinodes++
|
|
pt2.visited[frequency] = true
|
|
grid.Set(px2, py2, pt2)
|
|
addAntiNodes_p2(frequency, x2, y2, px2, py2, grid)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Function to calculate two points symmetrically placed above and below the line
|
|
func offsetPoints(x1, y1, x2, y2 int) (int, int, int, int) {
|
|
dx := x1 - x2
|
|
dy := y1 - y2
|
|
|
|
p1x := x1 + dx
|
|
p1y := y1 + dy
|
|
p2x := x2 - dx
|
|
p2y := y2 - dy
|
|
return p1x, p1y, p2x, p2y
|
|
}
|