github.com/agrigoryan/aoc_2023_go@v0.0.0-20231216221323-4ace361ec685/day3/d3p2.go (about) 1 package day3 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 "unicode" 8 ) 9 10 func d3p2(input string) int { 11 lines := strings.Split(input, "\n") 12 13 const empty = '.' 14 15 hasSymbol := func(parts []string) bool { 16 for _, p := range parts { 17 for _, r := range p { 18 if !unicode.IsDigit(r) && r != empty { 19 return true 20 } 21 } 22 } 23 return false 24 } 25 26 type partNumber struct { 27 numLine int 28 value int 29 start int 30 end int 31 } 32 33 parts := []partNumber{} 34 35 digitFound := func(numLine int, line string, start int, end int) { 36 pStart := max(start-1, 0) 37 pEnd := min(end+1, len(line)) 38 partsToCheck := []string{line[pStart:pEnd]} 39 40 if numLine > 0 { 41 partsToCheck = append(partsToCheck, lines[numLine-1][pStart:pEnd]) 42 } 43 if numLine < len(lines)-1 { 44 partsToCheck = append(partsToCheck, lines[numLine+1][pStart:pEnd]) 45 } 46 47 if hasSymbol(partsToCheck) { 48 if num, err := strconv.Atoi(line[start:end]); err == nil { 49 parts = append(parts, partNumber{ 50 numLine: numLine, 51 value: num, 52 start: start, 53 end: end, 54 }) 55 } 56 } 57 } 58 59 for i, line := range lines { 60 digitStart := -1 61 for j, r := range line { 62 if unicode.IsDigit(r) { 63 if digitStart == -1 { 64 digitStart = j 65 } 66 } else if digitStart != -1 { 67 digitFound(i, line, digitStart, j) 68 digitStart = -1 69 } 70 } 71 if digitStart != -1 { 72 digitFound(i, line, digitStart, len(line)) 73 } 74 } 75 76 sum := 0 77 for i, line := range lines { 78 for j, r := range line { 79 if r == '*' { 80 adjacentPartNumbers := []int{} 81 for _, p := range parts { 82 if p.numLine < i+2 && p.numLine > i-2 && j > p.start-2 && j < p.end+1 { 83 adjacentPartNumbers = append(adjacentPartNumbers, p.value) 84 } 85 } 86 if len(adjacentPartNumbers) == 2 { 87 sum += adjacentPartNumbers[0] * adjacentPartNumbers[1] 88 } 89 } 90 } 91 } 92 fmt.Println(sum) 93 return sum 94 }