152 lines
3.2 KiB
Go
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()
|
|
}
|