2022 Day 17 Complete
This commit is contained in:
parent
147602a52f
commit
48f30b8e42
@ -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 " "
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user