package main import ( "bufio" "errors" "fmt" "io" "log" "os" ) const MAX_LOOP = 1_000_000 func trim(bs []byte) []byte { last := len(bs) - 1 if last >= 0 && bs[last] == '\n' { return bs[:last] } return bs } func main() { var dim int var rows [][]byte r := bufio.NewReader(os.Stdin) line, err := r.ReadBytes('\n') if err != nil { log.Fatalf("While reading input: %v", err) } line = trim(line) dim = len(line) rows = make([][]byte, dim) rows[0] = line for i := 1; i < dim; i++ { line, err = r.ReadBytes('\n') if errors.Is(err, io.EOF) { break } if err != nil { log.Fatalf("While reading input: %v", err) } rows[i] = trim(line) } diags := dim - 4 + dim - 4 + 1 ctrs := 1 + dim + diags + diags bufs := make([]byte, ctrs*4) offset := 0 horizontal := make([]*Counter, 1) horizontal[0] = new(Counter) horizontal[0].Init(bufs[offset : offset+4]) offset += 4 vertical := make([]*Counter, dim) for i := 0; i < dim; i++ { vertical[i] = new(Counter) vertical[i].Init(bufs[offset : offset+4]) offset += 4 } swDiag := make([]*Counter, diags) for i := 0; i < diags; i++ { swDiag[i] = new(Counter) swDiag[i].Init(bufs[offset : offset+4]) offset += 4 } seDiag := make([]*Counter, diags) for i := 0; i < diags; i++ { seDiag[i] = new(Counter) seDiag[i].Init(bufs[offset : offset+4]) offset += 4 } diagLag := 3 for i := 0; i < dim; i++ { horizontal[0].Reset() for j := 0; j < dim; j++ { e := rows[i][j] horizontal[0].Event(e) vertical[j].Event(e) swIdx := i + j - diagLag if 0 <= swIdx && swIdx < diags { swDiag[swIdx].Event(e) } seIdx := j - i - (diagLag + 1 - dim) if 0 <= seIdx && seIdx < diags { seDiag[seIdx].Event(e) } } } sum := 0 for _, c := range horizontal { sum += c.Count() } for _, c := range vertical { sum += c.Count() } for _, c := range swDiag { sum += c.Count() } for _, c := range seDiag { sum += c.Count() } fmt.Println(sum) } type Counter struct { cnt int buf []byte } func (c *Counter) Init(buf []byte) { c.buf = buf } func (c *Counter) Reset() { c.buf = c.buf[:0] } func (c *Counter) Event(e byte) { switch { case e == 'X' && string(c.buf) == "SAM" || e == 'S' && string(c.buf) == "XMA": c.cnt++ c.Reset() c.buf = append(c.buf, e) case e == 'M' && string(c.buf) == "SA" || e == 'A' && string(c.buf) == "S" || e == 'S' && string(c.buf) == "" || e == 'A' && string(c.buf) == "XM" || e == 'M' && string(c.buf) == "X" || e == 'X' && string(c.buf) == "": c.buf = append(c.buf, e) default: c.Reset() c.buf = append(c.buf, e) } } func (c *Counter) Count() int { return c.cnt }