advent-of-code/aoc2024/day04/main.go

163 lines
2.4 KiB
Go
Raw Normal View History

2024-12-06 11:28:30 -07:00
package main
import (
"bufio"
_ "embed"
"fmt"
aoc "go.sour.is/advent-of-code"
)
// var log = aoc.Log
func main() { aoc.MustResult(aoc.Runner(run)) }
type result struct {
valuePT1 int
valuePT2 int
}
type record struct {
p aoc.Point[int]
d [2]int
}
func (r result) String() string { return fmt.Sprintf("%#v", r) }
func run(scan *bufio.Scanner) (*result, error) {
m := make([][]rune, 0, 1000)
var records []record
var records2 []record
for scan.Scan() {
txt := scan.Text()
m = append(m, []rune(txt))
}
for x, row := range m {
for y, c := range row {
if c == 'X' {
rs := search1(record{
p: aoc.Point[int]{x, y},
}, m)
records = append(records, rs...)
}
if c == 'A' {
rs := search2(record{
p: aoc.Point[int]{x, y},
}, m)
if len(rs) == 2 {
records2 = append(records2, rs...)
}
}
}
}
for _, r := range records2 {
fmt.Println(r)
}
return &result{len(records), len(records2)/2}, nil
}
func search1(r record, m [][]rune) []record {
var ds = [][2]int{
{1, 0}, // up
{0, 1}, // right
{-1, 0}, // down
{0, -1}, // left
{1, 1}, // up-right
{1, -1}, // up-left
{-1, 1}, // down-right
{-1, -1}, // down-left
}
var records []record
for _, d := range ds {
p := r.p
if !check1(m, p, d) {
continue
}
records = append(records, record{
p: p,
d: d,
})
}
return records
}
func check1(m [][]rune, p aoc.Point[int], d [2]int) bool {
for _, r := range []rune{'M', 'A', 'S'} {
p[0] += d[0]
p[1] += d[1]
if p[0] < 0 || p[0] >= len(m) {
return false
}
if p[1] < 0 || p[1] >= len(m[0]) {
return false
}
if m[p[0]][p[1]] != r {
return false
}
}
return true
}
func search2(r record, m [][]rune) []record {
var ds = [][2]int{
{1, 1}, // up-right
{1, -1}, // up-left
{-1, 1}, // down-right
{-1, -1}, // down-left
}
var records []record
for _, d := range ds {
p := r.p
if !check2(m, p, d) {
continue
}
records = append(records, record{
p: p,
d: d,
})
}
return records
}
func check2(m [][]rune, p aoc.Point[int], d [2]int) bool {
p0 := p[0] - d[0]
p1 := p[1] - d[1]
if p0 < 0 || p0 >= len(m) {
return false
}
if p1 < 0 || p1 >= len(m[0]) {
return false
}
if m[p0][p1] != 'M' {
return false
}
p0 = p[0] + d[0]
p1 = p[1] + d[1]
if p0 < 0 || p0 >= len(m) {
return false
}
if p1 < 0 || p1 >= len(m[0]) {
return false
}
if m[p0][p1] != 'S' {
return false
}
return true
}