190 lines
4.6 KiB
Go
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
|
|
}
|