Skip to main content

w_yw blog

Day3-Gear Ratios

Table of Contents

My solution and thoughts on Day 3 puzzle of Advent of Code 2023

## Part One

# Puzzle

The engine schematic (your puzzle input) consists of a visual representation of the engine. There are lots of numbers and symbols you don’t really understand, but apparently any number adjacent to a symbol, even diagonally, is a “part number” and should be included in your sum. (Periods (.) do not count as a symbol.)

Here is an example engine schematic:

467..114..
...*......
..35..633.
......#...
617*......
.....+.58.
..592.....
......755.
...$.*....
.664.598..

In this schematic, two numbers are not part numbers because they are not adjacent to a symbol: 114 (top right) and 58 (middle right). Every other number is adjacent to a symbol and so is a part number; their sum is _4361_.

Of course, the actual engine schematic is much larger. What is the sum of all of the part numbers in the engine schematic?

# Solution - Functions

- main()
- readLine(line string)
- checkSymbol(str string)
- findNumbers(matrix [][]int) [][]int
- checkNeighbors(matrix [][]int, ni, nj int) (int, int, bool)
- recursiveCheck(matrix [][]int, ni, nj int) [][]int
- findSum(matrix [][]int, charts [][]string) []int
- getSum(numbers []int) int

## main

func main() {  
    file, err := os.ReadFile("input2.txt")  
    if err != nil {  
       return  
    }  
    lines := strings.Split(string(file), "\n")  
    var matrix [][]int  
    var charts [][]string  
    for _, line := range lines {  
       // skip the empty line  
       if line == "" {  
          continue  
       }  
       // set the matrix  
       symPlace, chart := readLine(line)  
       matrix = append(matrix, symPlace)  
       // set the charts  
       charts = append(charts, chart)  
    }    var checkedMatrix [][]int  
    checkedMatrix = findNumbers(matrix)  
    // get the corresponding numbers from the matrix  
    var numbers []int  
    numbers = findSum(checkedMatrix, charts)  
    // get the sum of the numbers  
    var sum int  
    sum = getSum(numbers)  
    fmt.Println("The sum of the numbers is", sum)  
}

## readLine

func readLine(line string) ([]int, []string) {  
    // check the char is a symbol or not  
    symPlace := checkSymbol(line)  
    // add lines to the chart  
    var chart []string  
    for _, char := range line {  
       chart = append(chart, string(char))  
    }    return symPlace, chart  
}

## checkSymbol

// checkSymbol check the char is a symbol or not and return the place of the symbol  
func checkSymbol(str string) []int {  
    var symPlace []int  
    for i, char := range str {  
       if !unicode.IsDigit(char) && !(string(char) == ".") {  
          // if the char is not a number or ".", add the place to the symPlace  
          symPlace = append(symPlace, i)  
       } else if string(char) == "." {  
          // if the char is ".", add 0 to the symPlace  
          symPlace = append(symPlace, 0)  
       } else {  
          // if the char is a number, add -1 to the symPlace  
          symPlace = append(symPlace, -1)  
       }    }    return symPlace  
}

## findNumbers

func findNumbers(matrix [][]int) [][]int {  
    var checkedMatrix [][]int  
    for i, line := range matrix {  
       for j, place := range line {  
          // exclude the "."  
          if place > 0 {  
             // check neighbors if they are -1, which means they are numbers  
             // di/dj stands for the change in the i/j index, which corresponds to moving up or down in the matrix.             for di := -1; di <= 1; di++ {  
                for dj := -1; dj <= 1; dj++ {  
                   ni, nj := i+di, j+dj  
                   if ni >= 0 && ni < len(matrix) && nj >= 0 && nj < len(matrix[i]) && matrix[ni][nj] == -1 {  
                      //fmt.Printf(" position (%d, %d) and its value is %d\n", ni, nj, matrix[ni][nj])  
                      // recursive check the neighbors of this number if they are -1                      
                      checkedMatrix = recursiveCheck(matrix, ni, nj)  
                   }                
                }             
             }          
          }       
       }   
    }    
    return checkedMatrix  
}

## checkNeighbors

func checkNeighbors(matrix [][]int, ni, nj int) (int, int, bool) {  
    // set the current position to -2, which means it's checked  
    matrix[ni][nj] = -2  
    if nj <= 0 || nj >= len(matrix[ni])-1 {  
       //fmt.Println("ni,nj reach limit", ni, nj)  
       return ni, nj, false  
    } else {  
       if matrix[ni][nj-1] == -1 {  
          //fmt.Println("ni,nj is number", ni, nj-1)  
          return ni, nj - 1, true  
       } else if matrix[ni][nj+1] == -1 {  
          //fmt.Println("ni,nj is number", ni, nj+1)  
          return ni, nj + 1, true  
       }  
    }    return ni, nj, false  
}

## recursiveCheck

func recursiveCheck(matrix [][]int, ni, nj int) [][]int {  
    // flag is used to check whether the neighbors are -1  
    var flag bool  
    ni, nj, flag = checkNeighbors(matrix, ni, nj)  
    if flag {  
       recursiveCheck(matrix, ni, nj)  
    } else {  
       return matrix  
    }  
    return matrix  
}

## findSum

func findSum(matrix [][]int, charts [][]string) []int {  
    var s string  
    var numbers []int  
    for i := 0; i < len(matrix); i++ {  
       for j := 0; j < len(matrix[i]); j++ {  
          if matrix[i][j] == -2 {  
             s += charts[i][j]  
          }          // add "|" between numbers for sorting later on  
          if !(j == len(matrix[i])-1) {  
             // if the next one is not a number, add "|"  
             if matrix[i][j+1] != -2 {  
                s += "|"  
             }  
          }       
       }      
       if i == len(matrix)-1 {  
          str := strings.Split(s, "|")  
          for _, num := range str {  
             if num != "" {  
                num, _ := strconv.Atoi(num)  
                numbers = append(numbers, num)  
             }          
          }       
       }    
    }    
    return numbers  
}

## getSum

func getSum(numbers []int) int {  
    var sum int  
    for _, num := range numbers {  
       sum += num  
    }  
    return sum  
}

# Review

Again, my way is too verbose, I managed to figure out the part one, but it seems like i use a wrong way to deal with offset, so the part two became difficult for me, I find someone else using regexp package to deal with it, and it became so easy, I decided to look into that, and try to find a better way to reconstruct the algorithm.