From 7e759f3b8a6abb8a49f7681005dddb8800517e1a Mon Sep 17 00:00:00 2001 From: Gabriel Bizdoc Date: Mon, 8 Dec 2025 05:17:00 +0200 Subject: [PATCH] day 6 --- year25/day6.go | 150 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 year25/day6.go diff --git a/year25/day6.go b/year25/day6.go new file mode 100644 index 0000000..092b44a --- /dev/null +++ b/year25/day6.go @@ -0,0 +1,150 @@ +package year25 + +import ( + "bytes" + "fmt" + "log" + "os" + "strconv" + "strings" + + "git.bizdoc.ro/gabi-public/Advent-of-Code.git/aocutils" + "git.bizdoc.ro/private/devkit.git/collections/geometry/v2" +) + +func Day6Part1(c aocutils.Context) (int64, error) { + c.Logger = log.New(os.Stdout, "", log.LstdFlags) + lines, tokens, err := day6ParseInputs(c) + if err != nil { + return 0, fmt.Errorf("error parsing inputs: %w", err) + } + var total int64 + for _, t := range tokens { + calc := day6NewCalc(t.Operation) + + for _, line := range lines { + valueStr := string(line[t.Start:t.End()]) + v, err := strconv.Atoi(strings.TrimSpace(valueStr)) + if err != nil { + return 0, fmt.Errorf("converting %s to int: %w", valueStr, err) + } + + c.Printf("'%s' ", valueStr) + calc.Put(v) + } + + c.Printf("'%s' %d\n", string(t.Operation), calc.Value) + total += int64(calc.Value) + } + return total, err +} + +func Day6Part2(c aocutils.Context) (int64, error) { + lines, tokens, err := day6ParseInputs(c) + if err != nil { + return 0, fmt.Errorf("error parsing inputs: %w", err) + } + var total int64 + for _, t := range tokens { + calc := day6NewCalc(t.Operation) + + mask := geometry.NewGrid[byte](t.Size, len(lines)).Data() + for i := range mask { + for j := range mask[i] { + mask[i][j] = lines[j][t.Start+i] + } + } + + for _, line := range mask { + v, err := strconv.Atoi(strings.TrimSpace(string(line))) + if err != nil { + return 0, fmt.Errorf("converting %s to int: %w", string(line), err) + } + + c.Printf("'%s' ", string(line)) + calc.Put(v) + } + + c.Printf("'%s' %d\n", string(t.Operation), calc.Value) + total += int64(calc.Value) + } + return total, err +} + +type day6Calc[T any] struct { + Value T + handler func(a T, b T) T +} + +func (d *day6Calc[T]) Put(v T) { + d.Value = d.handler(d.Value, v) +} + +func day6NewCalc(sign byte) day6Calc[int] { + switch sign { + case '+': + return day6Calc[int]{ + Value: 0, + handler: func(a int, b int) int { + return a + b + }, + } + case '*': + return day6Calc[int]{ + Value: 1, + handler: func(a int, b int) int { + return a * b + }, + } + default: + panic(fmt.Errorf("day6NewCalc: invalid sign %v", sign)) + } +} + +type day6Token struct { + Start, Size int + Operation byte +} + +func (t day6Token) End() int { + return t.Start + t.Size +} + +func day6ParseInputs(c aocutils.Context) (lines [][]byte, tokens []day6Token, err error) { + s := c.Scanner() + + // handle malformed input + var maxLineSize int + for i := 0; s.Scan(); i++ { + line := bytes.Clone(s.Bytes()) + maxLineSize = max(maxLineSize, len(line)) + lines = append(lines, line) + } + if err := s.Err(); err != nil { + return nil, nil, fmt.Errorf("error scanning input") + } + + for i := range lines { + if len(lines[i]) < maxLineSize { + lines[i] = append(lines[i], strings.Repeat(" ", maxLineSize-len(lines[i]))...) + } + } + + opLine := lines[len(lines)-1] + for i := bytes.IndexAny(opLine, "+*"); i < maxLineSize; i++ { + tokenLen := bytes.IndexAny(opLine[i+1:], "+*") + if tokenLen == -1 { + tokenLen = maxLineSize - i + } + + tokens = append(tokens, day6Token{ + Start: i, + Size: tokenLen, + Operation: opLine[i], + }) + + i += tokenLen + } + + return lines[:len(lines)-1], tokens, nil +}