adventOfCode/internal/2023/day_01/in.go

81 lines
1.9 KiB
Go

package day_01
import (
"fmt"
"regexp"
"strings"
"git.rpjosh.de/RPJosh/go-logger"
"rpjosh.de/adventOfCode/pkg/utils"
)
type Day struct{}
// findFirstAndLastNumber finds the first and last occurence of a number by the given regex
// expression for the number (within a match group).
// If the found string value is present in the map, the mapped value is used
func (d *Day) findFirstAndLastNumber(in string, regex string, stringMap map[string]int) int {
// Build regex to get the first and last number in the string (because of greediness we get the last number)
regexFirst := regexp.MustCompile(`^.*?` + regex + `.*`)
regexLast := regexp.MustCompile(`^.*` + regex)
count := 0
for _, val := range strings.Split(in, "\n") {
if val == "" {
continue
}
matchesFirst := regexFirst.FindStringSubmatch(val)
matchesLast := regexLast.FindStringSubmatch(val)
// We expect exactly at least one match
if len(matchesFirst) < 1 {
logger.Fatal("Failed to get at least one number (got %d): %q", len(matchesFirst), val)
}
str := d.replaceDigitByInt(matchesFirst[1], stringMap)
if len(matchesLast) > 1 {
str += d.replaceDigitByInt(matchesLast[1], stringMap)
}
count += utils.ToInt(str)
}
return count
}
func (d *Day) replaceDigitByInt(val string, stringMap map[string]int) string {
if v, exists := stringMap[val]; exists {
return fmt.Sprintf("%d", v)
}
return val
}
func (d *Day) Part1(in string) string {
return fmt.Sprintf("%d", d.findFirstAndLastNumber(in, `(\d)`, make(map[string]int)))
}
func (d *Day) Part2(in string) string {
digist := map[string]int{
"one": 1,
"two": 2,
"three": 3,
"four": 4,
"five": 5,
"six": 6,
"seven": 7,
"eight": 8,
"nine": 9,
}
// Build regex string by looping through all digists
regex := `(\d`
for k, _ := range digist {
regex += "|" + k
}
regex += ")"
return fmt.Sprintf("%d", d.findFirstAndLastNumber(in, regex, digist))
}