This commit is contained in:
Katherina Walshe-Grey 2024-11-05 13:31:09 +00:00
parent 7403ce8e72
commit 27b95e6717
3 changed files with 148 additions and 0 deletions

113
day03/day03.go Normal file
View file

@ -0,0 +1,113 @@
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
const DIGITS = "0123456789"
const SPACE = '.'
type Number struct {
number int
index int
width int
}
func isDigit(in rune) bool {
return strings.ContainsRune(DIGITS, in)
}
func isNotDigit(in rune) bool {
return !isDigit(in)
}
func isSpace(in rune) bool {
return in == SPACE
}
func isPart(in rune) bool {
return !isDigit(in) && !isSpace(in)
}
func hasPartAtPos(line string, at int) bool {
return at >= 0 && at < len(line) && isPart(rune(line[at]))
}
func hasPartInRange(line string, from int, to int) bool {
return len(line) > from && strings.ContainsFunc(line[max(from, 0):min(to, len(line))], isPart)
}
func findNumbers(line string) (numbers []Number) {
offset, index := 0, 0
for {
index = strings.IndexFunc(line[offset:], isDigit)
if index == -1 {
break
}
width := strings.IndexFunc(line[offset+index:], isNotDigit)
if width == -1 {
width = len(line) - offset - index
}
numberA := line[offset+index:offset+index+width]
numberI, err := strconv.Atoi(numberA)
if err != nil {
panic(fmt.Sprintf(`day03: could not parse number: "%s"`, numberA))
}
numbers = append(numbers, Number{numberI, offset+index, width})
offset += index + width
}
return
}
func ScanFile(file *os.File) (int, error) {
scanner := bufio.NewScanner(file)
var sum int
var prevLine string
var prevNumbers []Number
for scanner.Scan() {
line := scanner.Text()
numbers := findNumbers(line)
var unmatchedNumbers []Number
for _, v := range numbers {
number, index, width := v.number, v.index, v.width
if hasPartAtPos(line, index - 1) || hasPartAtPos(line, index + width) || hasPartInRange(prevLine, index - 1, index + width + 1) {
sum += number
} else {
unmatchedNumbers = append(unmatchedNumbers, v)
}
}
for _, v := range prevNumbers {
number, index, width := v.number, v.index, v.width
if hasPartInRange(line, index - 1, index + width + 1) {
sum += number
}
}
prevLine = line
prevNumbers = unmatchedNumbers
}
if err := scanner.Err(); err != nil {
return 0, err
}
return sum, nil
}
func main() {
sum, err := ScanFile(os.Stdin)
if err != nil {
fmt.Fprintf(os.Stderr, "Invalid input: %s\n", err)
return
}
fmt.Println(sum)
}

25
day03/day03_test.go Normal file
View file

@ -0,0 +1,25 @@
package main
import (
"os"
"testing"
)
func TestScanFile(t *testing.T) {
inFile := "input.txt"
want := 4361
f, err := os.Open(inFile)
if err != nil {
t.Fatal(err)
}
got, err := ScanFile(f)
if err != nil {
t.Fatal(err)
}
if got != want {
t.Errorf("ScanFile(%q) == %d, want %d", inFile, got, want)
}
}

10
day03/input.txt Normal file
View file

@ -0,0 +1,10 @@
467..114..
...*......
..35..633.
......#...
617*......
.....+.58.
..592.....
......755.
...$.*....
.664.598..