Advent-of-Code/year25/day12/day.go
2025-12-23 19:29:13 +02:00

152 lines
3.2 KiB
Go

package day12
import (
"fmt"
"io"
"strconv"
"strings"
"git.bizdoc.ro/gabi-public/Advent-of-Code.git/aoc"
"git.bizdoc.ro/private/devkit.git/gg"
)
func Part1(ctx aoc.Context) (int, error) {
input, err := parseInput(ctx)
if err != nil {
return 0, fmt.Errorf("day12: failed to parse input: %w", err)
}
ctx.Println(input.String())
ares := make([]int, len(input.Shapes))
for i, shape := range input.Shapes {
ares[i] = shape.Area()
}
solution := 0
for _, region := range input.Regions {
regionSize := region.Rows * region.Cols
sum := 0
for i, count := range region.ShapeCounts {
sum += count * ares[i]
}
canFit := sum < regionSize
if canFit {
solution += 1
}
}
return solution, nil
}
type Shape [3][3]byte
func (s *Shape) Area() int {
sum := 0
for i := range s {
for j := range s[i] {
if s[i][j] == '#' {
sum += 1
}
}
}
return sum
}
type Region struct {
Rows, Cols int
ShapeCounts []int
}
func (r *Region) WriteTo(w io.Writer) (n int64, err error) {
out := gg.NewSafeWriter(w)
fmt.Fprintf(out, "%dx%d ", r.Rows, r.Cols)
for _, count := range r.ShapeCounts {
out.WriteString(strconv.Itoa(count) + " ")
}
out.WriteString("\n")
return out.BytesWritten(), out.Err()
}
type Input struct {
Shapes []Shape
Regions []Region
}
func parseInput(ctx aoc.Context) (input Input, err error) {
text, err := ctx.BodyString()
if err != nil {
return input, fmt.Errorf("day12: failed to read input file: %w", err)
}
parts := strings.Split(text, "\n\n")
regionPart := parts[len(parts)-1]
parts = parts[0 : len(parts)-1]
input.Shapes = make([]Shape, len(parts))
for _, part := range parts {
// 0:
// ###
// ##.
// ##.
lines := strings.Split(part, "\n")
id, err := strconv.Atoi(lines[0][:len(lines[0])-1])
if err != nil {
return input, fmt.Errorf("day12: failed to parse shape id: %w", err)
}
shape := input.Shapes[id]
for i := range shape {
for j := range shape[i] {
shape[i][j] = lines[1+i][j]
}
}
input.Shapes[id] = shape // shape is value object
}
for _, regionStr := range strings.Split(regionPart, "\n") {
// 12x5: 1 0 1 0 3 2
var region Region
regionArea, presentsArea := gg.SplitUnpack(regionStr, ": ")
for _, idstr := range strings.Split(presentsArea, " ") {
count, err := strconv.Atoi(idstr)
if err != nil {
return input, fmt.Errorf("day12: failed to parse region count: %w", err)
}
region.ShapeCounts = append(region.ShapeCounts, count)
}
rowsStr, colsStr := gg.SplitUnpack(regionArea, "x")
region.Rows, err = strconv.Atoi(rowsStr)
if err != nil {
return input, fmt.Errorf("day12: failed to parse region rows: %w", err)
}
region.Cols, err = strconv.Atoi(colsStr)
if err != nil {
return input, fmt.Errorf("day12: failed to parse region cols: %w", err)
}
input.Regions = append(input.Regions, region)
}
return input, nil
}
func (i Input) String() string {
buf := strings.Builder{}
for shapeid, shape := range i.Shapes {
fmt.Fprintln(&buf, shapeid)
for i := range shape {
for j := range shape[i] {
buf.WriteString(string(shape[i][j]) + " ")
}
buf.WriteString("\n")
}
buf.WriteString("\n")
}
for _, region := range i.Regions {
region.WriteTo(&buf)
}
return buf.String()
}