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' }