Solve day 6

This commit is contained in:
2025-12-06 21:42:43 +02:00
parent 2d5190c044
commit ce1b496761
2 changed files with 221 additions and 0 deletions

4
day6/example.txt Normal file
View File

@@ -0,0 +1,4 @@
123 328 51 64
45 64 387 23
6 98 215 314
* + * +

217
day6/main.go Normal file
View File

@@ -0,0 +1,217 @@
package main
import (
"bufio"
"bytes"
"fmt"
"io"
"iter"
"log"
"os"
"strconv"
"strings"
)
func main() {
f := os.Stdin
if len(os.Args) > 1 && os.Args[1] != "-" {
var err error
f, err = os.Open(os.Args[1])
if err != nil {
log.Fatal(err)
}
defer f.Close()
}
lines, err := readLines(f)
if err != nil {
log.Fatal(err)
}
problems1, err := parseProblemsPart1(lines)
if err != nil {
log.Fatal(err)
}
problems2, err := parseProblemsPart2(lines)
if err != nil {
log.Fatal(err)
}
var result1, result2 int
for _, p := range problems1 {
result1 += p.Solve()
}
for _, p := range problems2 {
result2 += p.Solve()
}
fmt.Println("part one:", result1)
fmt.Println("part two:", result2)
}
type Action int
const (
ActionAdd Action = iota
ActionMultiply
)
type problem struct {
Values []int
Action
}
func (p problem) Solve() int {
if len(p.Values) == 0 {
return 0
}
answer := p.Values[0]
for _, v := range p.Values[1:] {
switch p.Action {
case ActionAdd:
answer += v
case ActionMultiply:
answer *= v
default:
panic(fmt.Sprintf("unsupported action %d", p.Action))
}
}
return answer
}
func readLines(r io.Reader) ([]string, error) {
var lines []string
sc := bufio.NewScanner(r)
for sc.Scan() {
lines = append(lines, sc.Text())
}
return lines, sc.Err()
}
func parseFields(lines []string) [][]string {
cutAll := func(lines []string, sep string) (before, after []string, ok bool) {
var found bool
var i int
for _, line := range lines {
j := strings.Index(line, sep)
if j < 0 {
j = len(line)
} else {
found = true
}
i = max(i, j)
}
if !found {
return lines, nil, false
}
before = make([]string, 0, len(lines))
after = make([]string, 0, len(lines))
for _, line := range lines {
before = append(before, line[:min(i, len(line))])
after = append(after, line[min(i+len(sep), len(line)):])
}
return before, after, true
}
fields := make([][]string, len(lines))
for {
before, after, ok := cutAll(lines, " ")
if !ok {
break
}
for i, v := range before {
fields[i] = append(fields[i], v)
}
lines = after
}
return fields
}
func parseProblemsPart1(lines []string) ([]problem, error) {
if len(lines) == 0 {
return nil, nil
}
var data [][]string
for _, line := range lines {
data = append(data, strings.Fields(line))
}
problems := make([]problem, len(data[0]))
for i, row := range data {
if len(row) != len(problems) {
return nil, fmt.Errorf("line %d: unexpected number of fields", i+2)
}
last := i == len(data)-1
for j, v := range row {
p := &problems[j]
if last {
switch v {
case "+":
p.Action = ActionAdd
case "*":
p.Action = ActionMultiply
default:
return nil, fmt.Errorf("unexpected action %q", v)
}
} else {
n, err := strconv.Atoi(v)
if err != nil {
return nil, err
}
p.Values = append(p.Values, n)
}
}
}
return problems, nil
}
func parseProblemsPart2(lines []string) ([]problem, error) {
fields := parseFields(lines)
var problems []problem
for col := range columnsSeq(fields) {
var p problem
switch s := strings.TrimSpace(col[len(col)-1]); s {
case "+":
p.Action = ActionAdd
case "*":
p.Action = ActionMultiply
default:
return nil, fmt.Errorf("unexpected action %q", s)
}
var colBytes [][]byte
for _, v := range col[:len(col)-1] {
colBytes = append(colBytes, []byte(v))
}
for v := range columnsSeq(colBytes) {
s := string(bytes.TrimSpace(v))
n, err := strconv.Atoi(s)
if err != nil {
return nil, err
}
p.Values = append(p.Values, n)
}
problems = append(problems, p)
}
return problems, nil
}
func columnsSeq[T any](data [][]T) iter.Seq[[]T] {
return func(yield func([]T) bool) {
if len(data) < 1 {
return
}
for x := range len(data[0]) {
var col []T
for y := range data {
col = append(col, data[y][x])
}
if !yield(col) {
break
}
}
}
}