Advent-of-Code-2023/day22/block.go

98 lines
1.8 KiB
Go

package day22
import (
"fmt"
"log"
"os"
"regexp"
"strconv"
"strings"
)
type XY struct {
X, Y uint
}
type Block struct {
XMin, XMax uint
YMin, YMax uint
Z uint
IsSettled bool
ZHeight uint
Supports []*Block
}
func (b *Block) String() string {
return fmt.Sprintf("[Block x:%d-%d, y:%d-%d, z:%d, h:%d, isSettled %t]",
b.XMin, b.XMax, b.YMin, b.YMax, b.Z, b.ZHeight, b.IsSettled)
}
func AtoIOrPanic(a string) int {
n, err := strconv.Atoi(a)
if err != nil {
panic(err)
}
return n
}
func ReadBlock(line string) (b Block) {
re := regexp.MustCompile(`(\d+),(\d+),(\d+)~(\d+),(\d+),(\d+)`)
matches := re.FindStringSubmatch(line)
x1, x2 := AtoIOrPanic(matches[1]), AtoIOrPanic(matches[4])
y1, y2 := AtoIOrPanic(matches[2]), AtoIOrPanic(matches[5])
z1, z2 := AtoIOrPanic(matches[3]), AtoIOrPanic(matches[6])
b.XMax = uint(max(x1, x2))
b.XMin = uint(min(x1, x2))
b.YMax = uint(max(y1, y2))
b.YMin = uint(min(y1, y2))
b.Z = uint(min(z1, z2))
b.ZHeight = uint(max(z1, z2)) - b.Z
return
}
func (b *Block) getXY() (coords []XY) {
for x := b.XMin; x <= b.XMax; x++ {
for y := b.YMin; y <= b.YMax; y++ {
coords = append(coords, XY{X: x, Y: y})
}
}
return
}
func ReadBlockFile(filename string) (blocks []*Block) {
bytes, err := os.ReadFile(filename)
if err != nil {
panic(err)
}
text := strings.TrimSpace(string(bytes))
for _, line := range strings.Split(text, "\n") {
block := ReadBlock(line)
blocks = append(blocks, &block)
}
return
}
func BlocksByZ(blocks []*Block) [][]*Block {
maxZ := uint(0)
for _, block := range blocks {
if block.Z > maxZ {
maxZ = block.Z
}
}
log.Print("found max z: ", maxZ)
result := make([][]*Block, maxZ+1)
for _, block := range blocks {
result[block.Z] = append(result[block.Z], block)
}
return result
}