package day3 import ( "fmt" "os" "strings" "unicode" ) func Run() int { filename := "day3/input" 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) for _, num := range numbers { fmt.Println(num) } // partNumbersSum := 0 // for _, num := range numbers { // if len(num.Specials) > 0 { // partNumbersSum += num.Num // } // } gearRatiosSum := partTwo(numbers) return gearRatiosSum } 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 !unicode.IsDigit(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 } // part 2 - find all gears '*' that connect exactly two numbers // multiply the numbers and calculate total sum // i guess i could do full scan of my numbers? // every time i encounter '*' in special symbols, could put that into map, hopefully? // with value for the number func partTwo(numbers []MatrixNumber) int { res := 0 specialsMap := make(map[SpecialSymbol][]MatrixNumber) for _, num := range numbers { for special, _ := range num.Specials { specialsMap[special] = append(specialsMap[special], num) } } for special, nums := range specialsMap { if special.Symb == '*' && len(nums) == 2 { res += nums[0].Num * nums[1].Num } } return res }