2022 Day 17 part 1 Complete

This commit is contained in:
Brian Buller 2022-12-20 15:04:26 -06:00
parent 4abc58d07d
commit c4d5dae456
10 changed files with 1297 additions and 0 deletions

1
2022/day17/input Normal file

File diff suppressed because one or more lines are too long

294
2022/day17/main.go Normal file
View File

@ -0,0 +1,294 @@
package main
import (
"fmt"
"os"
"time"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
const (
dirU = iota
dirR
dirD
dirL
rocks = 5
debug = false
)
var (
emptyRow = []byte{'|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '|'}
bottomRow = []byte{'+', '-', '-', '-', '-', '-', '-', '-', '+'}
)
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
}
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}
}
} else {
fmt.Println("\nHeight:", turboHeight+GetHeight(m))
}
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
}
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 " "
}

404
2022/day17/problem Normal file
View File

@ -0,0 +1,404 @@
Advent of Code
• [About]
• [Events]
• [Shop]
• [Settings]
• [Log Out]
br0xen (AoC++) 32*
   sub y{2022}
• [Calendar]
• [AoC++]
• [Sponsors]
• [Leaderboard]
• [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!
--- 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.
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 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).
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.
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.
Drawing falling rocks with @ and stopped rocks with #, the jet pattern in the example above manifests as follows:
The first rock begins falling:
|..@@@@.|
|.......|
|.......|
|.......|
+-------+
Jet of gas pushes rock right:
|...@@@@|
|.......|
|.......|
|.......|
+-------+
Rock falls 1 unit:
|...@@@@|
|.......|
|.......|
+-------+
Jet of gas pushes rock right, but nothing happens:
|...@@@@|
|.......|
|.......|
+-------+
Rock falls 1 unit:
|...@@@@|
|.......|
+-------+
Jet of gas pushes rock right, but nothing happens:
|...@@@@|
|.......|
+-------+
Rock falls 1 unit:
|...@@@@|
+-------+
Jet of gas pushes rock left:
|..@@@@.|
+-------+
Rock falls 1 unit, causing it to come to rest:
|..####.|
+-------+
A new rock begins falling:
|...@...|
|..@@@..|
|...@...|
|.......|
|.......|
|.......|
|..####.|
+-------+
Jet of gas pushes rock left:
|..@....|
|.@@@...|
|..@....|
|.......|
|.......|
|.......|
|..####.|
+-------+
Rock falls 1 unit:
|..@....|
|.@@@...|
|..@....|
|.......|
|.......|
|..####.|
+-------+
Jet of gas pushes rock right:
|...@...|
|..@@@..|
|...@...|
|.......|
|.......|
|..####.|
+-------+
Rock falls 1 unit:
|...@...|
|..@@@..|
|...@...|
|.......|
|..####.|
+-------+
Jet of gas pushes rock left:
|..@....|
|.@@@...|
|..@....|
|.......|
|..####.|
+-------+
Rock falls 1 unit:
|..@....|
|.@@@...|
|..@....|
|..####.|
+-------+
Jet of gas pushes rock right:
|...@...|
|..@@@..|
|...@...|
|..####.|
+-------+
Rock falls 1 unit, causing it to come to rest:
|...#...|
|..###..|
|...#...|
|..####.|
+-------+
A new rock begins falling:
|....@..|
|....@..|
|..@@@..|
|.......|
|.......|
|.......|
|...#...|
|..###..|
|...#...|
|..####.|
+-------+
The moment each of the next few rocks begins falling, you would see this:
|..@....|
|..@....|
|..@....|
|..@....|
|.......|
|.......|
|.......|
|..#....|
|..#....|
|####...|
|..###..|
|...#...|
|..####.|
+-------+
|..@@...|
|..@@...|
|.......|
|.......|
|.......|
|....#..|
|..#.#..|
|..#.#..|
|#####..|
|..###..|
|...#...|
|..####.|
+-------+
|..@@@@.|
|.......|
|.......|
|.......|
|....##.|
|....##.|
|....#..|
|..#.#..|
|..#.#..|
|#####..|
|..###..|
|...#...|
|..####.|
+-------+
|...@...|
|..@@@..|
|...@...|
|.......|
|.......|
|.......|
|.####..|
|....##.|
|....##.|
|....#..|
|..#.#..|
|..#.#..|
|#####..|
|..###..|
|...#...|
|..####.|
+-------+
|....@..|
|....@..|
|..@@@..|
|.......|
|.......|
|.......|
|..#....|
|.###...|
|..#....|
|.####..|
|....##.|
|....##.|
|....#..|
|..#.#..|
|..#.#..|
|#####..|
|..###..|
|...#...|
|..####.|
+-------+
|..@....|
|..@....|
|..@....|
|..@....|
|.......|
|.......|
|.......|
|.....#.|
|.....#.|
|..####.|
|.###...|
|..#....|
|.####..|
|....##.|
|....##.|
|....#..|
|..#.#..|
|..#.#..|
|#####..|
|..###..|
|...#...|
|..####.|
+-------+
|..@@...|
|..@@...|
|.......|
|.......|
|.......|
|....#..|
|....#..|
|....##.|
|....##.|
|..####.|
|.###...|
|..#....|
|.####..|
|....##.|
|....##.|
|....#..|
|..#.#..|
|..#.#..|
|#####..|
|..###..|
|...#...|
|..####.|
+-------+
|..@@@@.|
|.......|
|.......|
|.......|
|....#..|
|....#..|
|....##.|
|##..##.|
|######.|
|.###...|
|..#....|
|.####..|
|....##.|
|....##.|
|....#..|
|..#.#..|
|..#.#..|
|#####..|
|..###..|
|...#...|
|..####.|
+-------+
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?
To begin, get your puzzle input.
Answer: _____________________ [ [Submit] ]
You can also [Shareon Twitter Mastodon] this puzzle.
References
Visible links
. https://adventofcode.com/
. https://adventofcode.com/2022/about
. https://adventofcode.com/2022/events
. https://teespring.com/stores/advent-of-code
. https://adventofcode.com/2022/settings
. https://adventofcode.com/2022/auth/logout
. Advent of Code Supporter
https://adventofcode.com/2022/support
. https://adventofcode.com/2022
. https://adventofcode.com/2022
. https://adventofcode.com/2022/support
. https://adventofcode.com/2022/sponsors
. https://adventofcode.com/2022/leaderboard
. https://adventofcode.com/2022/stats
. https://adventofcode.com/2022/sponsors
. https://www.smarty.com/advent-of-code
. 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
. javascript:void(0);

1
2022/day17/testinput Normal file
View File

@ -0,0 +1 @@
>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>

30
2022/day19/input Normal file
View File

@ -0,0 +1,30 @@
Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 3 ore and 8 obsidian.
Blueprint 2: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 17 obsidian.
Blueprint 3: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 2 ore and 14 obsidian.
Blueprint 4: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 4 ore and 17 obsidian.
Blueprint 5: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 20 clay. Each geode robot costs 2 ore and 8 obsidian.
Blueprint 6: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 15 clay. Each geode robot costs 2 ore and 20 obsidian.
Blueprint 7: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 17 obsidian.
Blueprint 8: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 13 clay. Each geode robot costs 3 ore and 12 obsidian.
Blueprint 9: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 11 clay. Each geode robot costs 4 ore and 12 obsidian.
Blueprint 10: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 18 clay. Each geode robot costs 2 ore and 19 obsidian.
Blueprint 11: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 14 obsidian.
Blueprint 12: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 15 clay. Each geode robot costs 4 ore and 9 obsidian.
Blueprint 13: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 13 clay. Each geode robot costs 3 ore and 15 obsidian.
Blueprint 14: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 7 clay. Each geode robot costs 2 ore and 14 obsidian.
Blueprint 15: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 4 ore and 20 obsidian.
Blueprint 16: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 15 clay. Each geode robot costs 3 ore and 9 obsidian.
Blueprint 17: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 16 clay. Each geode robot costs 2 ore and 15 obsidian.
Blueprint 18: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 6 clay. Each geode robot costs 2 ore and 14 obsidian.
Blueprint 19: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 13 clay. Each geode robot costs 2 ore and 10 obsidian.
Blueprint 20: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 2 ore and 18 obsidian.
Blueprint 21: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 2 ore and 12 obsidian.
Blueprint 22: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 6 clay. Each geode robot costs 2 ore and 16 obsidian.
Blueprint 23: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 3 ore and 13 obsidian.
Blueprint 24: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 2 ore and 9 obsidian.
Blueprint 25: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 5 clay. Each geode robot costs 3 ore and 18 obsidian.
Blueprint 26: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 2 ore and 10 obsidian.
Blueprint 27: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 8 clay. Each geode robot costs 4 ore and 14 obsidian.
Blueprint 28: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 4 ore and 15 obsidian.
Blueprint 29: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 20 clay. Each geode robot costs 2 ore and 12 obsidian.
Blueprint 30: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 14 clay. Each geode robot costs 4 ore and 10 obsidian.

176
2022/day19/main.go Normal file
View File

@ -0,0 +1,176 @@
package main
import (
"fmt"
"strings"
"time"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
func main() {
fmt.Println()
inp := h.StdinToStringSlice()
part1(inp)
}
func part1(inp []string) {
blueprints := ParseBlueprints(inp)
robots := []Robot{{tp: ResOre}}
var ticks int
resources := make(map[Resource]int)
var done bool
printState(robots, resources)
useBP := blueprints[0]
_ = useBP
// TODO: Get Ratios of needed resources
for !done {
// First check if we can build some bots
if useBP.CanBuild(ResGeode, resources) {
resources = useBP.Build(resGeode, resources)
}
if useBP.CanBuild(ResObsidian, resources) {
resources = useBP.Build(resObsidian, resources)
}
if useBP.CanBuild(ResClay, resources) {
resources = useBP.Build(resClay, resources)
}
// Every tick, each robot gathers one of it's resource
for i := range robots {
resources[robots[i].tp]++
}
ticks++
fmt.Println(h.CLEAR_SCREEN)
printState(robots, resources)
time.Sleep(time.Second / 10)
}
}
func printState(robots []Robot, resources map[Resource]int) {
var oreBots, clayBots, obsBots, geodeBots int
for i := range robots {
switch robots[i].tp {
case ResOre:
oreBots++
case ResClay:
clayBots++
case ResObsidian:
obsBots++
case ResGeode:
geodeBots++
}
}
fmt.Printf(
"Bots: %2d Ore, %2d Clay, %2d Obsidian, %2d Geode\n",
oreBots, clayBots, obsBots, geodeBots)
fmt.Printf("[ Ore : %2d ]\n", resources[ResOre])
fmt.Printf("[ Clay : %2d ]\n", resources[ResClay])
fmt.Printf("[ Obsidian: %2d ]\n", resources[ResObsidian])
fmt.Printf("[ Geode : %2d ]\n", resources[ResGeode])
}
type Resource int
const (
ResOre = iota
ResClay
ResObsidian
ResGeode
ResError
)
type Robot struct {
tp Resource
}
type Cost struct {
res Resource
count int
}
type Blueprint struct {
costs map[Resource][]Cost
}
func (b Blueprint) CanBuild(tp Resource, resources map[Resource]int) bool {
cost := b.costs[tp]
for _, c := range cost {
if resources[c.res] < c.count {
return false
}
}
return true
}
func (b Blueprint) String() string {
ret := fmt.Sprintf("Blueprint contains %d Recipes.\n", len(b.costs))
for _, tp := range []Resource{ResOre, ResClay, ResObsidian, ResGeode} {
if v, ok := b.costs[tp]; ok {
ret = ret + fmt.Sprintf("Each %s robot costs %d %s", tp.String(), v[0].count, v[0].res.String())
if len(v) > 1 {
ret = ret + fmt.Sprintf(" and %d %s", v[1].count, v[1].res.String())
}
ret = ret + ". "
}
}
return ret
}
func ParseBlueprints(inp []string) []Blueprint {
var ret []Blueprint
for i := range inp {
costs := make(map[Resource][]Cost)
wrk := strings.Split(inp[i], ": ")[1]
botReqs := strings.Split(wrk, ".")
for j := range botReqs {
if len(botReqs[j]) > 0 {
fields := strings.Fields(botReqs[j])
bot := ResourceFromString(fields[1])
var req []Cost
req = append(req, Cost{
res: ResourceFromString(fields[5]),
count: h.Atoi(fields[4]),
})
if len(fields) > 6 {
req = append(req, Cost{
res: ResourceFromString(fields[8]),
count: h.Atoi(fields[7]),
})
}
costs[bot] = req
}
}
ret = append(ret, Blueprint{costs: costs})
}
return ret
}
func ResourceFromString(s string) Resource {
switch s {
case "ore":
return ResOre
case "clay":
return ResClay
case "obsidian":
return ResObsidian
case "geode":
return ResGeode
}
return ResError
}
func (r Resource) String() string {
switch r {
case ResOre:
return "ore"
case ResClay:
return "clay"
case ResObsidian:
return "obsidian"
case ResGeode:
return "geode"
}
return "unknown"
}

240
2022/day19/problem Normal file
View File

@ -0,0 +1,240 @@
Advent of Code
• [About]
• [Events]
• [Shop]
• [Settings]
• [Log Out]
br0xen (AoC++) 29*
   0xffff&2022
• [Calendar]
• [AoC++]
• [Sponsors]
• [Leaderboard]
• [Stats]
Our sponsors help make Advent of Code possible:
Kotlin by JetBrains - Trees, lists, packages - itʼs Advent of Code time! Get ready to solve puzzles in Kotlin.
Watch us livestream our discussions about the solutions for the first few puzzles, join our leaderboard, win
prizes. Happy holidays!
--- Day 19: Not Enough Minerals ---
Your scans show that the lava did indeed form obsidian!
The wind has changed direction enough to stop sending lava droplets toward you, so you and the elephants exit
the cave. As you do, you notice a collection of geodes around the pond. Perhaps you could use the obsidian to
create some geode-cracking robots and break them open?
To collect the obsidian from the bottom of the pond, you'll need waterproof obsidian-collecting robots.
Fortunately, there is an abundant amount of clay nearby that you can use to make them waterproof.
In order to harvest the clay, you'll need special-purpose clay-collecting robots. To make any type of robot,
you'll need ore, which is also plentiful but in the opposite direction from the clay.
Collecting ore requires ore-collecting robots with big drills. Fortunately, you have exactly one ore-collecting
robot in your pack that you can use to kickstart the whole operation.
Each robot can collect 1 of its resource type per minute. It also takes one minute for the robot factory (also
conveniently from your pack) to construct any type of robot, although it consumes the necessary resources
available when construction begins.
The robot factory has many blueprints (your puzzle input) you can choose from, but once you've configured it
with a blueprint, you can't change it. You'll need to work out which blueprint is best.
For example:
Blueprint 1:
Each ore robot costs 4 ore.
Each clay robot costs 2 ore.
Each obsidian robot costs 3 ore and 14 clay.
Each geode robot costs 2 ore and 7 obsidian.
Blueprint 2:
Each ore robot costs 2 ore.
Each clay robot costs 3 ore.
Each obsidian robot costs 3 ore and 8 clay.
Each geode robot costs 3 ore and 12 obsidian.
(Blueprints have been line-wrapped here for legibility. The robot factory's actual assortment of blueprints are
provided one blueprint per line.)
The elephants are starting to look hungry, so you shouldn't take too long; you need to figure out which
blueprint would maximize the number of opened geodes after 24 minutes by figuring out which robots to build and
when to build them.
Using blueprint 1 in the example above, the largest number of geodes you could open in 24 minutes is 9. One way
to achieve that is:
== Minute 1 ==
1 ore-collecting robot collects 1 ore; you now have 1 ore.
== Minute 2 ==
1 ore-collecting robot collects 1 ore; you now have 2 ore.
== Minute 3 ==
Spend 2 ore to start building a clay-collecting robot.
1 ore-collecting robot collects 1 ore; you now have 1 ore.
The new clay-collecting robot is ready; you now have 1 of them.
== Minute 4 ==
1 ore-collecting robot collects 1 ore; you now have 2 ore.
1 clay-collecting robot collects 1 clay; you now have 1 clay.
== Minute 5 ==
Spend 2 ore to start building a clay-collecting robot.
1 ore-collecting robot collects 1 ore; you now have 1 ore.
1 clay-collecting robot collects 1 clay; you now have 2 clay.
The new clay-collecting robot is ready; you now have 2 of them.
== Minute 6 ==
1 ore-collecting robot collects 1 ore; you now have 2 ore.
2 clay-collecting robots collect 2 clay; you now have 4 clay.
== Minute 7 ==
Spend 2 ore to start building a clay-collecting robot.
1 ore-collecting robot collects 1 ore; you now have 1 ore.
2 clay-collecting robots collect 2 clay; you now have 6 clay.
The new clay-collecting robot is ready; you now have 3 of them.
== Minute 8 ==
1 ore-collecting robot collects 1 ore; you now have 2 ore.
3 clay-collecting robots collect 3 clay; you now have 9 clay.
== Minute 9 ==
1 ore-collecting robot collects 1 ore; you now have 3 ore.
3 clay-collecting robots collect 3 clay; you now have 12 clay.
== Minute 10 ==
1 ore-collecting robot collects 1 ore; you now have 4 ore.
3 clay-collecting robots collect 3 clay; you now have 15 clay.
== Minute 11 ==
Spend 3 ore and 14 clay to start building an obsidian-collecting robot.
1 ore-collecting robot collects 1 ore; you now have 2 ore.
3 clay-collecting robots collect 3 clay; you now have 4 clay.
The new obsidian-collecting robot is ready; you now have 1 of them.
== Minute 12 ==
Spend 2 ore to start building a clay-collecting robot.
1 ore-collecting robot collects 1 ore; you now have 1 ore.
3 clay-collecting robots collect 3 clay; you now have 7 clay.
1 obsidian-collecting robot collects 1 obsidian; you now have 1 obsidian.
The new clay-collecting robot is ready; you now have 4 of them.
== Minute 13 ==
1 ore-collecting robot collects 1 ore; you now have 2 ore.
4 clay-collecting robots collect 4 clay; you now have 11 clay.
1 obsidian-collecting robot collects 1 obsidian; you now have 2 obsidian.
== Minute 14 ==
1 ore-collecting robot collects 1 ore; you now have 3 ore.
4 clay-collecting robots collect 4 clay; you now have 15 clay.
1 obsidian-collecting robot collects 1 obsidian; you now have 3 obsidian.
== Minute 15 ==
Spend 3 ore and 14 clay to start building an obsidian-collecting robot.
1 ore-collecting robot collects 1 ore; you now have 1 ore.
4 clay-collecting robots collect 4 clay; you now have 5 clay.
1 obsidian-collecting robot collects 1 obsidian; you now have 4 obsidian.
The new obsidian-collecting robot is ready; you now have 2 of them.
== Minute 16 ==
1 ore-collecting robot collects 1 ore; you now have 2 ore.
4 clay-collecting robots collect 4 clay; you now have 9 clay.
2 obsidian-collecting robots collect 2 obsidian; you now have 6 obsidian.
== Minute 17 ==
1 ore-collecting robot collects 1 ore; you now have 3 ore.
4 clay-collecting robots collect 4 clay; you now have 13 clay.
2 obsidian-collecting robots collect 2 obsidian; you now have 8 obsidian.
== Minute 18 ==
Spend 2 ore and 7 obsidian to start building a geode-cracking robot.
1 ore-collecting robot collects 1 ore; you now have 2 ore.
4 clay-collecting robots collect 4 clay; you now have 17 clay.
2 obsidian-collecting robots collect 2 obsidian; you now have 3 obsidian.
The new geode-cracking robot is ready; you now have 1 of them.
== Minute 19 ==
1 ore-collecting robot collects 1 ore; you now have 3 ore.
4 clay-collecting robots collect 4 clay; you now have 21 clay.
2 obsidian-collecting robots collect 2 obsidian; you now have 5 obsidian.
1 geode-cracking robot cracks 1 geode; you now have 1 open geode.
== Minute 20 ==
1 ore-collecting robot collects 1 ore; you now have 4 ore.
4 clay-collecting robots collect 4 clay; you now have 25 clay.
2 obsidian-collecting robots collect 2 obsidian; you now have 7 obsidian.
1 geode-cracking robot cracks 1 geode; you now have 2 open geodes.
== Minute 21 ==
Spend 2 ore and 7 obsidian to start building a geode-cracking robot.
1 ore-collecting robot collects 1 ore; you now have 3 ore.
4 clay-collecting robots collect 4 clay; you now have 29 clay.
2 obsidian-collecting robots collect 2 obsidian; you now have 2 obsidian.
1 geode-cracking robot cracks 1 geode; you now have 3 open geodes.
The new geode-cracking robot is ready; you now have 2 of them.
== Minute 22 ==
1 ore-collecting robot collects 1 ore; you now have 4 ore.
4 clay-collecting robots collect 4 clay; you now have 33 clay.
2 obsidian-collecting robots collect 2 obsidian; you now have 4 obsidian.
2 geode-cracking robots crack 2 geodes; you now have 5 open geodes.
== Minute 23 ==
1 ore-collecting robot collects 1 ore; you now have 5 ore.
4 clay-collecting robots collect 4 clay; you now have 37 clay.
2 obsidian-collecting robots collect 2 obsidian; you now have 6 obsidian.
2 geode-cracking robots crack 2 geodes; you now have 7 open geodes.
== Minute 24 ==
1 ore-collecting robot collects 1 ore; you now have 6 ore.
4 clay-collecting robots collect 4 clay; you now have 41 clay.
2 obsidian-collecting robots collect 2 obsidian; you now have 8 obsidian.
2 geode-cracking robots crack 2 geodes; you now have 9 open geodes.
However, by using blueprint 2 in the example above, you could do even better: the largest number of geodes you
could open in 24 minutes is 12.
Determine the quality level of each blueprint by multiplying that blueprint's ID number with the largest number
of geodes that can be opened in 24 minutes using that blueprint. In this example, the first blueprint has ID 1
and can open 9 geodes, so its quality level is 9. The second blueprint has ID 2 and can open 12 geodes, so its
quality level is 24. Finally, if you add up the quality levels of all of the blueprints in the list, you get
33.
Determine the quality level of each blueprint using the largest number of geodes it could produce in 24
minutes. What do you get if you add up the quality level of all of the blueprints in your list?
To begin, get your puzzle input.
Answer: _____________________ [ [Submit] ]
You can also [Shareon Twitter Mastodon] this puzzle.
References
Visible links
. https://adventofcode.com/
. https://adventofcode.com/2022/about
. https://adventofcode.com/2022/events
. https://teespring.com/stores/advent-of-code
. https://adventofcode.com/2022/settings
. https://adventofcode.com/2022/auth/logout
. Advent of Code Supporter
https://adventofcode.com/2022/support
. https://adventofcode.com/2022
. https://adventofcode.com/2022
. https://adventofcode.com/2022/support
. https://adventofcode.com/2022/sponsors
. https://adventofcode.com/2022/leaderboard
. https://adventofcode.com/2022/stats
. https://adventofcode.com/2022/sponsors
. https://kotlinlang.org/
. https://en.wikipedia.org/wiki/Geode
. https://adventofcode.com/2022/day/19/input
. https://twitter.com/intent/tweet?text=%22Not+Enough+Minerals%22+%2D+Day+19+%2D+Advent+of+Code+2022&url=https%3A%2F%2Fadventofcode%2Ecom%2F2022%2Fday%2F19&related=ericwastl&hashtags=AdventOfCode
. javascript:void(0);

2
2022/day19/testinput Normal file
View File

@ -0,0 +1,2 @@
Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.
Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian.

View File

@ -134,3 +134,40 @@ func (c Coordinate) Adjacent(c2 Coordinate) bool {
c2.Equals(c.West()) ||
c2.Equals(c.NW())
}
func GetHighestY(list ...Coordinate) int {
top := math.MinInt
for i := range list {
if list[i].Y > top {
top = list[i].Y
}
}
return top
}
func GetLowestY(list ...Coordinate) int {
bot := math.MaxInt
for i := range list {
if list[i].Y < bot {
bot = list[i].Y
}
}
return bot
}
func GetLowestX(list ...Coordinate) int {
bot := math.MaxInt
for i := range list {
if list[i].X < bot {
bot = list[i].X
}
}
return bot
}
func GetHighestX(list ...Coordinate) int {
top := math.MinInt
for i := range list {
if list[i].X > top {
top = list[i].X
}
}
return top
}

View File

@ -0,0 +1,112 @@
package aoc
import (
"math"
)
type GrowUpCoordByteMap struct {
Field map[Coordinate]byte
Height int
Width int
// The Top-Left-most X/Y
// (Low X, High Y)
TLX, TLY int
// The Bottom-Right-most X/Y
// (High X, Low Y)
BRX, BRY int
// Options for the 'String' method
StringEmptyIsSpace bool
StringEmptyByte byte
}
func NewGrowUpCoordByteMap() *GrowUpCoordByteMap {
return &GrowUpCoordByteMap{
Field: make(map[Coordinate]byte),
TLX: math.MaxInt,
TLY: math.MinInt,
BRX: math.MinInt,
BRY: math.MaxInt,
StringEmptyByte: ' ',
}
}
func (m *GrowUpCoordByteMap) FindAll(b ...byte) []Coordinate {
var ret []Coordinate
for y := m.TLY; y >= m.BRY; y-- {
for x := m.TLX; x <= m.BRX; x++ {
c := Coordinate{X: x, Y: y}
for i := range b {
if m.Get(c) == b[i] {
ret = append(ret, c)
}
}
}
}
return ret
}
func (m *GrowUpCoordByteMap) Get(pos Coordinate) byte {
if v, ok := m.Field[pos]; ok {
return v
}
return 0
}
func (m *GrowUpCoordByteMap) Opt(pos Coordinate, def byte) byte {
if v, ok := m.Field[pos]; ok {
return v
}
return def
}
func (m *GrowUpCoordByteMap) Put(pos Coordinate, val byte) {
m.Field[pos] = val
m.Measure()
}
func (m *GrowUpCoordByteMap) PutBytes(bytes [][]byte, at Coordinate) {
for y := range bytes {
for x := range bytes[y] {
m.Put(Coordinate{X: at.X + x, Y: at.Y + y}, bytes[y][x])
}
}
m.Measure()
}
func (m *GrowUpCoordByteMap) Delete(pos Coordinate) {
delete(m.Field, pos)
m.Measure()
}
func (m *GrowUpCoordByteMap) Measure() {
m.TLX, m.TLY = math.MaxInt, math.MinInt
m.BRX, m.BRY = math.MinInt, math.MaxInt
for c := range m.Field {
if c.X < m.TLX {
m.TLX = c.X
}
if c.Y < m.BRY {
m.BRY = c.Y
}
if c.X > m.BRX {
m.BRX = c.X
}
if c.Y > m.TLY {
m.TLY = c.Y
}
m.Width = m.BRX - m.TLX + 1
m.Height = m.TLY - m.BRY + 1
}
}
func (m GrowUpCoordByteMap) String() string {
var ret string
for y := m.TLY; y >= m.BRY; y-- {
for x := m.TLX; x <= m.BRX; x++ {
if m.StringEmptyIsSpace {
ret = ret + string(m.Opt(Coordinate{X: x, Y: y}, m.StringEmptyByte))
} else {
ret = ret + string(m.Field[Coordinate{X: x, Y: y}])
}
}
if y > m.BRY {
ret = ret + "\n"
}
}
return ret
}