118 lines
2.7 KiB
Go
118 lines
2.7 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
|
||
|
"git.mstar.dev/mstar/aoc24/util"
|
||
|
"git.mstar.dev/mstar/goutils/sliceutils"
|
||
|
)
|
||
|
|
||
|
type Coord struct {
|
||
|
X, Y int
|
||
|
C rune
|
||
|
}
|
||
|
|
||
|
// Ugly but works
|
||
|
var allOffsets1 = [][]Coord{
|
||
|
{newCoord(0, 0, 'X'), newCoord(0, 1, 'M'), newCoord(0, 2, 'A'), newCoord(0, 3, 'S')},
|
||
|
{newCoord(0, 0, 'X'), newCoord(0, -1, 'M'), newCoord(0, -2, 'A'), newCoord(0, -3, 'S')},
|
||
|
{newCoord(0, 0, 'X'), newCoord(1, 0, 'M'), newCoord(2, 0, 'A'), newCoord(3, 0, 'S')},
|
||
|
{newCoord(0, 0, 'X'), newCoord(-1, 0, 'M'), newCoord(-2, 0, 'A'), newCoord(-3, 0, 'S')},
|
||
|
{newCoord(0, 0, 'X'), newCoord(1, 1, 'M'), newCoord(2, 2, 'A'), newCoord(3, 3, 'S')},
|
||
|
{newCoord(0, 0, 'X'), newCoord(-1, -1, 'M'), newCoord(-2, -2, 'A'), newCoord(-3, -3, 'S')},
|
||
|
{newCoord(0, 0, 'X'), newCoord(1, -1, 'M'), newCoord(2, -2, 'A'), newCoord(3, -3, 'S')},
|
||
|
{newCoord(0, 0, 'X'), newCoord(-1, 1, 'M'), newCoord(-2, 2, 'A'), newCoord(-3, 3, 'S')},
|
||
|
}
|
||
|
|
||
|
var allOffsets2 = [][]Coord{
|
||
|
{
|
||
|
newCoord(0, 0, 'A'),
|
||
|
newCoord(-1, -1, 'M'),
|
||
|
newCoord(-1, 1, 'M'),
|
||
|
newCoord(1, 1, 'S'),
|
||
|
newCoord(1, -1, 'S'),
|
||
|
},
|
||
|
{
|
||
|
newCoord(0, 0, 'A'),
|
||
|
newCoord(-1, -1, 'S'),
|
||
|
newCoord(-1, 1, 'M'),
|
||
|
newCoord(1, 1, 'M'),
|
||
|
newCoord(1, -1, 'S'),
|
||
|
},
|
||
|
{
|
||
|
newCoord(0, 0, 'A'),
|
||
|
newCoord(-1, -1, 'S'),
|
||
|
newCoord(-1, 1, 'S'),
|
||
|
newCoord(1, 1, 'M'),
|
||
|
newCoord(1, -1, 'M'),
|
||
|
},
|
||
|
{
|
||
|
newCoord(0, 0, 'A'),
|
||
|
newCoord(-1, -1, 'M'),
|
||
|
newCoord(-1, 1, 'S'),
|
||
|
newCoord(1, 1, 'S'),
|
||
|
newCoord(1, -1, 'M'),
|
||
|
},
|
||
|
}
|
||
|
|
||
|
func newCoord(x, y int, C rune) Coord { return Coord{x, y, C} }
|
||
|
|
||
|
func linesToGrid(lines []string) [][]rune {
|
||
|
return sliceutils.Map(lines, func(t string) []rune { return []rune(t) })
|
||
|
}
|
||
|
|
||
|
func safeAccess(grid [][]rune, x, y int) (bool, rune) {
|
||
|
if x < 0 {
|
||
|
return false, ' '
|
||
|
}
|
||
|
if y < 0 {
|
||
|
return false, ' '
|
||
|
}
|
||
|
if x >= len(grid[0]) {
|
||
|
return false, ' '
|
||
|
}
|
||
|
if y >= len(grid) {
|
||
|
return false, ' '
|
||
|
}
|
||
|
return true, grid[y][x]
|
||
|
}
|
||
|
|
||
|
func checkGridWithOffsets(x, y int, grid [][]rune, allOffsets [][]Coord) int {
|
||
|
acc := 0
|
||
|
outer:
|
||
|
for _, offsets := range allOffsets {
|
||
|
for _, offset := range offsets {
|
||
|
ok, r := safeAccess(grid, x+offset.X, y+offset.Y)
|
||
|
if !ok {
|
||
|
continue outer
|
||
|
}
|
||
|
if offset.C != r {
|
||
|
continue outer
|
||
|
}
|
||
|
}
|
||
|
acc++
|
||
|
}
|
||
|
if acc != 0 {
|
||
|
// fmt.Printf("Found %d at %d:%d\n", acc, x, y)
|
||
|
}
|
||
|
return acc
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
grid := linesToGrid(util.FileContentToNonEmptyLines(util.LoadFileFromArgs()))
|
||
|
counter := 0
|
||
|
for iy := range grid {
|
||
|
for ix := range grid[iy] {
|
||
|
counter += checkGridWithOffsets(ix, iy, grid, allOffsets1)
|
||
|
}
|
||
|
}
|
||
|
fmt.Printf("Task 1: %d\n", counter)
|
||
|
counter = 0
|
||
|
for iy := range grid {
|
||
|
for ix := range grid[iy] {
|
||
|
counter += checkGridWithOffsets(ix, iy, grid, allOffsets2)
|
||
|
}
|
||
|
}
|
||
|
fmt.Printf("Task 2: %d\n", counter)
|
||
|
}
|