day22: initial block setting

This commit is contained in:
efim 2023-12-22 09:24:43 +00:00
parent 7b34b52e5e
commit 3ede691333
5 changed files with 129 additions and 6 deletions

View File

@ -14,6 +14,7 @@ type XY struct {
}
type Block struct {
NameNum int
XMin, XMax uint
YMin, YMax uint
Z uint
@ -23,8 +24,8 @@ type Block struct {
}
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)
return fmt.Sprintf("[Block %d - x:%d-%d, y:%d-%d, z:%d, h:%d, isSettled %t]",
b.NameNum, b.XMin, b.XMax, b.YMin, b.YMax, b.Z, b.ZHeight, b.IsSettled)
}
func AtoIOrPanic(a string) int {
@ -35,7 +36,8 @@ func AtoIOrPanic(a string) int {
return n
}
func ReadBlock(line string) (b Block) {
func ReadBlock(line string, num int) (b Block) {
b.NameNum = num
re := regexp.MustCompile(`(\d+),(\d+),(\d+)~(\d+),(\d+),(\d+)`)
matches := re.FindStringSubmatch(line)
@ -70,8 +72,8 @@ func ReadBlockFile(filename string) (blocks []*Block) {
}
text := strings.TrimSpace(string(bytes))
for _, line := range strings.Split(text, "\n") {
block := ReadBlock(line)
for i, line := range strings.Split(text, "\n") {
block := ReadBlock(line, i)
blocks = append(blocks, &block)
}

View File

@ -15,7 +15,7 @@ func TestReadBlock(t *testing.T) {
1,1,8~1,1,9`
for _, line := range strings.Split(lines, "\n") {
b := ReadBlock(line)
b := ReadBlock(line, 0)
t.Logf("read %s into block %+v", line, b)
t.Logf("XY coords for %+v are : %+v", b, b.getXY())
}

View File

@ -29,4 +29,5 @@ 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)
** TODO [#A] when i settle single block. the maxSettledOnXY - should use (z + height)
** i can already imagine secon part? what is the most volume that can be disintegrated? or what? most volume is just all

56
day22/space.go Normal file
View File

@ -0,0 +1,56 @@
package day22
type Space struct {
MaxZ uint
SettledOnZ [][]*Block
MaxSettledOnXY map[XY]*Block
UnsettledByZ [][]*Block
}
func NewSpace(blocksByZ [][]*Block) Space {
return Space{
UnsettledByZ: blocksByZ,
MaxZ: uint(len(blocksByZ)),
MaxSettledOnXY: make(map[XY]*Block),
SettledOnZ: make([][]*Block, len(blocksByZ)),
}
}
// settle all blocks in Z, remove Z from UnsettledByZ
func (s *Space)SettleZ(z uint) {
}
// for the block:
// check all XY in MaxSettledOnXY
// if there are any settled blocks on these XY, find max of their Z
// for all blocks with that Z - add block to their 'supports'
// set Z for block to Z+1, settled to true
// add block as highest settled for all the XY
// add block to MaxSettledOnXY
func (s *Space)SettleBlock(block *Block) {
underZMax := uint(0)
underZBlocks := make([]*Block, 0)
for _, xy := range block.getXY() {
underBlock, found := s.MaxSettledOnXY[xy]
// if block.NameNum
if found {
if underBlock.Z > underZMax {
underZBlocks = []*Block{underBlock}
underZMax = underBlock.Z
} else if underBlock.Z == underZMax {
underZBlocks = append(underZBlocks, underBlock)
}
}
s.MaxSettledOnXY[xy] = block
}
for _, settledUnderblock := range underZBlocks {
settledUnderblock.Supports = append(settledUnderblock.Supports, block)
}
block.Z = underZMax + 1
block.IsSettled = true
s.SettledOnZ[block.Z] = append(s.SettledOnZ[block.Z], block)
}

64
day22/space_test.go Normal file
View File

@ -0,0 +1,64 @@
package day22
import "testing"
func TestSpaceSettleSingle(t *testing.T) {
filename := "example"
blocks := ReadBlockFile(filename)
byZ := BlocksByZ(blocks)
space := NewSpace(byZ)
t.Logf("read space %+v", space)
block := blocks[2]
t.Logf("block before setting %+v", block)
space.SettleBlock(block)
t.Logf("space after settings %+v:\n%+v", block, space)
}
func TestSpaceSettleSecondNearby(t *testing.T) {
filename := "example"
blocks := ReadBlockFile(filename)
byZ := BlocksByZ(blocks)
space := NewSpace(byZ)
t.Logf("read space %+v", space)
block1 := blocks[0]
block2 := blocks[3]
t.Logf("block 1 before setting %+v", block1)
space.SettleBlock(block1)
t.Logf("space after settling block 1 %+v", space)
t.Logf("block 2 before setting %+v", block2)
space.SettleBlock(block2)
t.Logf("space after settling block 2 %+v", space)
t.Logf("space after settling %+v", space)
}
func TestSpaceSettleThirdOnTopFirst(t *testing.T) {
filename := "example"
blocks := ReadBlockFile(filename)
byZ := BlocksByZ(blocks)
space := NewSpace(byZ)
t.Logf("read space %+v", space)
block1 := blocks[0]
block2 := blocks[3]
block3 := blocks[2] // should overlap X & Y coords of block 1
t.Logf("block 1 before setting %+v", block1)
space.SettleBlock(block1)
t.Logf("space after settling block 1 %+v", space)
t.Logf("block 2 before setting %+v", block2)
space.SettleBlock(block2)
t.Logf("space after settling block 2 %+v", space)
t.Logf("block 3 before setting %+v", block3)
space.SettleBlock(block3)
t.Logf("space after settling block 3 %+v", space)
t.Logf("space after settling %+v", space)
t.Logf("blocks 1 & 3 should support it: %+v , %+v", block1.Supports, block2.Supports)
// because block 3 is 0-2, 2-2
// and that overlaps 1-1, 0-2 AND 0-0, 0-2
t.Logf("other blocks should not supt %+v", block3.Supports)
}