136 lines
3.6 KiB
Go
136 lines
3.6 KiB
Go
|
|
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])
|
||
|
|
|
||
|
|
// split so that overlapping ones are also matched
|
||
|
|
r1 := regexp.MustCompile("MAS")
|
||
|
|
r2 := regexp.MustCompile("SAM")
|
||
|
|
|
||
|
|
r_nl := regexp.MustCompile("\n")
|
||
|
|
offset := r_nl.FindStringIndex(dat_str)[0] - 1
|
||
|
|
|
||
|
|
r_dot := regexp.MustCompile("\\.")
|
||
|
|
|
||
|
|
// increasing left padding + transpose (shear)
|
||
|
|
a_replaced_i1 := r1.ReplaceAllString(transpose(shear(dat_str, 0)), "M.S")
|
||
|
|
a_replaced_i2 := r2.ReplaceAllString(transpose(shear(dat_str, 0)), "S.M")
|
||
|
|
a_replaced_i1 = shear(transpose(a_replaced_i1), offset)
|
||
|
|
a_replaced_i2 = shear(transpose(a_replaced_i2), offset)
|
||
|
|
//fmt.Println(a_replaced_i1, "\n")
|
||
|
|
//fmt.Println(r_dot.FindAllStringIndex(a_replaced_i1, -1), "\n")
|
||
|
|
//fmt.Println(a_replaced_i2, "\n")
|
||
|
|
//fmt.Println(r_dot.FindAllStringIndex(a_replaced_i2, -1), "\n")
|
||
|
|
dot_indices_i := r_dot.FindAllStringIndex(a_replaced_i1, -1)
|
||
|
|
dot_indices_i = append(dot_indices_i, r_dot.FindAllStringIndex(a_replaced_i2, -1)...)
|
||
|
|
//fmt.Println(dot_indices_i)
|
||
|
|
|
||
|
|
// decreasing left padding + transpose (shear)
|
||
|
|
a_replaced_d1 := r1.ReplaceAllString(transpose(shear(dat_str, offset)), "M.S")
|
||
|
|
a_replaced_d2 := r2.ReplaceAllString(transpose(shear(dat_str, offset)), "S.M")
|
||
|
|
a_replaced_d1 = shear(transpose(a_replaced_d1), 0)
|
||
|
|
a_replaced_d2 = shear(transpose(a_replaced_d2), 0)
|
||
|
|
//fmt.Println(a_replaced_d1, "\n")
|
||
|
|
//fmt.Println(a_replaced_d2, "\n")
|
||
|
|
dot_indices_d := r_dot.FindAllStringIndex(a_replaced_d1, -1)
|
||
|
|
dot_indices_d = append(dot_indices_d, r_dot.FindAllStringIndex(a_replaced_d2, -1)...)
|
||
|
|
//fmt.Println(dot_indices_d)
|
||
|
|
|
||
|
|
// count duplicates
|
||
|
|
matches := 0
|
||
|
|
for _, elem1 := range dot_indices_i {
|
||
|
|
for _, elem2 := range dot_indices_d {
|
||
|
|
if elem1[0] == elem2[0] {
|
||
|
|
matches++
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fmt.Println(matches)
|
||
|
|
}
|