diff --git a/day22/day22.go b/day22/day22.go index af823f6..4ae8927 100644 --- a/day22/day22.go +++ b/day22/day22.go @@ -105,6 +105,13 @@ func (tower *Tower) layout(brick *Brick, currZ int) { } } } + + brick.start.z = currZ + if brickHeight > 1 { + brick.end.z = currZ + brickHeight - 1 + } else { + brick.end.z = currZ + } } func (tower *Tower) addBrick(brick *Brick) { @@ -137,11 +144,11 @@ func (tower *Tower) addBrick(brick *Brick) { func (tower *Tower) Print() { //for z := tower.maxHeight(); z >= 0; z-- { - for z := 8; z > 0; z-- { + for z := 20; z > 0; z-- { for x := 0; x < tower.floorWidth; x++ { for y := 0; y < tower.floorWidth; y++ { if tower.floors[z][x][y] != nil { - fmt.Print(tower.floors[z][x][y].ID) + fmt.Print(string(byte('A') - 1 + byte(tower.floors[z][x][y].ID)%26)) } else { fmt.Print(".") } @@ -184,3 +191,141 @@ func Part1(lines []string) (int, []*Brick) { tower.Print() return count, bricks } + +/* +func Part2(lines []string) { + // place bricks like Part1 + // and change z coord of each brick once it is layed out + bricks := parseBricks(lines) + tower := NewTower(500, 10) + + for _, brick := range bricks { + fmt.Printf("Placing brick %d (%v)~(%v)\n", brick.ID, brick.start, brick.end) + tower.addBrick(brick) + } + + // sort brick by z coord desc (highest first) + slices.SortFunc(bricks, func(a, b *Brick) int { + return b.start.z - a.start.z + }) + + // for each brick + // if the brick above the current brick has just the current brick as support + // then add 1 + the total fall of the brick above (coming from the map "total fallen") + // Store the value in the map "total fallen" using the ID of the current brick + // end for + count := 0 + for _, brick := range bricks { + for _, aboveBrick := range brick.supports { + if len(aboveBrick.supportedBy) == 0 { + log.Fatalln("Bug ", brick) + } + if len(aboveBrick.supportedBy) == 1 { + // will fall + + } + } + } + +} +*/ + +func buildDropList(brick *Brick, droppedList *map[int]bool) { + // Do not drop if the bricks below have not all been removed + for _, supportedBy := range brick.supportedBy { + if !(*droppedList)[supportedBy.ID] { + return + } + } + + (*droppedList)[brick.ID] = true // the supported brick + + for _, supportedBrick := range brick.supports { + dropAbove := true + for _, supportedBy := range supportedBrick.supportedBy { + if !(*droppedList)[supportedBy.ID] { + dropAbove = false + } + } + if dropAbove { + buildDropList(supportedBrick, droppedList) // the drops from the supported brick + } + } +} + +func Part2(lines []string) int { + bricks := parseBricks(lines) + tower := NewTower(500, 10) + + for _, brick := range bricks { + //fmt.Printf("Placing brick %d (%v)~(%v)\n", brick.ID, brick.start, brick.end) + tower.addBrick(brick) + } + + // for debugging + slices.SortFunc(bricks, func(a, b *Brick) int { + return a.ID - b.ID + }) + + sum := 0 + for _, brick := range bricks { + singleSupport := false + + for _, supportedBrick := range brick.supports { + if len(supportedBrick.supportedBy) == 0 { + log.Fatalln("Bug ", brick) + } + if len(supportedBrick.supportedBy) == 1 { + singleSupport = true + } + } + /* + if singleSupport { + + disintegrated := map[int]bool{brick.ID: true} + checkList := []*Brick{brick} + for len(checkList) > 0 { + // take first from checklist + check := checkList[0] + checkList = checkList[1:] + // for all bricks above, check ... + for _, above := range check.supports { + bricksRemoved := 0 + // whether all bricks below it are disintegrated ... + for _, below := range above.supportedBy { + if disintegrated[below.ID] { + bricksRemoved++ + } + } + if len(above.supportedBy) == bricksRemoved { + // then it would fall + checkList = append(checkList, above) + disintegrated[above.ID] = true + } + } + } + // do not include the brick we are currently checking + fmt.Printf("Brick %d would drop %d other bricks\n", brick.ID, len(disintegrated)-1) + sum += len(disintegrated) - 1 + } + } + */ + + if singleSupport { + dropList := map[int]bool{} + dropList[brick.ID] = true + if brick.ID == 14 { + fmt.Println("debug") + } + for _, supportedBrick := range brick.supports { + buildDropList(supportedBrick, &dropList) + } + fmt.Printf("Brick %d would drop %d other bricks\n", brick.ID, len(dropList)-1) + sum += len(dropList) - 1 + } + } + + tower.Print() + + return sum +} diff --git a/day22/day22_test.go b/day22/day22_test.go index 56b0830..f91575c 100644 --- a/day22/day22_test.go +++ b/day22/day22_test.go @@ -35,3 +35,31 @@ func TestPart1WithInput(t *testing.T) { t.Fatalf("expected 428, got %d", result) } } + +func TestPart2(t *testing.T) { + lines := []string{ + "1,0,1~1,2,1", // 1 + "0,0,2~2,0,2", // 2 + "0,2,3~2,2,3", // 3 + "0,0,4~0,2,4", // 4 + "2,0,5~2,2,5", // 5 + "0,1,6~2,1,6", // 6 + "1,1,8~1,1,9", // 7 + } + + result := Part2(lines) + + if result != 7 { + t.Fatalf("expected 7, got %d", result) + } +} + +func TestPart2WithInput(t *testing.T) { + lines := utils.ReadLines("input.txt") + + result := Part2(lines) + + if result != 35654 { + t.Fatalf("expected 35654, got %d", result) + } +}