package day3 import ( "fmt" "os" "strings" "unicode" ) func Run() int { filename := "day3/example" bytes, err := os.ReadFile(filename) if err != nil { panic(fmt.Sprint(err, filename)) } text := string(bytes) matrix := ReadMatrix(text) fmt.Println(matrix.String()) numbers := ReadNumbers(&matrix) fmt.Println(numbers) partNumbersSum := 0 for _, num := range numbers { if len(num.Specials) > 0 { partNumbersSum += num.Num } } return partNumbersSum } type Matrix [][]rune func ReadMatrix(text string) Matrix { text = strings.TrimSpace(text) lines := strings.Split(text, "\n") matrix := make([][]rune, len(lines)) for i, lineStr := range strings.Split(text, "\n") { for _, r := range lineStr { matrix[i] = append(matrix[i], r) } } return matrix } func (m *Matrix)String() string { res := make([]string, len(*m)) for _, row := range *m { res = append(res, string(row) + "\n") } return strings.Join(res, "") } // and now from matrix, i want to scan top-down, left-right // when encountering digit - start new number, read it in // and when finished reading : scan around for the special symbols type SpecialSymbol struct { Symb rune X, Y int } func (s SpecialSymbol) String() string { return fmt.Sprintf("('%s' at x:%d,y:%d)", string(s.Symb), s.X, s.Y) } func (s SpecialSymbol) Equal() bool { return false } type MatrixNumber struct { Num int Specials map[SpecialSymbol]any } func ReadNumbers(m *Matrix) []MatrixNumber { res := make([]MatrixNumber, 0) var curNum *MatrixNumber for x, row := range *m { for y, symb := range row { if unicode.IsDigit(symb) { digit := int(symb - '0') // seing digit if curNum == nil { curNum = &MatrixNumber{ Num: digit, Specials: make(map[SpecialSymbol]any), } } else { curNum.Num = curNum.Num*10 + digit } // on each digit - scan around for special symbols for i := x-1; i <= x+1; i++ { for j := y-1; j <= y+1; j++ { if isValidCoord(i, j, m) { checkingForSpecial := (*m)[i][j] if checkingForSpecial != '.' && !unicode.IsDigit(checkingForSpecial) { special := SpecialSymbol{ Symb: checkingForSpecial, X: i, Y: j, } curNum.Specials[special] = struct{}{} } } } } // now let's check for special symbols around and save them } if symb == '.' { if curNum != nil { res = append(res, *curNum) curNum = nil } } } } return res } // x is row, y is column. from top-left to bottom-right func isValidCoord(x, y int, m *Matrix) bool { if x < 0 || y < 0 || x >= len(*m) || y >= len((*m)[x]) { return false } return true }