package main import ( "fmt" "os" "regexp" "strings" ) func check(e error) { if e != nil { panic(e) } } func rune_matrix(text string) [][]rune { lines := strings.Split(text, "\n") matrix := make([][]rune, len(lines)) for i := range matrix { matrix[i] = make([]rune, 0, len(lines[0])) } for i, line := range lines { for _, c := range []rune(line) { matrix[i] = append(matrix[i], c) } } return matrix } func rune_matrix_to_string(matrix [][]rune) string { lines := make([]string, 0, len(matrix)) for _, line := range matrix { lines = append(lines, string(line)) } return strings.Join(lines, "\n") } func transpose(text string) string { matrix := rune_matrix(text) matrix_T := make([][]rune, len(matrix[0])) for i := range matrix[0] { matrix_T[i] = make([]rune, len(matrix)) } for i := range matrix { for j := range matrix[0] { matrix_T[j][i] = matrix[i][j] } } return rune_matrix_to_string(matrix_T) } func abs(n int) int { if n < 0 { return -n } return n } func shear(text string, offset int) string { lines := strings.Split(text, "\n") max_len := 0 // add left padding for pad_left := range lines { lines[pad_left] = strings.Repeat(" ", abs(pad_left - offset)) + lines[pad_left] max_len = max(max_len, len(lines[pad_left])) } // make square again by adding right padding var pad_right int for i := range lines { pad_right = max_len - len(lines[i]) lines[i] = lines[i] + strings.Repeat(" ", pad_right) } return strings.Join(lines, "\n") } func main() { dat, err := os.ReadFile("data.txt") check(err) dat_str := string(dat[:len(dat) - 1]) matches := 0 // split so that overlapping ones are also matched r1 := regexp.MustCompile("XMAS") r2 := regexp.MustCompile("SAMX") // horizontal matches += len(r1.FindAllStringIndex(dat_str, -1)) matches += len(r2.FindAllStringIndex(dat_str, -1)) // vertical matches += len(r1.FindAllStringIndex(transpose(dat_str), -1)) matches += len(r2.FindAllStringIndex(transpose(dat_str), -1)) // increasing left padding + transpose (shear) matches += len(r1.FindAllStringIndex(transpose(shear(dat_str, 0)), -1)) matches += len(r2.FindAllStringIndex(transpose(shear(dat_str, 0)), -1)) // decreasing left padding + transpose (shear) r := regexp.MustCompile("\n") offset := r.FindStringIndex(dat_str)[0] - 1 matches += len(r1.FindAllStringIndex(transpose(shear(dat_str, offset)), -1)) matches += len(r2.FindAllStringIndex(transpose(shear(dat_str, offset)), -1)) fmt.Println(matches) }