@@ -3,153 +3,53 @@ package day4
33import (
44 "slices"
55 "strings"
6- "unicode/utf8"
76)
87
9- const WORD_TO_FIND = "XMAS"
10-
11- var _rows []string
8+ type strategy func ([][]rune , int , int ) bool
129
1310func Solve (input string ) uint {
14- _rows = make ([]string , 0 )
15- return matchesByStrategy (input , rows ) + matchesByStrategy (input , columns ) + matchesByStrategy (input , diagonals )
16- }
17-
18- func matchesByStrategy (input string , strategy func (string ) []string ) uint {
19- var count uint = 0
20- for _ , x := range strategy (input ) {
21- if contains (x ) {
22- count += 1
23- }
24- if contains (reverse (x )) {
25- count += 1
26- }
27- }
28- return count
29- }
30-
31- func contains (input string ) bool {
32- return strings .Contains (input , WORD_TO_FIND )
33- }
34-
35- func rows (input string ) []string {
36- if len (_rows ) == 0 {
37- _rows = strings .Split (input , "\n " )
38- }
39- return _rows
40- }
41-
42- func columns (input string ) []string {
43- rows := rows (input )
44- var cols []string = make ([]string , len (rows ))
45- for _ , r := range rows {
46- for j , v := range r {
47- if j >= len (rows ) {
48- panic ("The input puzzle is not square" )
11+ puzzle := parseInput (input )
12+ ss := []strategy {builder (0 , - 1 ), builder (0 , 1 ), builder (- 1 , 0 ), builder (1 , 0 ), builder (- 1 , - 1 ), builder (1 , - 1 ), builder (- 1 , 1 ), builder (1 , 1 )}
13+ var result uint = 0
14+ for j , line := range puzzle {
15+ for i := range line {
16+ for _ , s := range ss {
17+ if s (puzzle , i , j ) {
18+ result ++
19+ }
4920 }
50- cols [j ] += string (v )
5121 }
5222 }
53- return cols
54- }
55-
56- func diagonals (input string ) []string {
57- rows := rows (input )
58- wordSize := len (WORD_TO_FIND )
59- squareSize := len (rows )
60- var diagonals []string = make ([]string , 0 )
61- seed := squareSize - wordSize
62-
63- for s := 0 ; s <= seed ; s ++ {
64- buf1 := forwardLower (s , squareSize , rows )
65- buf2 := forwardUpper (s , squareSize , rows )
66- buf3 := backLower (s , squareSize , rows )
67- buf4 := backUpper (s , squareSize , rows )
68- diagonals = slices .Insert (diagonals , len (diagonals ), string (buf1 ), string (buf2 ), string (buf3 ), string (buf4 ))
69- }
70-
71- return diagonals
23+ return result
7224}
7325
74- func forwardLower (s int , squareSize int , rows []string ) []byte {
75- buf := make ([]byte , 0 )
76- i := 0
77- j := s
78- for {
79- if ! inPuzzle (i , j , squareSize ) {
80- break
26+ func parseInput (input string ) [][]rune {
27+ result := make ([][]rune , 0 )
28+ for j , line := range strings .Split (input , "\n " ) {
29+ result = slices .Insert (result , j , make ([]rune , 0 ))
30+ for _ , r := range line {
31+ result [j ] = append (result [j ], r )
8132 }
82-
83- buf = slices .Insert (buf , len (buf ), rows [i ][j ])
84- i ++
85- j ++
8633 }
87- return buf
34+ return result
8835}
8936
90- func forwardUpper (s int , squareSize int , rows []string ) []byte {
91- buf := make ([]byte , 0 )
92- if s == 0 {
93- return buf
94- }
95- i := s
96- j := 0
97- for {
98- if ! inPuzzle (i , j , squareSize ) {
99- break
37+ func builder (right , up int ) strategy {
38+ word := [4 ]rune {'X' , 'M' , 'A' , 'S' }
39+ length := len (word )
40+ return func (puzzle [][]rune , x , y int ) bool {
41+ if (up < 0 && y < length - 1 ) || (up > 0 && y > len (puzzle )- length ) {
42+ return false
10043 }
101-
102- buf = slices .Insert (buf , len (buf ), rows [i ][j ])
103- i ++
104- j ++
105- }
106- return buf
107- }
108-
109- func backUpper (s int , squareSize int , rows []string ) []byte {
110- buf := make ([]byte , 0 )
111- i := squareSize - 1 - s
112- j := 0
113- for {
114- if ! inPuzzle (i , j , squareSize ) {
115- break
44+ if (right < 0 && x < length - 1 ) || (right > 0 && x > len (puzzle )- length ) {
45+ return false
11646 }
11747
118- buf = slices .Insert (buf , len (buf ), rows [i ][j ])
119- i --
120- j ++
121- }
122- return buf
123- }
124-
125- func backLower (s int , squareSize int , rows []string ) []byte {
126- buf := make ([]byte , 0 )
127- i := squareSize - 1
128- j := s
129- for {
130- if ! inPuzzle (i , j , squareSize ) {
131- break
48+ for i , r := range word {
49+ if puzzle [y + (i * up )][x + (i * right )] != r {
50+ return false
51+ }
13252 }
133-
134- buf = slices .Insert (buf , len (buf ), rows [i ][j ])
135- i --
136- j ++
137- }
138- return buf
139- }
140-
141- // @see {https://stackoverflow.com/a/34521190}
142- func reverse (s string ) string {
143- size := len (s )
144- buf := make ([]byte , size )
145- for start := 0 ; start < size ; {
146- r , n := utf8 .DecodeRuneInString (s [start :])
147- start += n
148- utf8 .EncodeRune (buf [size - start :], r )
53+ return true
14954 }
150- return string (buf )
151- }
152-
153- func inPuzzle (i , j int , squareSize int ) bool {
154- return i >= 0 && i < squareSize && j >= 0 && j < squareSize
15555}
0 commit comments