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 }