advent-of-code-2023/day1/main.go

83 lines
1.6 KiB
Go
Raw Normal View History

2023-12-01 12:37:08 +00:00
package main
import (
"errors"
"fmt"
"io"
"os"
"strconv"
"strings"
"unicode"
)
func filterChars(line string, criteria func(rune) bool) string {
validChars := []rune{}
for _, char := range line {
if criteria(char) {
validChars = append(validChars, char)
}
}
return string(validChars)
}
func getCoordinate(line string) (int, error) {
candidates := filterChars(line, unicode.IsDigit)
if len(candidates) == 0 {
return 0, errors.New("invalid calibration value")
}
if len(candidates) == 1 {
value, err := strconv.Atoi(candidates)
if err != nil {
// Programmer error, given the above filter
panic("invalid numeric string " + candidates)
}
return value*10 + value, nil
}
value1 := int(candidates[0] - '0')
value2 := int(candidates[len(candidates)-1] - '0')
return value1*10 + value2, nil
}
func part1(input []string) int {
total := 0
for _, line := range input {
coordinate, err := getCoordinate(line)
if err != nil {
panic(fmt.Sprintf("No valid coordinate on line '%s': %s\n", line, err))
}
total += coordinate
}
return total
}
func main() {
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, "Usage: %s inputfile\n", os.Args[0])
os.Exit(1)
}
filename := os.Args[1]
inputFile, err := os.Open(filename)
if err != nil {
panic(fmt.Sprintf("failed to open input file: %s", err))
}
defer inputFile.Close()
inputFileBytes, err := io.ReadAll(inputFile)
if err != nil {
panic(fmt.Sprintf("failed to read input file: %s", err))
}
input := string(inputFileBytes)
inputLines := strings.Split(strings.TrimSpace(input), "\n")
fmt.Printf("Part 1: %d\n", part1(inputLines))
}