83 lines
1.6 KiB
Go
83 lines
1.6 KiB
Go
|
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))
|
||
|
}
|