day 6
This commit is contained in:
parent
87a9c56a77
commit
7e759f3b8a
150
year25/day6.go
Normal file
150
year25/day6.go
Normal file
@ -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
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user