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 }