aoc2024/internal/day04/handler.go
2024-12-04 18:23:27 +01:00

190 lines
4.6 KiB
Go

package day04
import (
"errors"
)
var ErrNotEnoughSpace = errors.New("not enough space to form word")
func Handle(input []string) (int, int) {
xmas := 0
crossMAS := 0
for i, line := range input {
for j, char := range line {
if char == 'X' {
xmas += countWord(input, "XMAS", i, j)
}
if char == 'A' {
crossMAS += countCrossPattern(input, "MAS", i, j)
}
}
}
return xmas, crossMAS
}
func countWord(matrix []string, word string, posY, posX int) int {
wordCount := 0
wordLenght := len(word)
result, err := getWordHoz(matrix, wordLenght, posY, posX)
if err == nil && result == word {
wordCount++
}
result, err = getWordHozRev(matrix, wordLenght, posY, posX)
if err == nil && result == word {
wordCount++
}
result, err = getWordVert(matrix, wordLenght, posY, posX)
if err == nil && result == word {
wordCount++
}
result, err = getWordVertRev(matrix, wordLenght, posY, posX)
if err == nil && result == word {
wordCount++
}
result, err = getWordDiagAsc(matrix, wordLenght, posY, posX)
if err == nil && result == word {
wordCount++
}
result, err = getWordDiagAscRev(matrix, wordLenght, posY, posX)
if err == nil && result == word {
wordCount++
}
result, err = getWordDiagDesc(matrix, wordLenght, posY, posX)
if err == nil && result == word {
wordCount++
}
result, err = getWordDiagDescRev(matrix, wordLenght, posY, posX)
if err == nil && result == word {
wordCount++
}
return wordCount
}
func countCrossPattern(matrix []string, word string, posY, posX int) int {
wordCount := 0
wordLenght := len(word)
result, err := getWordDiagAsc(matrix, wordLenght, posY-1, posX-1)
if err == nil && result == word {
wordCount++
}
result, err = getWordDiagAscRev(matrix, wordLenght, posY-1, posX+1)
if err == nil && result == word {
wordCount++
}
result, err = getWordDiagDesc(matrix, wordLenght, posY+1, posX-1)
if err == nil && result == word {
wordCount++
}
result, err = getWordDiagDescRev(matrix, wordLenght, posY+1, posX+1)
if err == nil && result == word {
wordCount++
}
if wordCount == 2 {
return 1
}
return 0
}
func reverseString(str string) string {
runes := []rune(str)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
func getWordHoz(matrix []string, wordLenght, posY, posX int) (string, error) {
if posX > len(matrix[posY])-wordLenght {
return "", ErrNotEnoughSpace
}
if posX > len(matrix[posY])-wordLenght-1 {
return string(matrix[posY][posX:]), nil
}
return string(matrix[posY][posX : posX+wordLenght]), nil
}
func getWordHozRev(matrix []string, wordLenght, posY, posX int) (string, error) {
if posX < wordLenght-1 {
return "", ErrNotEnoughSpace
}
if posX < wordLenght {
word := matrix[posY][0:wordLenght]
return reverseString(word), nil
}
return reverseString(matrix[posY][posX-wordLenght+1 : posX+1]), nil
}
func getWordVert(matrix []string, wordLenght, posY, posX int) (string, error) {
if posY > len(matrix)-wordLenght {
return "", ErrNotEnoughSpace
}
word := make([]byte, wordLenght)
for i := 0; i < wordLenght; i++ {
word[i] = matrix[posY+i][posX]
}
return string(word), nil
}
func getWordVertRev(matrix []string, wordLenght, posY, posX int) (string, error) {
if posY < wordLenght-1 {
return "", ErrNotEnoughSpace
}
word := make([]byte, wordLenght)
for i := 0; i < wordLenght; i++ {
word[i] = matrix[posY-i][posX]
}
return string(word), nil
}
func getWordDiagAsc(matrix []string, wordLenght, posY, posX int) (string, error) {
if posY > len(matrix)-wordLenght || posX > len(matrix[posY])-wordLenght {
return "", ErrNotEnoughSpace
}
word := make([]byte, wordLenght)
for i := 0; i < wordLenght; i++ {
word[i] = matrix[posY+i][posX+i]
}
return string(word), nil
}
func getWordDiagAscRev(matrix []string, wordLenght, posY, posX int) (string, error) {
if posY > len(matrix)-wordLenght || posX < wordLenght-1 {
return "", ErrNotEnoughSpace
}
word := make([]byte, wordLenght)
for i := 0; i < wordLenght; i++ {
word[i] = matrix[posY+i][posX-i]
}
return string(word), nil
}
func getWordDiagDesc(matrix []string, wordLenght, posY, posX int) (string, error) {
if posY < wordLenght-1 || posX > len(matrix[posY])-wordLenght {
return "", ErrNotEnoughSpace
}
word := make([]byte, wordLenght)
for i := 0; i < wordLenght; i++ {
word[i] = matrix[posY-i][posX+i]
}
return string(word), nil
}
func getWordDiagDescRev(matrix []string, wordLenght, posY, posX int) (string, error) {
if posY < wordLenght-1 || posX < wordLenght-1 {
return "", ErrNotEnoughSpace
}
word := make([]byte, wordLenght)
for i := 0; i < wordLenght; i++ {
word[i] = matrix[posY-i][posX-i]
}
return string(word), nil
}