adventofcode/2023/day03/main.go

111 lines
2.3 KiB
Go

package main
import (
"fmt"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
func main() {
inp := h.StdinToStringSlice()
part1(inp)
part2(inp)
}
func part1(input []string) {
bm := h.StringSliceToCoordByteMap(input)
symbols := bm.FindAllNot('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.')
// Gather a list of numbers that are adjacent to the symbols
nums := make(map[h.Coordinate]int)
for k, _ := range symbols {
wrk := findPartNumsFrom(bm, k)
for coord, val := range wrk {
nums[coord] = val
}
}
var sum int
for _, v := range nums {
sum += v
}
fmt.Println("# Part 1")
fmt.Println(sum)
}
func part2(input []string) {
bm := h.StringSliceToCoordByteMap(input)
maybeGears := bm.FindAll('*')
var ratioSum int
for _, k := range maybeGears {
wrk := findPartNumsFrom(bm, k)
if len(wrk) != 2 {
// It's not a gear
continue
}
var second bool
var ratio int
for _, v := range wrk {
if !second {
ratio += v
second = true
} else {
ratio *= v
}
}
ratioSum += ratio
}
fmt.Println("# Part 2")
fmt.Println(ratioSum)
}
func findPartNumsFrom(m h.CoordByteMap, c h.Coordinate) map[h.Coordinate]int {
partNums := make(map[h.Coordinate]int)
for _, chk := range []h.Coordinate{
c.North(),
c.NE(),
c.East(),
c.SE(),
c.South(),
c.SW(),
c.West(),
c.NW(),
} {
if m.Get(chk) >= '0' && m.Get(chk) <= '9' {
v, pos := parseNumAt(m, chk)
partNums[pos] = v
}
}
return partNums
}
// parseNumAt returns the number at c and the Coordinate
// that the first digit of that number is at
func parseNumAt(m h.CoordByteMap, c h.Coordinate) (int, h.Coordinate) {
var resStr string
startCoord := c
// From 'c' move left until we find the first digit
chk := m.Get(startCoord)
for coordIsNum(m, startCoord) {
startCoord = startCoord.West()
chk = m.Get(startCoord)
}
startCoord = startCoord.East()
// Now put the number at 'startCoord' together
parseNum := startCoord
chk = m.Get(startCoord)
for coordIsNum(m, parseNum) {
resStr = fmt.Sprintf("%s%s", resStr, string(chk))
parseNum = parseNum.East()
chk = m.Get(parseNum)
}
if resStr == "" {
return -1, h.Coordinate{X: -1, Y: -1}
}
return h.Atoi(resStr), startCoord
}
func coordIsNum(m h.CoordByteMap, c h.Coordinate) bool {
wrk := m.Get(c)
return wrk >= '0' && wrk <= '9'
}