day22, simple block code
This commit is contained in:
parent
99c2269df8
commit
7b34b52e5e
|
@ -0,0 +1,97 @@
|
|||
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
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package day22
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReadBlock(t *testing.T) {
|
||||
lines := `1,0,1~1,2,1
|
||||
0,0,2~2,0,2
|
||||
0,2,3~2,2,3
|
||||
0,0,4~0,2,4
|
||||
2,0,5~2,2,5
|
||||
0,1,6~2,1,6
|
||||
1,1,8~1,1,9`
|
||||
|
||||
for _, line := range strings.Split(lines, "\n") {
|
||||
b := ReadBlock(line)
|
||||
t.Logf("read %s into block %+v", line, b)
|
||||
t.Logf("XY coords for %+v are : %+v", b, b.getXY())
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadFile(t *testing.T) {
|
||||
filename := "example"
|
||||
// filename := "input"
|
||||
blocks := ReadBlockFile(filename)
|
||||
|
||||
byZ := BlocksByZ(blocks)
|
||||
for z, zBlocks := range byZ {
|
||||
zBlocksLine := ""
|
||||
for _, block := range zBlocks {
|
||||
zBlocksLine += block.String()
|
||||
}
|
||||
t.Logf("for level %d blocks %+v", z, zBlocksLine)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
1,0,1~1,2,1
|
||||
0,0,2~2,0,2
|
||||
0,2,3~2,2,3
|
||||
0,0,4~0,2,4
|
||||
2,0,5~2,2,5
|
||||
0,1,6~2,1,6
|
||||
1,1,8~1,1,9
|
|
@ -0,0 +1,32 @@
|
|||
#+title: Notes
|
||||
* ok. let's try this.
|
||||
i'd want to have block type
|
||||
with function to get it's XY coords
|
||||
|
||||
i'd want to settle blocks first.
|
||||
but if i store enough data, for example block.supports slice i'll be able to anser first task.
|
||||
|
||||
(settledOnZ) i would want [][]*Block per level from 0 to up. with references to blocks that settled on that level
|
||||
|
||||
(maxSettledXY) and for going from 0 up i'll want XY of the top block settled with it's level. i guess i could store settled level in the block as well
|
||||
|
||||
then for settling blocks, i will need (sorted map if data is sparse?) go from 0 up,
|
||||
order of processing for blocks on same z level is not important.
|
||||
for each block get it's XY, check maxSettledXY if there's a block check it's Z,
|
||||
for all block XY coords, find maximal settled Z, and refs to all blocks that are directly under with that same Z.
|
||||
|
||||
for the block set settledZ to Z+1, and for all those blocks add the block to 'supports'
|
||||
add block to settledOnZ[Z+1]
|
||||
|
||||
for the second part, i can scan all the blocks, don't even need the settledOnZ, just check if it's 'supports' is empty
|
||||
|
||||
** DONE block type
|
||||
store z, and have 'settledZ', maybe with default -1?
|
||||
** DONE coords type, func to get XY coords of the block
|
||||
** DONE now i guess what? do i want a sorted map? or just map from height to blocks on that hight?
|
||||
let's read file, and calc max height present?
|
||||
i suppose funciton to read file could also be initially entered via test, right?
|
||||
** TODO now go through the z levels, block by block, doing setting.
|
||||
i suppose i could organize setting methods around Space?
|
||||
it will store (settledOnZ) and (maxSettledOnXY)
|
||||
** i can already imagine secon part? what is the most volume that can be disintegrated? or what? most volume is just all
|
|
@ -0,0 +1,10 @@
|
|||
package day22
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func Run() int {
|
||||
fmt.Print("oi, hello day 22")
|
||||
return 0
|
||||
}
|
6
main.go
6
main.go
|
@ -4,15 +4,15 @@ import (
|
|||
"log"
|
||||
"time"
|
||||
|
||||
"sunshine.industries/aoc2023/day21"
|
||||
"sunshine.industries/aoc2023/day22"
|
||||
)
|
||||
|
||||
func main() {
|
||||
startTime := time.Now()
|
||||
log.Print("> starting run:")
|
||||
|
||||
result := day21.Run()
|
||||
log.Printf("\n\nday21 result: %d\n****\n", result)
|
||||
result := day22.Run()
|
||||
log.Printf("\n\nday22 result: %d\n****\n", result)
|
||||
endTime := time.Now()
|
||||
diff := endTime.Sub(startTime)
|
||||
log.Printf("execution took %s", diff.String())
|
||||
|
|
Loading…
Reference in New Issue