aoc/2024/day-04/main.go

180 lines
3.6 KiB
Go

package main
import (
"fmt"
"log"
"os"
)
type direction struct {
X int
Y int
}
var (
undef direction = direction{0, 0}
north direction = direction{-1, 0}
north_east direction = direction{-1, 1}
east direction = direction{0, 1}
south_east direction = direction{1, 1}
south direction = direction{1, 0}
south_west direction = direction{1, -1}
west direction = direction{0, -1}
north_west direction = direction{-1, -1}
)
func checkX_MAS(field [][]string, x int, y int) bool {
ne := getChar(field, x+north_east.X, y+north_east.Y)
se := getChar(field, x+south_east.X, y+south_east.Y)
sw := getChar(field, x+south_west.X, y+south_west.Y)
nw := getChar(field, x+north_west.X, y+north_west.Y)
// All allowed options
// M.S
// .A.
// M.S
//
// S.S
// .A.
// M.M
//
// S.M
// .A.
// S.M
//
// M.M
// .A.
// S.S
pattern := fmt.Sprintf("%s%s%s%s", ne, se, sw, nw)
if pattern == "SSMM" || pattern == "SMMS" || pattern == "MMSS" || pattern == "MSSM" {
return true
}
return false
}
func getChar(field [][]string, x, y int) string {
bound_x := len(field)
if x == -1 || x >= bound_x {
return ""
}
bound_y := len(field[x])
if y == -1 || y >= bound_y {
return ""
}
return field[x][y]
}
func main() {
content, err := os.ReadFile("./input.txt")
if err != nil {
log.Fatalf("failed to open file: %s\n", err)
}
var field [][]string
x_axis := 0
y_axis := 0
result2 := 0
for _, b := range content {
char := string(b)
if char == "\n" {
x_axis++
y_axis = 0
continue
}
if y_axis == 0 {
field = append(field, make([]string, 0))
}
field[x_axis] = append(field[x_axis], char)
y_axis++
}
var found [][]pos
for x := 0; x < len(field); x++ {
for y := 0; y < len(field[x]); y++ {
if field[x][y] == "X" {
seq := []pos{}
seq = append(seq, pos{x, y})
checkXMAS(field, x+north.X, y+north.Y, seq, &found, north)
checkXMAS(field, x+north_east.X, y+north_east.Y, seq, &found, north_east)
checkXMAS(field, x+east.X, y+east.Y, seq, &found, east)
checkXMAS(field, x+south_east.X, y+south_east.Y, seq, &found, south_east)
checkXMAS(field, x+south.X, y+south.Y, seq, &found, south)
checkXMAS(field, x+south_west.X, y+south_west.Y, seq, &found, south_west)
checkXMAS(field, x+west.X, y+west.Y, seq, &found, west)
checkXMAS(field, x+north_west.X, y+north_west.Y, seq, &found, north_west)
}
if field[x][y] == "A" {
if checkX_MAS(field, x, y) {
result2++
}
}
}
}
fmt.Println("result part 1: ", len(found))
fmt.Println("result part 2: ", result2)
}
type pos struct {
X int
Y int
}
func seqToString(field [][]string, seq []pos) string {
str := ""
for _, p := range seq {
str += field[p.X][p.Y]
}
return str
}
func checkXMAS(field [][]string, x int, y int, current_seq []pos, found *[][]pos, dir direction) {
char := getChar(field, x, y)
if char == "" {
return
}
seq_str := seqToString(field, current_seq)
if (seq_str == "" && char == "X") ||
(seq_str == "X" && char == "M") ||
(seq_str == "XM" && char == "A") ||
(seq_str == "XMA" && char == "S") {
pos := pos{X: x, Y: y}
current_seq = append(current_seq, pos)
} else {
return
}
if seqToString(field, current_seq) == "XMAS" {
*found = append(*found, current_seq)
}
// nort = -1, 0
// north_east = -1, 1
// east = 0, 1
// south_east = 1, 1
// south = 1, 0
// south_west = 1, -1
// west = 0, -1
// [0, 0] [0, 1] [0, 2] [0, 3]
// [1, 0] [1, 1] [1, 2] [1, 3]
// [2, 0] [2, 1] [2, 2] [2, 3]
// [3, 0] [3, 1] [3, 2] [3, 3]
checkXMAS(field, x+dir.X, y+dir.Y, current_seq, found, dir)
}