diff --git a/2022/day17/main.go b/2022/day17/main.go index e12944f..ff66437 100644 --- a/2022/day17/main.go +++ b/2022/day17/main.go @@ -2,8 +2,7 @@ package main import ( "fmt" - "os" - "time" + "image" h "git.bullercodeworks.com/brian/adventofcode/helpers" ) @@ -26,269 +25,62 @@ var ( func main() { inp := h.StdinToString() - //fmt.Println("# Part 1") - //simulate(inp, 2022) - fmt.Println("# Part 2") - simulate(inp, 1000000000000) -} - -func stateAndSleep(m *h.GrowUpCoordByteMap) { - if !debug { - return + rocks := [][]image.Point{ + {{0, 0}, {1, 0}, {2, 0}, {3, 0}}, + {{1, 2}, {0, 1}, {1, 1}, {2, 1}, {1, 0}}, + {{2, 2}, {2, 1}, {0, 0}, {1, 0}, {2, 0}}, + {{0, 3}, {0, 2}, {0, 1}, {0, 0}}, + {{0, 1}, {1, 1}, {0, 0}, {1, 0}}, } - fmt.Print(h.CLEAR_SCREEN) - //fmt.Println() - fmt.Println(m) - time.Sleep(time.Second / 10) -} - -var cache map[string][]int - -func simulate(jets string, numRocks int) { - cache = make(map[string][]int) - m := h.NewGrowUpCoordByteMap() - m.PutBytes([][]byte{ - bottomRow, emptyRow, emptyRow, emptyRow, emptyRow, - emptyRow, emptyRow, emptyRow, - }, h.Coordinate{X: 0, Y: 0}) - m.StringEmptyIsSpace = true - - jetIdx := 0 - rockType := 0 - var state string - var height int - var turboHeight int - var cacheDisabled bool - for rockNum := 1; rockNum <= numRocks; rockNum++ { - fmt.Println(h.CLEAR_SCREEN) - fmt.Println("Simulating:", rockNum, "/", numRocks) - h.PrintProgress(rockNum, numRocks) - fmt.Println("\nHeight:", height) - if !cacheDisabled { - state, height = GetState(rockType, jetIdx, m) - if v, ok := cache[state]; !cacheDisabled && ok { - // Ok, we've got a duplicate. Go full turbo. - //addHeight := height - mult := numRocks / rockNum - newRockNum := rockNum * mult - turboHeight = height * mult - /* - for rockNum+v[1] <= numRocks { - rockNum = rockNum + v[1] - height = height + addHeight - fmt.Println(h.CLEAR_SCREEN) - fmt.Println("Simulating:", rockNum, "/", numRocks) - h.PrintProgress(rockNum, numRocks) - fmt.Println("\nHeight:", height) - } - */ - fmt.Println(h.CLEAR_SCREEN) - fmt.Println("Simulating:", rockNum, "/", numRocks) - h.PrintProgress(rockNum, numRocks) - fmt.Println("\nHeight:", height) - fmt.Println("State", state, "\nV:", v, "\nMult:", mult, "\nRockNum:", rockNum, "\nNewRockNum:", newRockNum, "\nTurboHeight:", turboHeight) - cacheDisabled = true - os.Exit(0) - } else { - cache[state] = []int{rockNum, height} + grid := map[image.Point]struct{}{} + move := func(rock []image.Point, delta image.Point) bool { + nrock := make([]image.Point, len(rock)) + for i, p := range rock { + p = p.Add(delta) + if _, ok := grid[p]; ok || p.X < 0 || p.X >= 7 || p.Y < 0 { + return false } - } else { - fmt.Println("\nHeight:", turboHeight+GetHeight(m)) + nrock[i] = p + } + copy(rock, nrock) + return true + } + cache := map[[2]int][]int{} + + height, jet := 0, 0 + for i := 0; i < 1000000000000; i++ { + if i == 2022 { + fmt.Println("# Part 1") + fmt.Println(height) + fmt.Println() + } + k := [2]int{i % len(rocks), jet} + if c, ok := cache[k]; ok { + if n, d := 1000000000000-i, i-c[0]; n%d == 0 { + fmt.Println("# Part 2") + fmt.Println(height + n/d*(height-c[1])) + break + } + } + cache[k] = []int{i, height} + + rock := []image.Point{} + for _, p := range rocks[i%len(rocks)] { + rock = append(rock, p.Add(image.Point{2, height + 3})) } - AddFallingRock(rockType, m) - stateAndSleep(m) - doJet := true for { - if !doJet && AtRest(m) { - break - } - shiftDir := dirD - if doJet { - switch jets[jetIdx] { - case '>': - shiftDir = dirR - case '<': - shiftDir = dirL + move(rock, image.Point{int(inp[jet]) - int('='), 0}) + jet = (jet + 1) % len(inp) + + if !move(rock, image.Point{0, -1}) { + for _, p := range rock { + grid[p] = struct{}{} + if p.Y+1 > height { + height = p.Y + 1 + } } - jetIdx = (jetIdx + 1) % len(jets) - } - ShiftRock(shiftDir, m) - stateAndSleep(m) - doJet = !doJet - } - // The falling rock has stopped - StopRock(m) - stateAndSleep(m) - rockType = (rockType + 1) % rocks - } - fmt.Println("After", numRocks, "the tower is", GetHeight(m), "blocks tall") -} - -func GetState(r, j int, m *h.GrowUpCoordByteMap) (string, int) { - ret := fmt.Sprintf("%d;%d;", r, j) - for x := 1; x < 7; x++ { - for y := m.TLY; y > 1; y-- { - if m.Get(h.Coordinate{X: x, Y: y}) == '#' { - ret = fmt.Sprintf("%s-%d", ret, m.TLY-y) break } } } - return ret, GetHeight(m) -} - -func GetHeight(m *h.GrowUpCoordByteMap) int { - return h.GetHighestY(m.FindAll('#')...) -} - -func FindTopAtRestY(m *h.GrowUpCoordByteMap) int { - rockSpots := m.FindAll('#') - if len(rockSpots) != 0 { - return h.GetHighestY(rockSpots...) - } - return 0 -} - -func StopRock(m *h.GrowUpCoordByteMap) { - rockSpots := m.FindAll('@') - for i := range rockSpots { - m.Put(rockSpots[i], '#') - } -} -func ShiftRock(dir int, m *h.GrowUpCoordByteMap) { - if !CanShift(dir, m) { - return - } - - rockSpots := m.FindAll('@') - for i := range rockSpots { - m.Put(rockSpots[i], ' ') - } - for i := range rockSpots { - switch dir { - case dirU: - m.Put(GetUp(rockSpots[i]), '@') - case dirR: - m.Put(GetRight(rockSpots[i]), '@') - case dirD: - m.Put(GetDown(rockSpots[i]), '@') - case dirL: - m.Put(GetLeft(rockSpots[i]), '@') - } - } -} -func CanShift(dir int, m *h.GrowUpCoordByteMap) bool { - rockSpots := m.FindAll('@') - switch dir { - case dirU: // Shouldn't need to, though. - return true - case dirR: - for i := range rockSpots { - tst := m.Get(GetRight(rockSpots[i])) - if tst != '@' && tst != ' ' { - return false - } - } - return true - case dirD: - for i := range rockSpots { - tst := m.Get(GetDown(rockSpots[i])) - if tst != '@' && tst != ' ' { - return false - } - } - return true - case dirL: - for i := range rockSpots { - tst := m.Get(GetLeft(rockSpots[i])) - if tst != '@' && tst != ' ' { - return false - } - } - return true - } - return false -} -func AddFallingRock(tp int, m *h.GrowUpCoordByteMap) { - rock := GetRockBytes(tp) - pos := h.Coordinate{X: 3, Y: FindTopAtRestY(m) + 4} - for pos.Y+3 > m.TLY { - m.PutBytes([][]byte{emptyRow}, h.Coordinate{X: 0, Y: m.TLY + 1}) - } - m.PutBytes(rock, pos) -} -func AtRest(m *h.GrowUpCoordByteMap) bool { - rockSpots := m.FindAll('@') - if len(rockSpots) == 0 { - return true - } - for i := range rockSpots { - pos := GetDown(rockSpots[i]) - wrk := m.Get(pos) - if pos.Y == m.BRY { - return true - } - if wrk != ' ' && wrk != '@' { - return true - } - } - return false -} - -func GetRockBytes(tp int) [][]byte { - switch tp { - case 0: - return [][]byte{{'@', '@', '@', '@'}} - case 1: - return [][]byte{ - {' ', '@', ' '}, - {'@', '@', '@'}, - {' ', '@', ' '}, - } - case 2: - return [][]byte{ - {'@', '@', '@'}, - {' ', ' ', '@'}, - {' ', ' ', '@'}, - } - case 3: - return [][]byte{ - {'@'}, - {'@'}, - {'@'}, - {'@'}, - } - case 4: - return [][]byte{ - {'@', '@'}, - {'@', '@'}, - } - } - return [][]byte{} -} - -func GetLeft(c h.Coordinate) h.Coordinate { - return h.Coordinate{X: c.X - 1, Y: c.Y} -} -func GetRight(c h.Coordinate) h.Coordinate { - return h.Coordinate{X: c.X + 1, Y: c.Y} -} -func GetUp(c h.Coordinate) h.Coordinate { - return h.Coordinate{X: c.X, Y: c.Y + 1} -} -func GetDown(c h.Coordinate) h.Coordinate { - return h.Coordinate{X: c.X, Y: c.Y - 1} -} -func DirToString(shiftDir int) string { - switch shiftDir { - case dirU: - return "^" - case dirR: - return ">" - case dirD: - return "v" - case dirL: - return "<" - } - return " " } diff --git a/2022/day17/problem b/2022/day17/problem index 21d96dd..14ef1e9 100644 --- a/2022/day17/problem +++ b/2022/day17/problem @@ -1,4 +1,4 @@ - Advent of Code + Advent of Code • [About] • [Events] @@ -6,9 +6,9 @@ • [Settings] • [Log Out] - br0xen (AoC++) 32* + br0xen (AoC++) 43* -    sub y{2022} +   {year=>2022} • [Calendar] • [AoC++] @@ -17,20 +17,23 @@ • [Stats] Our sponsors help make Advent of Code possible: - Smarty - Join our private leaderboard and solve our puzzles for BIG PRIZES!!! ----------------- Address Validation - and Autocomplete, and more! + Teradyne - Do you like coding algorithms where milliseconds matter? + What about nanoseconds? --- Day 17: Pyroclastic Flow --- - Your handheld device has located an alternative exit from the cave for you and the elephants. The ground is - rumbling almost continuously now, but the strange valves bought you some time. It's definitely getting warmer in - here, though. + Your handheld device has located an alternative exit from the cave + for you and the elephants. The ground is rumbling almost + continuously now, but the strange valves bought you some time. It's + definitely getting warmer in here, though. - The tunnels eventually open into a very tall, narrow chamber. Large, oddly-shaped rocks are falling into the - chamber from above, presumably due to all the rumbling. If you can't work out where the rocks will fall next, you - might be crushed! + The tunnels eventually open into a very tall, narrow chamber. Large, + oddly-shaped rocks are falling into the chamber from above, + presumably due to all the rumbling. If you can't work out where the + rocks will fall next, you might be crushed! - The five types of rocks have the following peculiar shapes, where # is rock and . is empty space: + The five types of rocks have the following peculiar shapes, where # + is rock and . is empty space: #### @@ -50,31 +53,40 @@ ## ## - The rocks fall in the order shown above: first the - shape, then the + shape, and so on. Once the end of the list - is reached, the same order repeats: the - shape falls first, sixth, 11th, 16th, etc. + The rocks fall in the order shown above: first the - shape, then the + + shape, and so on. Once the end of the list is reached, the same + order repeats: the - shape falls first, sixth, 11th, 16th, etc. - The rocks don't spin, but they do get pushed around by jets of hot gas coming out of the walls themselves. A quick - scan reveals the effect the jets of hot gas will have on the rocks as they fall (your puzzle input). + The rocks don't spin, but they do get pushed around by jets of hot + gas coming out of the walls themselves. A quick scan reveals the + effect the jets of hot gas will have on the rocks as they fall (your + puzzle input). For example, suppose this was the jet pattern in your cave: >>><<><>><<<>><>>><<<>>><<<><<<>><>><<>> - In jet patterns, < means a push to the left, while > means a push to the right. The pattern above means that the - jets will push a falling rock right, then right, then right, then left, then left, then right, and so on. If the - end of the list is reached, it repeats. + In jet patterns, < means a push to the left, while > means a push to + the right. The pattern above means that the jets will push a falling + rock right, then right, then right, then left, then left, then + right, and so on. If the end of the list is reached, it repeats. - The tall, vertical chamber is exactly seven units wide. Each rock appears so that its left edge is two units away - from the left wall and its bottom edge is three units above the highest rock in the room (or the floor, if there - isn't one). + The tall, vertical chamber is exactly seven units wide. Each rock + appears so that its left edge is two units away from the left wall + and its bottom edge is three units above the highest rock in the + room (or the floor, if there isn't one). - After a rock appears, it alternates between being pushed by a jet of hot gas one unit (in the direction indicated - by the next symbol in the jet pattern) and then falling one unit down. If any movement would cause any part of the - rock to move into the walls, floor, or a stopped rock, the movement instead does not occur. If a downward movement - would have caused a falling rock to move into the floor or an already-fallen rock, the falling rock stops where it - is (having landed on something) and a new rock immediately begins falling. + After a rock appears, it alternates between being pushed by a jet of + hot gas one unit (in the direction indicated by the next symbol in + the jet pattern) and then falling one unit down. If any movement + would cause any part of the rock to move into the walls, floor, or a + stopped rock, the movement instead does not occur. If a downward + movement would have caused a falling rock to move into the floor or + an already-fallen rock, the falling rock stops where it is (having + landed on something) and a new rock immediately begins falling. - Drawing falling rocks with @ and stopped rocks with #, the jet pattern in the example above manifests as follows: + Drawing falling rocks with @ and stopped rocks with #, the jet + pattern in the example above manifests as follows: The first rock begins falling: |..@@@@.| @@ -212,7 +224,8 @@ |..####.| +-------+ - The moment each of the next few rocks begins falling, you would see this: + The moment each of the next few rocks begins falling, you would see + this: |..@....| |..@....| @@ -368,15 +381,36 @@ |..####.| +-------+ - To prove to the elephants your simulation is accurate, they want to know how tall the tower will get after 2022 - rocks have stopped (but before the 2023rd rock begins falling). In this example, the tower of rocks will be 3068 - units tall. + To prove to the elephants your simulation is accurate, they want to + know how tall the tower will get after 2022 rocks have stopped (but + before the 2023rd rock begins falling). In this example, the tower + of rocks will be 3068 units tall. - How many units tall will the tower of rocks be after 2022 rocks have stopped falling? + How many units tall will the tower of rocks be after 2022 rocks have + stopped falling? - To begin, get your puzzle input. + Your puzzle answer was 3081. - Answer: _____________________ [ [Submit] ] +--- Part Two --- + + The elephants are not impressed by your simulation. They demand to + know how tall the tower will be after 1000000000000 rocks have + stopped! Only then will they feel confident enough to proceed + through the cave. + + In the example above, the tower would be 1514285714288 units tall! + + How tall will the tower be after 1000000000000 rocks have stopped? + + Your puzzle answer was 1524637681145. + + Both parts of this puzzle are complete! They provide two gold stars: + ** + + At this point, you should return to your Advent calendar and try + another puzzle. + + If you still want to see it, you can get your puzzle input. You can also [Shareon Twitter Mastodon] this puzzle. @@ -398,7 +432,8 @@ References . https://adventofcode.com/2022/leaderboard . https://adventofcode.com/2022/stats . https://adventofcode.com/2022/sponsors - . https://www.smarty.com/advent-of-code + . https://jobs.teradyne.com/?utm_source=adventofcode&utm_medium=ad&utm_campaign=2022 + . https://adventofcode.com/2022 . https://adventofcode.com/2022/day/17/input - . https://twitter.com/intent/tweet?text=%22Pyroclastic+Flow%22+%2D+Day+17+%2D+Advent+of+Code+2022&url=https%3A%2F%2Fadventofcode%2Ecom%2F2022%2Fday%2F17&related=ericwastl&hashtags=AdventOfCode + . https://twitter.com/intent/tweet?text=I%27ve+completed+%22Pyroclastic+Flow%22+%2D+Day+17+%2D+Advent+of+Code+2022&url=https%3A%2F%2Fadventofcode%2Ecom%2F2022%2Fday%2F17&related=ericwastl&hashtags=AdventOfCode . javascript:void(0);