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.