diff --git a/day22/notes.org b/day22/notes.org index 2d31056..0e3022e 100644 --- a/day22/notes.org +++ b/day22/notes.org @@ -26,8 +26,26 @@ store z, and have 'settledZ', maybe with default -1? ** 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. +** DONE 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) +** DONE [#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 +* part 1, wrong answer. +i guess try to go, setting the input? block after block and try to check the calculations? + +what i want to check: +how maxSettledOnXY works, how linking works. maybe i'll find a problem in few steps =C +** can't see anything just glancing around. +maybe then trying to pick a block and track what's under it? +* ok. let's try to brute force? +for each block, remove it? +create new space and try to settle it +** this is shit. why blocks move up? +2023/12/22 12:12:24 >>> starting for block [Block 1 - x:0-2, y:0-0, z:1, h:0, isSettled true] (supports [[Block 3 - x:0-0, y:0-2, z:3, h:0, isSettled true] [Block 4 - x:2-2, y:0-2, z:3, h:0, isSettled true] [Block 3 - x:0-0, y:0-2, z:2, h:0, isSettled true] [Block 4 - x:2-2, y:0-2, z:2, h:0, isSettled true]]) +2023/12/22 12:12:24 block [Block 2 - x:0-2, y:2-2, z:2, h:0, isSettled true] moved from 1 to 2 +2023/12/22 12:12:24 block [Block 3 - x:0-0, y:0-2, z:3, h:0, isSettled true] moved from 2 to 3 +2023/12/22 12:12:24 block [Block 4 - x:2-2, y:0-2, z:3, h:0, isSettled true] moved from 2 to 3 +2023/12/22 12:12:24 block [Block 5 - x:0-2, y:1-1, z:4, h:0, isSettled true] moved from 3 to 4 +2023/12/22 12:12:24 block [Block 6 - x:1-1, y:1-1, z:5, h:1, isSettled true] moved from 4 to 5 +2023/12/22 12:12:24 for block [Block 1 - x:0-2, y:0-0, z:1, h:0, isSettled true] new space has 5 moved diff --git a/day22/printingSpace.go b/day22/printingSpace.go new file mode 100644 index 0000000..4a95083 --- /dev/null +++ b/day22/printingSpace.go @@ -0,0 +1,38 @@ +package day22 + +import ( + "math" + + "github.com/tidwall/pinhole" +) + +func TestPinhole() { + p := pinhole.New() + p.DrawCube(-0.3, -0.3, -0.3, 0.3, 0.3, 0.3) + p.Rotate(math.Pi/3, math.Pi/2, 0) + p.SavePNG("cube.png", 500, 500, nil) +} + +func PrintSpace(s Space, filename string) { + // pinhole is from -1 to 1. let's use from 0 to 1. + // so coord should be divided by max height, and let's hope that they are not too wide + + rotation := []float64{math.Pi/3, math.Pi/6, 0} + + p := pinhole.New() + + p.DrawRect(-1, -1, 1, 1, 0) + + for _, zLevel := range s.SettledOnZ { + for _, block := range zLevel { + p.DrawCube(float64(block.XMin) / float64(s.MaxZ), + float64(block.YMin) / float64(s.MaxZ), + float64(block.Z) / float64(s.MaxZ), + float64(block.XMax + 1) / float64(s.MaxZ), + float64(block.YMax + 1) / float64(s.MaxZ), + float64(block.Z + block.ZHeight + 1) / float64(s.MaxZ)) + } + } + p.Rotate(rotation[0], rotation[1], rotation[2]) + p.SavePNG(filename, 1920, 1080, nil) +} diff --git a/day22/sandSlabs.go b/day22/sandSlabs.go index 2476633..7d4f608 100644 --- a/day22/sandSlabs.go +++ b/day22/sandSlabs.go @@ -6,13 +6,13 @@ import ( func Run() int { fmt.Print("oi, hello day 22") - filename := "day22/example" + filename := "day22/input" blocks := ReadBlockFile(filename) byZ := BlocksByZ(blocks) space := NewSpace(byZ) space.SettleAll() - result := space.CountFreeBlocks() + result := space.ThirdTimeCountFreeBlocks() return result } diff --git a/day22/space.go b/day22/space.go index e0c3e91..0351ebc 100644 --- a/day22/space.go +++ b/day22/space.go @@ -1,6 +1,11 @@ package day22 -import "log" +import ( + // "fmt" + "log" + "slices" + // "time" +) type Space struct { MaxZ uint @@ -18,16 +23,37 @@ func NewSpace(blocksByZ [][]*Block) Space { } } -func (s *Space)CountFreeBlocks() (result int) { +func (s *Space) AgainCountFreeBlocks() (result int) { + for _, row := range s.SettledOnZ { + for _, block := range row { + thisSupports := block.Supports + canDisintegrate := true + for _, blockThisSupports := range thisSupports { + if len(blockThisSupports.SupportedBy) == 1 { + // we cannot disintigrate this block + canDisintegrate = false + } + } + if canDisintegrate { + result += 1 + } + } + } + return +} + + +func (s *Space) CountFreeBlocks() (result int) { allBlocks := make(map[*Block]any) for _, row := range s.SettledOnZ { for _, block := range row { allBlocks[block] = struct{}{} if len(block.SupportedBy) == 1 { - log.Printf("in block %+v. only support is %+v", block, block.SupportedBy) - log.Printf("should be NOT OK to remove %+v", block.SupportedBy) - delete(allBlocks, block.SupportedBy[0]) + onlySupport := block.SupportedBy[0] + log.Printf("in block %+v. only support is %+v", block, onlySupport) + log.Printf("should be NOT OK to remove %+v", onlySupport) + delete(allBlocks, onlySupport) } } } @@ -35,21 +61,61 @@ func (s *Space)CountFreeBlocks() (result int) { return } -func (s *Space)SettleAll() { - for i := uint(1); i <= s.MaxZ; i++ { - s.SettleZ(i) +func (s *Space) ThirdTimeCountFreeBlocks() (result int) { + // for each block create a new space without it. try to settle and check if 0 moved + log.Println(">>>>> starting hardcode count <<<<<") + for rowNum, row := range s.SettledOnZ { + for blockNum, block := range row { + log.Printf(">>> starting for block %+v (supports %+v)\n", block, block.Supports) + newUnsettled := slices.Clone(s.SettledOnZ) + for rowNum, row := range newUnsettled { + newUnsettled[rowNum] = slices.Clone(row) + } + newUnsettled[rowNum] = slices.Delete(newUnsettled[rowNum], blockNum, blockNum+1) + // and now copy the blocks + for rowNum, row := range newUnsettled { + for blockNum, block := range row { + newBlock := *block + newUnsettled[rowNum][blockNum] = &newBlock + } + } + + newSpace := NewSpace(newUnsettled) + moved := newSpace.SettleAll() + if moved > 0 { + log.Printf("for block %+v new space has %d moved\n\n", block, moved) + } else { + log.Printf("for block %+v new space has %d moved\n\n", block, moved) + result += 1 + } + + } } + + return +} + +func (s *Space) SettleAll() (totalMoved int) { + for i := uint(1); i <= s.MaxZ; i++ { + movedAfterLayer := s.SettleZ(i) + totalMoved += movedAfterLayer + } + return } // settle all blocks in Z, remove Z from UnsettledByZ -func (s *Space)SettleZ(z uint) { +func (s *Space) SettleZ(z uint) (totalMoved int) { blocksToSettle := s.UnsettledByZ[int(z)] for _, block := range blocksToSettle { - s.SettleBlock(block) + hasMoved := s.SettleBlock(block) + if hasMoved { + totalMoved += 1 + } } s.UnsettledByZ[int(z)] = nil + return } // for the block: @@ -59,20 +125,29 @@ func (s *Space)SettleZ(z uint) { // 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) { +func (s *Space) SettleBlock(block *Block) (hasMoved bool) { + initialZ := block.Z underZMax := uint(0) underZBlocks := make([]*Block, 0) + // fmt.Printf("\n>> for block %s\n", block) for _, xy := range block.getXY() { underBlock, found := s.MaxSettledOnXY[xy] // if block.NameNum if found { underBlockMaxZ := underBlock.Z + underBlock.ZHeight + // action := " 'skipping' " if underBlockMaxZ > underZMax { underZBlocks = []*Block{underBlock} underZMax = underBlockMaxZ + // action = " 'overriding' " } else if underBlockMaxZ == underZMax { underZBlocks = append(underZBlocks, underBlock) + // action = " 'adding' " } + // fmt.Printf("checking under coord %+v. found under %+v. (%s) with %d ; maxZ %d\n directly supporting blocks are %+v\n", + // xy, underBlock, action, underBlockMaxZ, underZMax, underZBlocks) + } else { + // fmt.Printf("checking under coord %+v. nothing under\n", xy) } s.MaxSettledOnXY[xy] = block } @@ -86,4 +161,12 @@ func (s *Space)SettleBlock(block *Block) { block.IsSettled = true s.SettledOnZ[block.Z] = append(s.SettledOnZ[block.Z], block) + // fmt.Printf(">> after settring block %s. supported by %+v\n\n", block, block.SupportedBy) + + // time.Sleep(500 * time.Millisecond) + hasMoved = initialZ != block.Z + if hasMoved { + log.Printf("block %+v moved from %d to %d", block, initialZ, block.Z) + } + return } diff --git a/day22/space_test.go b/day22/space_test.go index 5379601..e3dec2b 100644 --- a/day22/space_test.go +++ b/day22/space_test.go @@ -85,3 +85,22 @@ func TestSpaceExampleSettleAll(t *testing.T) { // i guess we can start with set of all blocks, then? // run over all, if some block is only supported by some underBlock - remove that underblock } + +func TestPinholeStart(t *testing.T) { + TestPinhole() +} + +func TestExampleSpacePrint(t *testing.T) { + filename := "example" + blocks := ReadBlockFile(filename) + byZ := BlocksByZ(blocks) + + space := NewSpace(byZ) + + // PrintSpace(space, "before-settping.png") + + space.SettleAll() + + PrintSpace(space, "after-settping.png") + +} diff --git a/go.mod b/go.mod index 2c193a9..6c21a56 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,12 @@ module sunshine.industries/aoc2023 go 1.21.4 + +require github.com/tidwall/pinhole v0.0.0-20210130162507-d8644a7c3d19 + +require ( + github.com/fogleman/gg v1.3.0 // indirect + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect + github.com/google/btree v1.1.2 // indirect + golang.org/x/image v0.14.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..f788e65 --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/tidwall/pinhole v0.0.0-20210130162507-d8644a7c3d19 h1:PH18rfaiwA/34DAtuREBTrrByvZeLHqhfYh4SG7jYg4= +github.com/tidwall/pinhole v0.0.0-20210130162507-d8644a7c3d19/go.mod h1:5VfbOBfzaI6Y0XiGSkz7hiXgKtwYaDBI3plwKGsLonM= +golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4= +golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=