Created
December 3, 2023 06:21
-
-
Save PatrickVienne/8c4dd899fb4d2e974786e7dd3b029623 to your computer and use it in GitHub Desktop.
Advent of Code 2023 - Day 3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package d3 | |
import ( | |
"bufio" | |
"io" | |
"regexp" | |
"strconv" | |
) | |
func Must(err error) { | |
if err != nil { | |
panic(err) | |
} | |
} | |
func getSum(numbers []int) int { | |
total := 0 | |
for _, num := range numbers { | |
total += num | |
} | |
return total | |
} | |
// idea: | |
// find all numbers and their index ranges | |
// look for symbol around their index ranges | |
func d3_1(r io.Reader) int { | |
numberLinesStartTopIdx := map[int][][3]int{} | |
symbolLinesStartTopIdx := map[int]map[int]bool{} | |
reNums := regexp.MustCompile(`\d+`) | |
fileScanner := bufio.NewScanner(r) | |
fileScanner.Split(bufio.ScanLines) | |
lineNo := 0 | |
for fileScanner.Scan() { | |
numberLinesStartTopIdx[lineNo] = [][3]int{} | |
lineBytes := fileScanner.Bytes() | |
for i, c := range lineBytes { | |
if (c >= '0' && c <= '9') || c == '.' { | |
continue | |
} else { | |
if val, ok := symbolLinesStartTopIdx[lineNo]; !ok { | |
symbolLinesStartTopIdx[lineNo] = map[int]bool{i: true} | |
} else { | |
val[i] = true | |
} | |
} | |
} | |
nums := reNums.FindAllIndex(lineBytes, -1) | |
for _, numGroup := range nums { | |
num, err := strconv.Atoi(string(lineBytes[numGroup[0]:numGroup[1]])) | |
Must(err) | |
numberLinesStartTopIdx[lineNo] = append(numberLinesStartTopIdx[lineNo], [3]int{numGroup[0], numGroup[1], num}) | |
} | |
lineNo++ | |
} | |
validNumbers := []int{} | |
for lineNo, numGroups := range numberLinesStartTopIdx { | |
for _, numGroup := range numGroups { | |
// start or end of number | |
if symbolLine, ok := symbolLinesStartTopIdx[lineNo]; !ok { | |
// nothing on the same line | |
} else if symbolLine[numGroup[0]-1] || symbolLine[numGroup[1]] { | |
validNumbers = append(validNumbers, numGroup[2]) | |
continue | |
} | |
// line on top or under | |
for i := numGroup[0] - 1; i <= numGroup[1]; i++ { | |
if symbolLine, ok := symbolLinesStartTopIdx[lineNo-1]; !ok { | |
// nothing on the same line | |
} else if symbolLine[i] { | |
validNumbers = append(validNumbers, numGroup[2]) | |
break | |
} | |
if symbolLine, ok := symbolLinesStartTopIdx[lineNo+1]; !ok { | |
// nothing on the same line | |
} else if symbolLine[i] { | |
validNumbers = append(validNumbers, numGroup[2]) | |
break | |
} | |
} | |
} | |
} | |
return getSum(validNumbers) | |
} | |
func d3_2(r io.Reader) int { | |
numberLinesStartTopIdx := map[int][][3]int{} | |
symbolLinesStartTopIdx := map[int]map[int]bool{} | |
reNums := regexp.MustCompile(`\d+`) | |
fileScanner := bufio.NewScanner(r) | |
fileScanner.Split(bufio.ScanLines) | |
lineNo := 0 | |
for fileScanner.Scan() { | |
numberLinesStartTopIdx[lineNo] = [][3]int{} | |
lineBytes := fileScanner.Bytes() | |
for i, c := range lineBytes { | |
if c == '*' { | |
if val, ok := symbolLinesStartTopIdx[lineNo]; !ok { | |
symbolLinesStartTopIdx[lineNo] = map[int]bool{i: true} | |
} else { | |
val[i] = true | |
} | |
} | |
} | |
nums := reNums.FindAllIndex(lineBytes, -1) | |
for _, numGroup := range nums { | |
num, err := strconv.Atoi(string(lineBytes[numGroup[0]:numGroup[1]])) | |
Must(err) | |
numberLinesStartTopIdx[lineNo] = append(numberLinesStartTopIdx[lineNo], [3]int{numGroup[0], numGroup[1], num}) | |
} | |
lineNo++ | |
} | |
totalSum := 0 | |
for lineNo, startStops := range symbolLinesStartTopIdx { | |
for gearIdx := range startStops { | |
neighborNumsCount := 0 | |
neighborNums := []int{} | |
for _, numGroup := range numberLinesStartTopIdx[lineNo-1] { | |
if gearIdx >= numGroup[0]-1 && gearIdx <= numGroup[1] { | |
neighborNumsCount++ | |
neighborNums = append(neighborNums, numGroup[2]) | |
} | |
} | |
for _, numGroup := range numberLinesStartTopIdx[lineNo] { | |
if gearIdx >= numGroup[0]-1 && gearIdx <= numGroup[1] { | |
neighborNumsCount++ | |
neighborNums = append(neighborNums, numGroup[2]) | |
} | |
} | |
for _, numGroup := range numberLinesStartTopIdx[lineNo+1] { | |
if gearIdx >= numGroup[0]-1 && gearIdx <= numGroup[1] { | |
neighborNumsCount++ | |
neighborNums = append(neighborNums, numGroup[2]) | |
} | |
} | |
if neighborNumsCount == 2 { | |
totalSum += neighborNums[0] * neighborNums[1] | |
} | |
} | |
} | |
return totalSum | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment