2022 Day 23 Complete
This commit is contained in:
parent
667c3a4dc9
commit
cdc31b204b
2643
2022/day21/input
Normal file
2643
2022/day21/input
Normal file
File diff suppressed because it is too large
Load Diff
143
2022/day21/main.go
Normal file
143
2022/day21/main.go
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||||
|
)
|
||||||
|
|
||||||
|
var output []string
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
inp := h.StdinToStringSlice()
|
||||||
|
part1(inp)
|
||||||
|
part2(inp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func showLog() {
|
||||||
|
fmt.Println(h.CLEAR_SCREEN)
|
||||||
|
fmt.Println(strings.Join(output, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func setLog(v ...string) {
|
||||||
|
output = []string{}
|
||||||
|
log(v...)
|
||||||
|
}
|
||||||
|
func log(v ...string) {
|
||||||
|
output = append(output, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadMonkeys(inp []string) map[string]*Monkey {
|
||||||
|
monkeys := make(map[string]*Monkey)
|
||||||
|
for _, v := range inp {
|
||||||
|
if len(v) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
m := NewMonkey(strings.Split(v, ": ")...)
|
||||||
|
monkeys[m.name] = m
|
||||||
|
}
|
||||||
|
for _, v := range monkeys {
|
||||||
|
v.init(monkeys, 1)
|
||||||
|
}
|
||||||
|
return monkeys
|
||||||
|
}
|
||||||
|
|
||||||
|
func part1(inp []string) {
|
||||||
|
monkeys := loadMonkeys(inp)
|
||||||
|
log("# Part 1", fmt.Sprintf("%d", monkeys["root"].Value()))
|
||||||
|
showLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
func part2(inp []string) {
|
||||||
|
fmt.Println()
|
||||||
|
monkeys := loadMonkeys(inp)
|
||||||
|
|
||||||
|
m1 := monkeys["root"].inp1 // <- Human is in here
|
||||||
|
m2 := monkeys["root"].inp2 // <- We need to make it match this
|
||||||
|
monkeys["humn"].Value = func() int { return 0 }
|
||||||
|
fmt.Println(m1.Value(), m2.Value())
|
||||||
|
monkeys["humn"].Value = func() int { return 1000 }
|
||||||
|
fmt.Println(m1.Value(), m2.Value())
|
||||||
|
//v := monkeys["root"].Value()
|
||||||
|
|
||||||
|
/*
|
||||||
|
i := 0
|
||||||
|
var lastV int
|
||||||
|
for {
|
||||||
|
monkeys["humn"].Value = func() int {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
v := monkeys["root"].Value()
|
||||||
|
if v == 0 {
|
||||||
|
output = append(output[:1], []string{"# Part 2", fmt.Sprintf("Found: %d", i)}...)
|
||||||
|
showLog()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
output = append(output[:3], []string{
|
||||||
|
"# Part 2",
|
||||||
|
fmt.Sprintf("Scanning... [ humn: %d ]", i),
|
||||||
|
fmt.Sprintf("CURR: %d =? 0", v),
|
||||||
|
fmt.Sprintf("LAST: %d", lastV),
|
||||||
|
}...)
|
||||||
|
setLog(output...)
|
||||||
|
showLog()
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
type Operation int
|
||||||
|
|
||||||
|
const (
|
||||||
|
opAdd = iota
|
||||||
|
opSub
|
||||||
|
opMlt
|
||||||
|
opDiv
|
||||||
|
)
|
||||||
|
|
||||||
|
type Monkey struct {
|
||||||
|
name string
|
||||||
|
op Operation
|
||||||
|
inp1, inp2 *Monkey
|
||||||
|
rawValue string
|
||||||
|
Value func() int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMonkey(inp ...string) *Monkey { return &Monkey{name: inp[0], rawValue: inp[1]} }
|
||||||
|
func (m *Monkey) init(monkeys map[string]*Monkey, part int) {
|
||||||
|
pts := strings.Fields(m.rawValue)
|
||||||
|
if len(pts) == 1 {
|
||||||
|
m.Value = func() int { return h.Atoi(pts[0]) }
|
||||||
|
} else {
|
||||||
|
if part == 2 && m.name == "root" {
|
||||||
|
pts[1] = "-"
|
||||||
|
}
|
||||||
|
m.inp1, m.inp2 = monkeys[pts[0]], monkeys[pts[2]]
|
||||||
|
switch pts[1] {
|
||||||
|
case "+":
|
||||||
|
m.Value = func() int {
|
||||||
|
return m.inp1.Value() + m.inp2.Value()
|
||||||
|
}
|
||||||
|
case "-":
|
||||||
|
m.Value = func() int {
|
||||||
|
return m.inp1.Value() - m.inp2.Value()
|
||||||
|
}
|
||||||
|
case "*":
|
||||||
|
m.Value = func() int {
|
||||||
|
return m.inp1.Value() * m.inp2.Value()
|
||||||
|
}
|
||||||
|
case "/":
|
||||||
|
m.Value = func() int {
|
||||||
|
return m.inp1.Value() / m.inp2.Value()
|
||||||
|
}
|
||||||
|
case "=":
|
||||||
|
m.Value = func() int {
|
||||||
|
if m.inp1.Value() == m.inp2.Value() {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
102
2022/day21/problem
Normal file
102
2022/day21/problem
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
Advent of Code
|
||||||
|
|
||||||
|
• [About]
|
||||||
|
• [Events]
|
||||||
|
• [Shop]
|
||||||
|
• [Settings]
|
||||||
|
• [Log Out]
|
||||||
|
|
||||||
|
br0xen (AoC++) 35*
|
||||||
|
|
||||||
|
/*2022*/
|
||||||
|
|
||||||
|
• [Calendar]
|
||||||
|
• [AoC++]
|
||||||
|
• [Sponsors]
|
||||||
|
• [Leaderboard]
|
||||||
|
• [Stats]
|
||||||
|
|
||||||
|
Our sponsors help make Advent of Code possible:
|
||||||
|
Teradyne - Do you like coding algorithms where milliseconds matter? What about nanoseconds?
|
||||||
|
|
||||||
|
--- Day 21: Monkey Math ---
|
||||||
|
|
||||||
|
The monkeys are back! You're worried they're going to try to steal your stuff again, but it seems like they're just
|
||||||
|
holding their ground and making various monkey noises at you.
|
||||||
|
|
||||||
|
Eventually, one of the elephants realizes you don't speak monkey and comes over to interpret. As it turns out, they
|
||||||
|
overheard you talking about trying to find the grove; they can show you a shortcut if you answer their riddle.
|
||||||
|
|
||||||
|
Each monkey is given a job: either to yell a specific number or to yell the result of a math operation. All of the
|
||||||
|
number-yelling monkeys know their number from the start; however, the math operation monkeys need to wait for two other
|
||||||
|
monkeys to yell a number, and those two other monkeys might also be waiting on other monkeys.
|
||||||
|
|
||||||
|
Your job is to work out the number the monkey named root will yell before the monkeys figure it out themselves.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
root: pppw + sjmn
|
||||||
|
dbpl: 5
|
||||||
|
cczh: sllz + lgvd
|
||||||
|
zczc: 2
|
||||||
|
ptdq: humn - dvpt
|
||||||
|
dvpt: 3
|
||||||
|
lfqf: 4
|
||||||
|
humn: 5
|
||||||
|
ljgn: 2
|
||||||
|
sjmn: drzm * dbpl
|
||||||
|
sllz: 4
|
||||||
|
pppw: cczh / lfqf
|
||||||
|
lgvd: ljgn * ptdq
|
||||||
|
drzm: hmdt - zczc
|
||||||
|
hmdt: 32
|
||||||
|
|
||||||
|
Each line contains the name of a monkey, a colon, and then the job of that monkey:
|
||||||
|
|
||||||
|
• A lone number means the monkey's job is simply to yell that number.
|
||||||
|
• A job like aaaa + bbbb means the monkey waits for monkeys aaaa and bbbb to yell each of their numbers; the monkey
|
||||||
|
then yells the sum of those two numbers.
|
||||||
|
• aaaa - bbbb means the monkey yells aaaa's number minus bbbb's number.
|
||||||
|
• Job aaaa * bbbb will yell aaaa's number multiplied by bbbb's number.
|
||||||
|
• Job aaaa / bbbb will yell aaaa's number divided by bbbb's number.
|
||||||
|
|
||||||
|
So, in the above example, monkey drzm has to wait for monkeys hmdt and zczc to yell their numbers. Fortunately, both
|
||||||
|
hmdt and zczc have jobs that involve simply yelling a single number, so they do this immediately: 32 and 2. Monkey drzm
|
||||||
|
can then yell its number by finding 32 minus 2: 30.
|
||||||
|
|
||||||
|
Then, monkey sjmn has one of its numbers (30, from monkey drzm), and already has its other number, 5, from dbpl. This
|
||||||
|
allows it to yell its own number by finding 30 multiplied by 5: 150.
|
||||||
|
|
||||||
|
This process continues until root yells a number: 152.
|
||||||
|
|
||||||
|
However, your actual situation involves considerably more monkeys. What number will the monkey named root yell?
|
||||||
|
|
||||||
|
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://jobs.teradyne.com/?utm_source=adventofcode&utm_medium=ad&utm_campaign=2022
|
||||||
|
. https://adventofcode.com/2022/day/11
|
||||||
|
. https://adventofcode.com/2022/day/21/input
|
||||||
|
. https://twitter.com/intent/tweet?text=%22Monkey+Math%22+%2D+Day+21+%2D+Advent+of+Code+2022&url=https%3A%2F%2Fadventofcode%2Ecom%2F2022%2Fday%2F21&related=ericwastl&hashtags=AdventOfCode
|
||||||
|
. javascript:void(0);
|
15
2022/day21/testinput
Normal file
15
2022/day21/testinput
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
root: pppw + sjmn
|
||||||
|
dbpl: 5
|
||||||
|
cczh: sllz + lgvd
|
||||||
|
zczc: 2
|
||||||
|
ptdq: humn - dvpt
|
||||||
|
dvpt: 3
|
||||||
|
lfqf: 4
|
||||||
|
humn: 5
|
||||||
|
ljgn: 2
|
||||||
|
sjmn: drzm * dbpl
|
||||||
|
sllz: 4
|
||||||
|
pppw: cczh / lfqf
|
||||||
|
lgvd: ljgn * ptdq
|
||||||
|
drzm: hmdt - zczc
|
||||||
|
hmdt: 32
|
202
2022/day22/input
Normal file
202
2022/day22/input
Normal file
File diff suppressed because one or more lines are too long
308
2022/day22/input-m
Normal file
308
2022/day22/input-m
Normal file
File diff suppressed because one or more lines are too long
422
2022/day22/main.go
Normal file
422
2022/day22/main.go
Normal file
@ -0,0 +1,422 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
|
||||||
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
inp := h.StdinToStringSlice()
|
||||||
|
//part1(inp)
|
||||||
|
part2(inp)
|
||||||
|
}
|
||||||
|
func part1(inp []string) {
|
||||||
|
board, inst := inp[:len(inp)-2], inp[len(inp)-1]
|
||||||
|
b := BuildBoard(board)
|
||||||
|
var count int
|
||||||
|
var turn byte
|
||||||
|
fmt.Println(b)
|
||||||
|
fmt.Println(b.pos)
|
||||||
|
for len(inst) > 0 {
|
||||||
|
count, turn, inst = getNextInstructions(inst)
|
||||||
|
b.Move(count)
|
||||||
|
if turn == 'L' || turn == 'R' {
|
||||||
|
b.Turn(turn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("Password:", b.Password())
|
||||||
|
}
|
||||||
|
|
||||||
|
func part2(inp []string) {
|
||||||
|
board, inst := inp[:len(inp)-2], inp[len(inp)-1]
|
||||||
|
b := BuildCubeBoard(board)
|
||||||
|
var count int
|
||||||
|
var turn byte
|
||||||
|
fmt.Println(b)
|
||||||
|
fmt.Println(b.pos)
|
||||||
|
for len(inst) > 0 {
|
||||||
|
count, turn, inst = getNextInstructions(inst)
|
||||||
|
b.Move(count)
|
||||||
|
if turn == 'L' || turn == 'R' {
|
||||||
|
b.Turn(turn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("Password:", b.Password())
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNextInstructions(inst string) (int, byte, string) {
|
||||||
|
for i := range inst {
|
||||||
|
if inst[i] == 'L' || inst[i] == 'R' {
|
||||||
|
return h.Atoi(inst[:i]), inst[i], inst[i+1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return h.Atoi(inst), 0, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
dirR = iota
|
||||||
|
dirD
|
||||||
|
dirL
|
||||||
|
dirU
|
||||||
|
dirErr
|
||||||
|
|
||||||
|
sideTop = iota
|
||||||
|
sideBottom
|
||||||
|
sideRight
|
||||||
|
sideLeft
|
||||||
|
sideFront
|
||||||
|
sideBack
|
||||||
|
)
|
||||||
|
|
||||||
|
type CubeBoard struct {
|
||||||
|
Top *CubeBoardSide
|
||||||
|
Bottom *CubeBoardSide
|
||||||
|
Left *CubeBoardSide
|
||||||
|
Right *CubeBoardSide
|
||||||
|
Front *CubeBoardSide
|
||||||
|
Back *CubeBoardSide
|
||||||
|
|
||||||
|
// Pos now holds:
|
||||||
|
// y, x, dir, side
|
||||||
|
pos []int
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the purposes of directions, we treat the board like this:
|
||||||
|
// [T]
|
||||||
|
// [B][L][F][R]
|
||||||
|
// [B]
|
||||||
|
// So up from left, front, back, and right are all top
|
||||||
|
// Up from bottom is front
|
||||||
|
// Down from bottom is back
|
||||||
|
// Up from top is back
|
||||||
|
// Down from top is front
|
||||||
|
// So you can continually go left on the main level and circumnavigate the cube
|
||||||
|
// Continually going up from anywhere will eventually get you bouncing between top and back
|
||||||
|
// Continually going down from anywhere will eventually get you bouncing between bottom and back
|
||||||
|
func BuildCubeBoard(inp []string) *CubeBoard {
|
||||||
|
cb := CubeBoard{}
|
||||||
|
var side string
|
||||||
|
for i := 0; i < len(inp); i++ {
|
||||||
|
if len(inp) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
side = inp[i]
|
||||||
|
i++
|
||||||
|
cbs := BuildCubeBoardSide(inp[i : i+len(inp[i])])
|
||||||
|
switch side {
|
||||||
|
case "Top":
|
||||||
|
cb.Top = cbs
|
||||||
|
case "Bottom":
|
||||||
|
cb.Bottom = cbs
|
||||||
|
case "Left":
|
||||||
|
cb.Left = cbs
|
||||||
|
case "Right":
|
||||||
|
cb.Right = cbs
|
||||||
|
case "Front":
|
||||||
|
cb.Front = cbs
|
||||||
|
case "Back":
|
||||||
|
cb.Back = cbs
|
||||||
|
}
|
||||||
|
i = i + cbs.Size() - 1
|
||||||
|
}
|
||||||
|
cb.pos = []int{0, 0, dirR, sideTop}
|
||||||
|
return &cb
|
||||||
|
}
|
||||||
|
func (cb *CubeBoard) Size() int { return cb.Top.Size() }
|
||||||
|
func (cb *CubeBoard) Move(count int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
func (cb *CubeBoard) GetPosUp() []int {
|
||||||
|
y := cb.pos[0]
|
||||||
|
x := cb.pos[1]
|
||||||
|
dir := cb.pos[2]
|
||||||
|
side := cb.pos[3]
|
||||||
|
if y == 0 {
|
||||||
|
// Going to another side
|
||||||
|
switch side {
|
||||||
|
case sideTop:
|
||||||
|
side = sideBack
|
||||||
|
case sideBottom:
|
||||||
|
side = sideFront
|
||||||
|
case sideFront:
|
||||||
|
side = sideTop
|
||||||
|
case sideBack:
|
||||||
|
side = sideTop
|
||||||
|
case sideLeft:
|
||||||
|
side = sideTop
|
||||||
|
case sideRight:
|
||||||
|
side = sideTop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return []int{y, x, dir, side}
|
||||||
|
}
|
||||||
|
func (cb *CubeBoard) GetPosDown() []int {
|
||||||
|
y := cb.pos[0]
|
||||||
|
x := cb.pos[1]
|
||||||
|
dir := cb.pos[2]
|
||||||
|
side := cb.pos[3]
|
||||||
|
if y == cb.Size()-1 {
|
||||||
|
// Going to another side
|
||||||
|
switch side {
|
||||||
|
case sideTop:
|
||||||
|
side = sideFront
|
||||||
|
case sideBottom:
|
||||||
|
side = sideBack
|
||||||
|
case sideFront:
|
||||||
|
side = sideBottom
|
||||||
|
case sideBack:
|
||||||
|
side = sideBottom
|
||||||
|
case sideLeft:
|
||||||
|
side = sideBottom
|
||||||
|
case sideRight:
|
||||||
|
side = sideBottom
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
y = y + 1
|
||||||
|
}
|
||||||
|
return []int{y, x, dir, side}
|
||||||
|
}
|
||||||
|
func (cb *CubeBoard) GetPosRight() []int {
|
||||||
|
y := cb.pos[0]
|
||||||
|
x := cb.pos[1]
|
||||||
|
dir := cb.pos[2]
|
||||||
|
side := cb.pos[3]
|
||||||
|
if x == cb.Size()-1 {
|
||||||
|
// Going to another side
|
||||||
|
switch side {
|
||||||
|
case sideTop:
|
||||||
|
side = sideRight
|
||||||
|
case sideBottom:
|
||||||
|
side = sideRight
|
||||||
|
case sideFront:
|
||||||
|
side = sideRight
|
||||||
|
case sideBack:
|
||||||
|
side = sideLeft
|
||||||
|
case sideLeft:
|
||||||
|
side = sideFront
|
||||||
|
case sideRight:
|
||||||
|
side = sideBack
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
y = y + 1
|
||||||
|
}
|
||||||
|
return []int{y, x, dir, side}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current pos' side
|
||||||
|
func (cb *CubeBoard) Side() *CubeBoardSide {
|
||||||
|
switch cb.pos[3] {
|
||||||
|
case sideTop:
|
||||||
|
return cb.Top
|
||||||
|
case sideBottom:
|
||||||
|
return cb.Bottom
|
||||||
|
case sideFront:
|
||||||
|
return cb.Front
|
||||||
|
case sideBack:
|
||||||
|
return cb.Back
|
||||||
|
case sideLeft:
|
||||||
|
return cb.Left
|
||||||
|
case sideRight:
|
||||||
|
return cb.Right
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (cb *CubeBoard) Turn(dir byte) {
|
||||||
|
if dir == 'R' {
|
||||||
|
cb.pos[2] = (cb.pos[2] + 1) % dirErr
|
||||||
|
} else if dir == 'L' {
|
||||||
|
cb.pos[2] = (cb.pos[2] - 1 + dirErr) % dirErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (cb *CubeBoard) Tile(y, x, side int) byte {
|
||||||
|
switch side {
|
||||||
|
case sideTop:
|
||||||
|
return cb.Top.Tile(y, x)
|
||||||
|
case sideBottom:
|
||||||
|
return cb.Bottom.Tile(y, x)
|
||||||
|
case sideLeft:
|
||||||
|
return cb.Left.Tile(y, x)
|
||||||
|
case sideRight:
|
||||||
|
return cb.Right.Tile(y, x)
|
||||||
|
case sideFront:
|
||||||
|
return cb.Front.Tile(y, x)
|
||||||
|
case sideBack:
|
||||||
|
return cb.Back.Tile(y, x)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
func (cb *CubeBoard) Password() int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type CubeBoardSide struct {
|
||||||
|
spots [][]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildCubeBoardSide(inp []string) *CubeBoardSide {
|
||||||
|
cbs := CubeBoardSide{}
|
||||||
|
fmt.Println("Building CBS from:", inp)
|
||||||
|
cbs.spots = make([][]byte, len(inp))
|
||||||
|
for y := range inp {
|
||||||
|
row := make([]byte, len(inp[y]))
|
||||||
|
for x := range inp[y] {
|
||||||
|
row[x] = inp[y][x]
|
||||||
|
}
|
||||||
|
cbs.spots[y] = row
|
||||||
|
}
|
||||||
|
return &cbs
|
||||||
|
}
|
||||||
|
func (cbs *CubeBoardSide) Size() int {
|
||||||
|
return len(cbs.spots)
|
||||||
|
}
|
||||||
|
func (cbs *CubeBoardSide) Tile(y, x int) byte {
|
||||||
|
if len(cbs.spots) < y && len(cbs.spots[y]) < x {
|
||||||
|
return cbs.spots[y][x]
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type Board struct {
|
||||||
|
spots [][]byte
|
||||||
|
// pos holds
|
||||||
|
// y, x, dir
|
||||||
|
pos []int
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildBoard(inp []string) *Board {
|
||||||
|
maxX := math.MinInt
|
||||||
|
for y := range inp {
|
||||||
|
maxX = h.Max(maxX, len(inp[y]))
|
||||||
|
}
|
||||||
|
b := Board{
|
||||||
|
spots: make([][]byte, len(inp)),
|
||||||
|
}
|
||||||
|
for y := range inp {
|
||||||
|
sl := make([]byte, maxX)
|
||||||
|
for x := range inp[y] {
|
||||||
|
sl[x] = inp[y][x]
|
||||||
|
}
|
||||||
|
b.spots[y] = sl
|
||||||
|
}
|
||||||
|
|
||||||
|
b.pos = make([]int, 3)
|
||||||
|
for x := range b.spots[0] {
|
||||||
|
if b.spots[0][x] == '.' {
|
||||||
|
b.pos = []int{0, x, dirR}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &b
|
||||||
|
}
|
||||||
|
func (b *Board) Password() int {
|
||||||
|
return ((b.pos[0] + 1) * 1000) + ((b.pos[1] + 1) * 4) + b.pos[2]
|
||||||
|
}
|
||||||
|
func (b *Board) Tile(y, x int) byte {
|
||||||
|
if len(b.spots) > y && len(b.spots[y]) > x {
|
||||||
|
return b.spots[y][x]
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
func (b *Board) GetNextPos() []int {
|
||||||
|
switch b.pos[2] {
|
||||||
|
case dirU:
|
||||||
|
return b.GetPosUp()
|
||||||
|
case dirR:
|
||||||
|
return b.GetPosRight()
|
||||||
|
case dirD:
|
||||||
|
return b.GetPosDown()
|
||||||
|
case dirL:
|
||||||
|
return b.GetPosLeft()
|
||||||
|
}
|
||||||
|
return []int{-1, -1}
|
||||||
|
}
|
||||||
|
func (b *Board) GetPosUp() []int {
|
||||||
|
x := b.pos[1]
|
||||||
|
y := ((b.pos[0] - 1) + len(b.spots)) % len(b.spots)
|
||||||
|
for (b.spots[y][x] == 0 || b.spots[y][x] == 32) && y != b.pos[0] {
|
||||||
|
y = ((y - 1) + len(b.spots)) % len(b.spots)
|
||||||
|
}
|
||||||
|
return []int{y, x}
|
||||||
|
}
|
||||||
|
func (b *Board) GetPosRight() []int {
|
||||||
|
y := b.pos[0]
|
||||||
|
x := (b.pos[1] + 1) % len(b.spots[y])
|
||||||
|
for (b.spots[y][x] == 0 || b.spots[y][x] == 32) && x != b.pos[1] {
|
||||||
|
x = (x + 1) % len(b.spots[y])
|
||||||
|
}
|
||||||
|
return []int{y, x}
|
||||||
|
}
|
||||||
|
func (b *Board) GetPosDown() []int {
|
||||||
|
x := b.pos[1]
|
||||||
|
y := (b.pos[0] + 1) % len(b.spots)
|
||||||
|
for (b.spots[y][x] == 0 || b.spots[y][x] == 32) && y != b.pos[0] {
|
||||||
|
y = (y + 1) % len(b.spots)
|
||||||
|
}
|
||||||
|
return []int{y, x}
|
||||||
|
}
|
||||||
|
func (b *Board) GetPosLeft() []int {
|
||||||
|
y := b.pos[0]
|
||||||
|
x := ((b.pos[1] - 1) + len(b.spots[y])) % len(b.spots[y])
|
||||||
|
for (b.spots[y][x] == 0 || b.spots[y][x] == 32) && x != b.pos[1] {
|
||||||
|
x = ((x - 1) + len(b.spots[y])) % len(b.spots[y])
|
||||||
|
}
|
||||||
|
return []int{y, x}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Board) Move(count int) {
|
||||||
|
var to []int
|
||||||
|
for count > 0 {
|
||||||
|
switch b.pos[2] {
|
||||||
|
case dirU:
|
||||||
|
to = b.GetPosUp()
|
||||||
|
case dirR:
|
||||||
|
to = b.GetPosRight()
|
||||||
|
case dirD:
|
||||||
|
to = b.GetPosDown()
|
||||||
|
case dirL:
|
||||||
|
to = b.GetPosLeft()
|
||||||
|
}
|
||||||
|
if b.Tile(to[0], to[1]) == '.' {
|
||||||
|
count--
|
||||||
|
b.pos[0], b.pos[1] = to[0], to[1]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Board) Turn(dir byte) {
|
||||||
|
if dir == 'R' {
|
||||||
|
b.pos[2] = (b.pos[2] + 1) % dirErr
|
||||||
|
} else if dir == 'L' {
|
||||||
|
b.pos[2] = (b.pos[2] - 1 + dirErr) % dirErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Board) String() string {
|
||||||
|
var ret string
|
||||||
|
for y := range b.spots {
|
||||||
|
for x := range b.spots[y] {
|
||||||
|
bt := b.spots[y][x]
|
||||||
|
if b.pos[1] == x && b.pos[0] == y {
|
||||||
|
switch b.pos[2] {
|
||||||
|
case dirU:
|
||||||
|
bt = '^'
|
||||||
|
case dirR:
|
||||||
|
bt = '>'
|
||||||
|
case dirD:
|
||||||
|
bt = 'v'
|
||||||
|
case dirL:
|
||||||
|
bt = '<'
|
||||||
|
default:
|
||||||
|
bt = '!'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = ret + fmt.Sprint(string(bt))
|
||||||
|
}
|
||||||
|
ret = ret + "\n"
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
156
2022/day22/problem
Normal file
156
2022/day22/problem
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
Advent of Code
|
||||||
|
|
||||||
|
• [About]
|
||||||
|
• [Events]
|
||||||
|
• [Shop]
|
||||||
|
• [Settings]
|
||||||
|
• [Log Out]
|
||||||
|
|
||||||
|
br0xen (AoC++) 36*
|
||||||
|
|
||||||
|
var y=2022;
|
||||||
|
|
||||||
|
• [Calendar]
|
||||||
|
• [AoC++]
|
||||||
|
• [Sponsors]
|
||||||
|
• [Leaderboard]
|
||||||
|
• [Stats]
|
||||||
|
|
||||||
|
Our sponsors help make Advent of Code possible:
|
||||||
|
Infi - De kerstman wil weer cadeaus bezorgen maar komt tot de ontdekking dat zijn
|
||||||
|
Kerstman Positioning System (KPS) niet meer werkt. Kan jij hem helpen?
|
||||||
|
|
||||||
|
--- Day 22: Monkey Map ---
|
||||||
|
|
||||||
|
The monkeys take you on a surprisingly easy trail through the jungle. They're even
|
||||||
|
going in roughly the right direction according to your handheld device's Grove
|
||||||
|
Positioning System.
|
||||||
|
|
||||||
|
As you walk, the monkeys explain that the grove is protected by a force field. To pass
|
||||||
|
through the force field, you have to enter a password; doing so involves tracing a
|
||||||
|
specific path on a strangely-shaped board.
|
||||||
|
|
||||||
|
At least, you're pretty sure that's what you have to do; the elephants aren't exactly
|
||||||
|
fluent in monkey.
|
||||||
|
|
||||||
|
The monkeys give you notes that they took when they last saw the password entered
|
||||||
|
(your puzzle input).
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
...#
|
||||||
|
.#..
|
||||||
|
#...
|
||||||
|
....
|
||||||
|
...#.......#
|
||||||
|
........#...
|
||||||
|
..#....#....
|
||||||
|
..........#.
|
||||||
|
...#....
|
||||||
|
.....#..
|
||||||
|
.#......
|
||||||
|
......#.
|
||||||
|
|
||||||
|
10R5L5R10L4R5L5
|
||||||
|
|
||||||
|
The first half of the monkeys' notes is a map of the board. It is comprised of a set
|
||||||
|
of open tiles (on which you can move, drawn .) and solid walls (tiles which you cannot
|
||||||
|
enter, drawn #).
|
||||||
|
|
||||||
|
The second half is a description of the path you must follow. It consists of
|
||||||
|
alternating numbers and letters:
|
||||||
|
|
||||||
|
• A number indicates the number of tiles to move in the direction you are facing. If
|
||||||
|
you run into a wall, you stop moving forward and continue with the next
|
||||||
|
instruction.
|
||||||
|
• A letter indicates whether to turn 90 degrees clockwise (R) or counterclockwise
|
||||||
|
(L). Turning happens in-place; it does not change your current tile.
|
||||||
|
|
||||||
|
So, a path like 10R5 means "go forward 10 tiles, then turn clockwise 90 degrees, then
|
||||||
|
go forward 5 tiles".
|
||||||
|
|
||||||
|
You begin the path in the leftmost open tile of the top row of tiles. Initially, you
|
||||||
|
are facing to the right (from the perspective of how the map is drawn).
|
||||||
|
|
||||||
|
If a movement instruction would take you off of the map, you wrap around to the other
|
||||||
|
side of the board. In other words, if your next tile is off of the board, you should
|
||||||
|
instead look in the direction opposite of your current facing as far as you can until
|
||||||
|
you find the opposite edge of the board, then reappear there.
|
||||||
|
|
||||||
|
For example, if you are at A and facing to the right, the tile in front of you is
|
||||||
|
marked B; if you are at C and facing down, the tile in front of you is marked D:
|
||||||
|
|
||||||
|
...#
|
||||||
|
.#..
|
||||||
|
#...
|
||||||
|
....
|
||||||
|
...#.D.....#
|
||||||
|
........#...
|
||||||
|
B.#....#...A
|
||||||
|
.....C....#.
|
||||||
|
...#....
|
||||||
|
.....#..
|
||||||
|
.#......
|
||||||
|
......#.
|
||||||
|
|
||||||
|
It is possible for the next tile (after wrapping around) to be a wall; this still
|
||||||
|
counts as there being a wall in front of you, and so movement stops before you
|
||||||
|
actually wrap to the other side of the board.
|
||||||
|
|
||||||
|
By drawing the last facing you had with an arrow on each tile you visit, the full path
|
||||||
|
taken by the above example looks like this:
|
||||||
|
|
||||||
|
>>v#
|
||||||
|
.#v.
|
||||||
|
#.v.
|
||||||
|
..v.
|
||||||
|
...#...v..v#
|
||||||
|
>>>v...>#.>>
|
||||||
|
..#v...#....
|
||||||
|
...>>>>v..#.
|
||||||
|
...#....
|
||||||
|
.....#..
|
||||||
|
.#......
|
||||||
|
......#.
|
||||||
|
|
||||||
|
To finish providing the password to this strange input device, you need to determine
|
||||||
|
numbers for your final row, column, and facing as your final position appears from the
|
||||||
|
perspective of the original map. Rows start from 1 at the top and count downward;
|
||||||
|
columns start from 1 at the left and count rightward. (In the above example, row 1,
|
||||||
|
column 1 refers to the empty space with no tile on it in the top-left corner.) Facing
|
||||||
|
is 0 for right (>), 1 for down (v), 2 for left (<), and 3 for up (^). The final
|
||||||
|
password is the sum of 1000 times the row, 4 times the column, and the facing.
|
||||||
|
|
||||||
|
In the above example, the final row is 6, the final column is 8, and the final facing
|
||||||
|
is 0. So, the final password is 1000 * 6 + 4 * 8 + 0: 6032.
|
||||||
|
|
||||||
|
Follow the path given in the monkeys' notes. What is the final password?
|
||||||
|
|
||||||
|
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://aoc.infi.nl/?mtm_campaign=aoc2022&mtm_source=aoc
|
||||||
|
. https://adventofcode.com/2022/day/22/input
|
||||||
|
. https://twitter.com/intent/tweet?text=%22Monkey+Map%22+%2D+Day+22+%2D+Advent+of+Code+2022&url=https%3A%2F%2Fadventofcode%2Ecom%2F2022%2Fday%2F22&related=ericwastl&hashtags=AdventOfCode
|
||||||
|
. javascript:void(0);
|
14
2022/day22/testinput
Normal file
14
2022/day22/testinput
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
...#
|
||||||
|
.#..
|
||||||
|
#...
|
||||||
|
....
|
||||||
|
...#.......#
|
||||||
|
........#...
|
||||||
|
..#....#....
|
||||||
|
..........#.
|
||||||
|
...#....
|
||||||
|
.....#..
|
||||||
|
.#......
|
||||||
|
......#.
|
||||||
|
|
||||||
|
10R5L5R10L4R5L5
|
32
2022/day22/testinput-m
Normal file
32
2022/day22/testinput-m
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
Top
|
||||||
|
...#
|
||||||
|
.#..
|
||||||
|
#...
|
||||||
|
....
|
||||||
|
Back
|
||||||
|
...#
|
||||||
|
....
|
||||||
|
..#.
|
||||||
|
....
|
||||||
|
Left
|
||||||
|
....
|
||||||
|
....
|
||||||
|
...#
|
||||||
|
....
|
||||||
|
Front
|
||||||
|
...#
|
||||||
|
#...
|
||||||
|
....
|
||||||
|
..#.
|
||||||
|
Bottom
|
||||||
|
...#
|
||||||
|
....
|
||||||
|
.#..
|
||||||
|
....
|
||||||
|
Right
|
||||||
|
....
|
||||||
|
.#..
|
||||||
|
....
|
||||||
|
..#.
|
||||||
|
|
||||||
|
10R5L5R10L4R5L5
|
73
2022/day23/input
Normal file
73
2022/day23/input
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
.#.###...###....##..####.#.###.####.#..##......#.####.###.###...#.####.##
|
||||||
|
.#...#.####.##.#.#.#####.#.#.....#...#.####.#..#.###.###....##.#.###.#...
|
||||||
|
.....#..#........###.##.......###..#.....#####......###.#.#.####..#...#.#
|
||||||
|
.##.##.#.####....###.#..###..#########..##....#..##..#.##.#....#.#.##.#.#
|
||||||
|
..#..##...#.#..##.#...###.#.#..#...#....####.##.##...#.###.###...##..#.#.
|
||||||
|
###.###....#.##.#...#.##.##.##..###.#.#..##...###.###...###.#.#..#.######
|
||||||
|
.#.#####..#.####.###..##.#.#.#.#.#.#...##.####.#..#.#####.#..#....#.#..#.
|
||||||
|
..######.##.#.##.###..#.#.#.#.##..###.######..#.......######.#.##.##..#.#
|
||||||
|
#####......#.......######.#####.###..###......#..#..###.....#.#####......
|
||||||
|
##...#.#..###.#######.###.##########...#...#.##.#..#..##.#...#.##....##..
|
||||||
|
####.#...######....##..#.###.#...#.#.#..########...#..#######.####.#.#.##
|
||||||
|
#....###..#.##..###.....#.#####...#.##....###..##.#..##..#....###......#.
|
||||||
|
##.#..#.##.#.####...#.....##.##.#.#.######.#.###.....##..#......#..##.#..
|
||||||
|
.......#.#####.#..#.##.#....##..#.##.#..#..#.###.#.##...#..#.##.#..#.....
|
||||||
|
#.#..#...#..####.#.#.###..###..#######.#...#....##..###...#...##.###.###.
|
||||||
|
#.#..#..#...##..#.#...#..#.#.#..#.#..#####......##..##.#...#.#.###....##.
|
||||||
|
#..#...##.#.#.#....##......##...#.###.#..#..#...#.###.####.#.##..##....#.
|
||||||
|
###.#..#.#.##..#.##......#...####.....##...#.#......##..######.#.#..#..#.
|
||||||
|
.......#.######...##..#....#.#...##......#.....#..###.######.#...#.####.#
|
||||||
|
...##.....#....#.##.##.########.#..#....#####.######....##.###...#.#.##..
|
||||||
|
##...##..#...#.#..#..#.#.##.###.########..##...#..##....##..##..#####..##
|
||||||
|
##..#####..#.####..##...#.##..##.##..#....####..####..#.########.#######.
|
||||||
|
.#.#.######..#.##.###.#.#...#.#...###..#.##.#####.##.####.#...####.##.###
|
||||||
|
##.#..#.#####.#....#..##...##..##.###..#.#....#.##....###.....#..##.##..#
|
||||||
|
##.##.#..##.###.#.##.#..###...##.##...##.###...####.###...#.####.#.....#.
|
||||||
|
.#.##..#####..#..#.....#####.#.#.###.#.#.####.##....##..#..##.####.###...
|
||||||
|
.#...#.#.######.#....##.##.#.##...#..#.##....##...#.##.....###.#......###
|
||||||
|
##....###.##.###.##.###..##...####..#..#####..##..........##.....#.#.#..#
|
||||||
|
..#####.##.#...#......#..###..#...##..#.###....##.##.##.####.#.##.###..##
|
||||||
|
##.##..#####..####..#..##.#....##...#..####..######...##..##.#.###.#.##.#
|
||||||
|
.#.#..#...######.###..##.#......##.##..#.##.##..#.##.#.#.###.##..###....#
|
||||||
|
..###.#...#......#.#.#........#.#######..#.#.######..##.#...###.##.#....#
|
||||||
|
#..####.....#.#.#.#.###...#..##.#.#.##.#.#...###.#.#.#.#####..#.##.###..#
|
||||||
|
##...####.....#....#.####.#....#...####.########..#....######.#..##..#.##
|
||||||
|
.#.#.##...########.#######.......##......###..#....########..#......#..##
|
||||||
|
.##......#..#######..#....#..##.#.####..##.#.#..##..##..#######..###.#.#.
|
||||||
|
..##.######...##..#.#.##...##.###.##.##....##.#...#..#..#..###.####......
|
||||||
|
.#.###.###.#..###..#.#.##.#..##.#.#..#.####.#.#...##.#####.#.##..#..##.#.
|
||||||
|
.#..#........#..#..#.#..####.#.#....#.#.#.#...##...####..##.##.##.#.##.#.
|
||||||
|
##...#.#.#.###...#....###..####.##..##.##..#.#####.##....#..##.########.#
|
||||||
|
.#.#..##.#.####..#..#...#.######...###.#.#####.###.##.##..............##.
|
||||||
|
.....###.#..###.#.##...#.#.####..##.#####.##..#.###.##.....#..##.#.#.#.#.
|
||||||
|
##.#...###.#.#.###.#...#....#.#.....#.#..#.#..###.##.#...##..#####.#..#..
|
||||||
|
.###....#######.##.#..#####.#.#.##.#..###.#.#.###.#.#.###...#.##.....###.
|
||||||
|
##.#.#.#...#...#.#...#.....##..###..#......#.#.###.#.#.##.##..####.####..
|
||||||
|
#.###.#####.#####....#..###..####.###.#####..##.....#.#####.###...#..#.#.
|
||||||
|
.#..#..#..##..####.######...#...#.#.#.#....#.#......###...###.....#..###.
|
||||||
|
#..####.##.#.#..##..#####.###..#.######.##..####.........##.....##..#.#..
|
||||||
|
#..#.#..##.#.#..##..##.#.#.#.#..#.#....#.#.###.#.#.##.#.#.#..###..#...###
|
||||||
|
##....###.##..#..##.##.#.##.#.....#...###.######....#.##.##.#..##.##...##
|
||||||
|
.#..#....#...#.###..########.#...#..#.#.###.#.###...#..#.#..##.###.##..##
|
||||||
|
#.#.##.##.#...######.#...#...###.###.##...###.#..#.##...#.###.###.##.#.##
|
||||||
|
.....#..##..##.####..##..#.###.#######.#...##..#...#####..##...####......
|
||||||
|
#.#####..##...#.##...#.#...##....######.#.#####...#.....#.#..#.#...#..#..
|
||||||
|
#####.####.####.#..#.####..##..###.######..##.###..####.#...#.#.###....#.
|
||||||
|
###..#.##.#######.#.#.#.#......###.#.##..##.##.##..#.#....#..####......#.
|
||||||
|
.....#..#..#..###...#.###..####.#...###...######.#.##....###.##..#..#..#.
|
||||||
|
#.#..##..##.##...#.###.#.###.#####.#.#.####.###.##.####..##.###..#.#####.
|
||||||
|
.###....#...#.##.####.#.....####..#.##..##..##.##.#.##.##..###.###.#..#..
|
||||||
|
..#.###.....#...##..###.##....###..####.#.##.###.####.##.#.##.#...#.#####
|
||||||
|
.##.#..#....#..##.###..#..#.#..####.##.#...#.......###.#...#.##......#.#.
|
||||||
|
......###.##########..###.##..#...#....#....#.####....##.#.#.##.##......#
|
||||||
|
#.#.####..#.#..##..##......##..#####..##.#.#.###........#.#..#.#####.#.#.
|
||||||
|
#...###..#...##..#.#.##..#.#..#..#.##..#.#...#####..#.#.###.##.#..##.#.#.
|
||||||
|
..#.###.###..###..#.#.#.##.###.#####......#.###...##.#.##.###.##.##.#####
|
||||||
|
....###..##.#.##....#..###.#.##.###.#....#.##...#...####.#.#..##..##.#.#.
|
||||||
|
#..#.###.###.######.#.##.#..#.#.#...#..#........##..#...##.###.#.##.#...#
|
||||||
|
####...###...#.###.#..#.#.#..#.#..##....#.##.#..#.##.#..#.###.#.##.####..
|
||||||
|
.#####....##.#..##.....##.#..#......#..##..#.....#..#.###.#.#.###...###.#
|
||||||
|
.#........#.....###.####..##....##.##....####.##.#####...##..#........#..
|
||||||
|
...#####.#.####.#.#....#..##.#..#.#.##....###....#..#..#...##.#.##.##...#
|
||||||
|
#...##..#.####.####.##.##.###.##....#...#.####..##.#.......#..#.###..#..#
|
||||||
|
.##...#####..####..#.###.##..##.#.#...#....#.#..####..##...#.....#.##.##.
|
201
2022/day23/main.go
Normal file
201
2022/day23/main.go
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
inp := h.StdinToStringSlice()
|
||||||
|
part1(inp)
|
||||||
|
part2(inp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func part1(inp []string) {
|
||||||
|
field := plotElves(inp)
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
proposals := buildProposals(field, i)
|
||||||
|
for k, v := range proposals {
|
||||||
|
delete(field, v)
|
||||||
|
field[k] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("# Part 1")
|
||||||
|
fmt.Println("Empty Tiles:", countEmpties(field))
|
||||||
|
}
|
||||||
|
func part2(inp []string) {
|
||||||
|
field := plotElves(inp)
|
||||||
|
var lastHash string
|
||||||
|
for i := 0; i < 100000000; i++ {
|
||||||
|
proposals := buildProposals(field, i)
|
||||||
|
for k, v := range proposals {
|
||||||
|
delete(field, v)
|
||||||
|
field[k] = true
|
||||||
|
}
|
||||||
|
currHash := fieldHash(field)
|
||||||
|
if currHash == lastHash {
|
||||||
|
fmt.Println("# Part 2")
|
||||||
|
fmt.Println("Stable on round", i+1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lastHash = currHash
|
||||||
|
}
|
||||||
|
fmt.Println("# Part 2")
|
||||||
|
fmt.Println("No solution found.")
|
||||||
|
}
|
||||||
|
func fieldHash(field map[h.Coordinate]bool) string {
|
||||||
|
var sorted []h.Coordinate
|
||||||
|
for k := range field {
|
||||||
|
sorted = append(sorted, k)
|
||||||
|
}
|
||||||
|
sort.Slice(sorted, func(i, j int) bool {
|
||||||
|
if sorted[i].X == sorted[j].X {
|
||||||
|
return sorted[i].Y > sorted[j].Y
|
||||||
|
}
|
||||||
|
return sorted[i].X > sorted[j].X
|
||||||
|
})
|
||||||
|
return fmt.Sprintf("%v", sorted)
|
||||||
|
}
|
||||||
|
|
||||||
|
func countEmpties(field map[h.Coordinate]bool) int {
|
||||||
|
maxX, minX := math.MinInt, math.MaxInt
|
||||||
|
maxY, minY := math.MinInt, math.MaxInt
|
||||||
|
for k := range field {
|
||||||
|
maxX = h.Max(maxX, k.X)
|
||||||
|
minX = h.Min(minX, k.X)
|
||||||
|
maxY = h.Max(maxY, k.Y)
|
||||||
|
minY = h.Min(minY, k.Y)
|
||||||
|
}
|
||||||
|
var ret int
|
||||||
|
for y := minY; y <= maxY; y++ {
|
||||||
|
for x := minX; x <= maxX; x++ {
|
||||||
|
if _, ok := field[h.Coordinate{X: x, Y: y}]; !ok {
|
||||||
|
ret++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
func printField(field map[h.Coordinate]bool) {
|
||||||
|
maxX, minX := math.MinInt, 0
|
||||||
|
maxY, minY := math.MinInt, 0
|
||||||
|
for k := range field {
|
||||||
|
maxX = h.Max(maxX, k.X)
|
||||||
|
minX = h.Min(minX, k.X)
|
||||||
|
maxY = h.Max(maxY, k.Y)
|
||||||
|
minY = h.Min(minY, k.Y)
|
||||||
|
}
|
||||||
|
maxX = maxX + 2
|
||||||
|
maxY = maxY + 2
|
||||||
|
for y := minY; y <= maxY; y++ {
|
||||||
|
for x := minX; x <= maxX; x++ {
|
||||||
|
if _, ok := field[h.Coordinate{X: x, Y: y}]; ok {
|
||||||
|
fmt.Print("#")
|
||||||
|
} else {
|
||||||
|
fmt.Print(".")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func plotElves(inp []string) map[h.Coordinate]bool {
|
||||||
|
field := make(map[h.Coordinate]bool)
|
||||||
|
for y := range inp {
|
||||||
|
for x := range inp[y] {
|
||||||
|
if inp[y][x] == '#' {
|
||||||
|
field[h.Coordinate{X: x, Y: y}] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return field
|
||||||
|
}
|
||||||
|
func buildProposals(field map[h.Coordinate]bool, round int) map[h.Coordinate]h.Coordinate {
|
||||||
|
props := make(map[h.Coordinate]h.Coordinate)
|
||||||
|
var errProps []h.Coordinate
|
||||||
|
for k := range field {
|
||||||
|
var neighbors []h.Coordinate
|
||||||
|
for _, n := range k.GetAllNeighbors() {
|
||||||
|
if _, ok := field[n]; ok {
|
||||||
|
neighbors = append(neighbors, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(neighbors) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var hasNorth, hasEast, hasSouth, hasWest bool
|
||||||
|
for _, n := range neighbors {
|
||||||
|
if n.Y < k.Y {
|
||||||
|
hasNorth = true
|
||||||
|
}
|
||||||
|
if n.Y > k.Y {
|
||||||
|
hasSouth = true
|
||||||
|
}
|
||||||
|
if n.X < k.X {
|
||||||
|
hasWest = true
|
||||||
|
}
|
||||||
|
if n.X > k.X {
|
||||||
|
hasEast = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addProp := func(c h.Coordinate) {
|
||||||
|
if _, ok := props[c]; ok {
|
||||||
|
errProps = append(errProps, c)
|
||||||
|
} else {
|
||||||
|
props[c] = k
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testNorth := func(c h.Coordinate) bool {
|
||||||
|
if !hasNorth {
|
||||||
|
addProp(k.North())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
testSouth := func(c h.Coordinate) bool {
|
||||||
|
if !hasSouth {
|
||||||
|
addProp(k.South())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
testWest := func(c h.Coordinate) bool {
|
||||||
|
if !hasWest {
|
||||||
|
addProp(k.West())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
testEast := func(c h.Coordinate) bool {
|
||||||
|
if !hasEast {
|
||||||
|
addProp(k.East())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
findProposal := func(c h.Coordinate, tests ...func(h.Coordinate) bool) {
|
||||||
|
for i := range tests {
|
||||||
|
if tests[i](c) == true {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch round % 4 {
|
||||||
|
case 0: // North First
|
||||||
|
findProposal(k, testNorth, testSouth, testWest, testEast)
|
||||||
|
case 1: // South First
|
||||||
|
findProposal(k, testSouth, testWest, testEast, testNorth)
|
||||||
|
case 2: // West First
|
||||||
|
findProposal(k, testWest, testEast, testNorth, testSouth)
|
||||||
|
case 3: // East First
|
||||||
|
findProposal(k, testEast, testNorth, testSouth, testWest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Now remove all conflicts
|
||||||
|
for i := range errProps {
|
||||||
|
delete(props, errProps[i])
|
||||||
|
}
|
||||||
|
return props
|
||||||
|
}
|
299
2022/day23/problem
Normal file
299
2022/day23/problem
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
Advent of Code
|
||||||
|
br0xen (AoC++) 39*
|
||||||
|
|
||||||
|
--- Day 23: Unstable Diffusion ---
|
||||||
|
|
||||||
|
You enter a large crater of gray dirt where the grove is supposed to be. All around
|
||||||
|
you, plants you imagine were expected to be full of fruit are instead withered and
|
||||||
|
broken. A large group of Elves has formed in the middle of the grove.
|
||||||
|
|
||||||
|
"...but this volcano has been dormant for months. Without ash, the fruit can't grow!"
|
||||||
|
|
||||||
|
You look up to see a massive, snow-capped mountain towering above you.
|
||||||
|
|
||||||
|
"It's not like there are other active volcanoes here; we've looked everywhere."
|
||||||
|
|
||||||
|
"But our scanners show active magma flows; clearly it's going somewhere."
|
||||||
|
|
||||||
|
They finally notice you at the edge of the grove, your pack almost overflowing from
|
||||||
|
the random star fruit you've been collecting. Behind you, elephants and monkeys
|
||||||
|
explore the grove, looking concerned. Then, the Elves recognize the ash cloud slowly
|
||||||
|
spreading above your recent detour.
|
||||||
|
|
||||||
|
"Why do you--" "How is--" "Did you just--"
|
||||||
|
|
||||||
|
Before any of them can form a complete question, another Elf speaks up: "Okay, new
|
||||||
|
plan. We have almost enough fruit already, and ash from the plume should spread here
|
||||||
|
eventually. If we quickly plant new seedlings now, we can still make it to the
|
||||||
|
extraction point. Spread out!"
|
||||||
|
|
||||||
|
The Elves each reach into their pack and pull out a tiny plant. The plants rely on
|
||||||
|
important nutrients from the ash, so they can't be planted too close together.
|
||||||
|
|
||||||
|
There isn't enough time to let the Elves figure out where to plant the seedlings
|
||||||
|
themselves; you quickly scan the grove (your puzzle input) and note their positions.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
....#..
|
||||||
|
..###.#
|
||||||
|
#...#.#
|
||||||
|
.#...##
|
||||||
|
#.###..
|
||||||
|
##.#.##
|
||||||
|
.#..#..
|
||||||
|
|
||||||
|
The scan shows Elves # and empty ground .; outside your scan, more empty ground
|
||||||
|
extends a long way in every direction. The scan is oriented so that north is up;
|
||||||
|
orthogonal directions are written N (north), S (south), W (west), and E (east), while
|
||||||
|
diagonal directions are written NE, NW, SE, SW.
|
||||||
|
|
||||||
|
The Elves follow a time-consuming process to figure out where they should each go; you
|
||||||
|
can speed up this process considerably. The process consists of some number of rounds
|
||||||
|
during which Elves alternate between considering where to move and actually moving.
|
||||||
|
|
||||||
|
During the first half of each round, each Elf considers the eight positions adjacent
|
||||||
|
to themself. If no other Elves are in one of those eight positions, the Elf does not
|
||||||
|
do anything during this round. Otherwise, the Elf looks in each of four directions in
|
||||||
|
the following order and proposes moving one step in the first valid direction:
|
||||||
|
|
||||||
|
• If there is no Elf in the N, NE, or NW adjacent positions, the Elf proposes moving
|
||||||
|
north one step.
|
||||||
|
• If there is no Elf in the S, SE, or SW adjacent positions, the Elf proposes moving
|
||||||
|
south one step.
|
||||||
|
• If there is no Elf in the W, NW, or SW adjacent positions, the Elf proposes moving
|
||||||
|
west one step.
|
||||||
|
• If there is no Elf in the E, NE, or SE adjacent positions, the Elf proposes moving
|
||||||
|
east one step.
|
||||||
|
|
||||||
|
After each Elf has had a chance to propose a move, the second half of the round can
|
||||||
|
begin. Simultaneously, each Elf moves to their proposed destination tile if they were
|
||||||
|
the only Elf to propose moving to that position. If two or more Elves propose moving
|
||||||
|
to the same position, none of those Elves move.
|
||||||
|
|
||||||
|
Finally, at the end of the round, the first direction the Elves considered is moved to
|
||||||
|
the end of the list of directions. For example, during the second round, the Elves
|
||||||
|
would try proposing a move to the south first, then west, then east, then north. On
|
||||||
|
the third round, the Elves would first consider west, then east, then north, then
|
||||||
|
south.
|
||||||
|
|
||||||
|
As a smaller example, consider just these five Elves:
|
||||||
|
|
||||||
|
.....
|
||||||
|
..##.
|
||||||
|
..#..
|
||||||
|
.....
|
||||||
|
..##.
|
||||||
|
.....
|
||||||
|
|
||||||
|
The northernmost two Elves and southernmost two Elves all propose moving north, while
|
||||||
|
the middle Elf cannot move north and proposes moving south. The middle Elf proposes
|
||||||
|
the same destination as the southwest Elf, so neither of them move, but the other
|
||||||
|
three do:
|
||||||
|
|
||||||
|
..##.
|
||||||
|
.....
|
||||||
|
..#..
|
||||||
|
...#.
|
||||||
|
..#..
|
||||||
|
.....
|
||||||
|
|
||||||
|
Next, the northernmost two Elves and the southernmost Elf all propose moving south. Of
|
||||||
|
the remaining middle two Elves, the west one cannot move south and proposes moving
|
||||||
|
west, while the east one cannot move south or west and proposes moving east. All five
|
||||||
|
Elves succeed in moving to their proposed positions:
|
||||||
|
|
||||||
|
.....
|
||||||
|
..##.
|
||||||
|
.#...
|
||||||
|
....#
|
||||||
|
.....
|
||||||
|
..#..
|
||||||
|
|
||||||
|
Finally, the southernmost two Elves choose not to move at all. Of the remaining three
|
||||||
|
Elves, the west one proposes moving west, the east one proposes moving east, and the
|
||||||
|
middle one proposes moving north; all three succeed in moving:
|
||||||
|
|
||||||
|
..#..
|
||||||
|
....#
|
||||||
|
#....
|
||||||
|
....#
|
||||||
|
.....
|
||||||
|
..#..
|
||||||
|
|
||||||
|
At this point, no Elves need to move, and so the process ends.
|
||||||
|
|
||||||
|
The larger example above proceeds as follows:
|
||||||
|
|
||||||
|
== Initial State ==
|
||||||
|
..............
|
||||||
|
..............
|
||||||
|
.......#......
|
||||||
|
.....###.#....
|
||||||
|
...#...#.#....
|
||||||
|
....#...##....
|
||||||
|
...#.###......
|
||||||
|
...##.#.##....
|
||||||
|
....#..#......
|
||||||
|
..............
|
||||||
|
..............
|
||||||
|
..............
|
||||||
|
|
||||||
|
== End of Round 1 ==
|
||||||
|
..............
|
||||||
|
.......#......
|
||||||
|
.....#...#....
|
||||||
|
...#..#.#.....
|
||||||
|
.......#..#...
|
||||||
|
....#.#.##....
|
||||||
|
..#..#.#......
|
||||||
|
..#.#.#.##....
|
||||||
|
..............
|
||||||
|
....#..#......
|
||||||
|
..............
|
||||||
|
..............
|
||||||
|
|
||||||
|
== End of Round 2 ==
|
||||||
|
..............
|
||||||
|
.......#......
|
||||||
|
....#.....#...
|
||||||
|
...#..#.#.....
|
||||||
|
.......#...#..
|
||||||
|
...#..#.#.....
|
||||||
|
.#...#.#.#....
|
||||||
|
..............
|
||||||
|
..#.#.#.##....
|
||||||
|
....#..#......
|
||||||
|
..............
|
||||||
|
..............
|
||||||
|
|
||||||
|
== End of Round 3 ==
|
||||||
|
..............
|
||||||
|
.......#......
|
||||||
|
.....#....#...
|
||||||
|
..#..#...#....
|
||||||
|
.......#...#..
|
||||||
|
...#..#.#.....
|
||||||
|
.#..#.....#...
|
||||||
|
.......##.....
|
||||||
|
..##.#....#...
|
||||||
|
...#..........
|
||||||
|
.......#......
|
||||||
|
..............
|
||||||
|
|
||||||
|
== End of Round 4 ==
|
||||||
|
..............
|
||||||
|
.......#......
|
||||||
|
......#....#..
|
||||||
|
..#...##......
|
||||||
|
...#.....#.#..
|
||||||
|
.........#....
|
||||||
|
.#...###..#...
|
||||||
|
..#......#....
|
||||||
|
....##....#...
|
||||||
|
....#.........
|
||||||
|
.......#......
|
||||||
|
..............
|
||||||
|
|
||||||
|
== End of Round 5 ==
|
||||||
|
.......#......
|
||||||
|
..............
|
||||||
|
..#..#.....#..
|
||||||
|
.........#....
|
||||||
|
......##...#..
|
||||||
|
.#.#.####.....
|
||||||
|
...........#..
|
||||||
|
....##..#.....
|
||||||
|
..#...........
|
||||||
|
..........#...
|
||||||
|
....#..#......
|
||||||
|
..............
|
||||||
|
|
||||||
|
After a few more rounds...
|
||||||
|
|
||||||
|
== End of Round 10 ==
|
||||||
|
.......#......
|
||||||
|
...........#..
|
||||||
|
..#.#..#......
|
||||||
|
......#.......
|
||||||
|
...#.....#..#.
|
||||||
|
.#......##....
|
||||||
|
.....##.......
|
||||||
|
..#........#..
|
||||||
|
....#.#..#....
|
||||||
|
..............
|
||||||
|
....#..#..#...
|
||||||
|
..............
|
||||||
|
|
||||||
|
To make sure they're on the right track, the Elves like to check after round 10 that
|
||||||
|
they're making good progress toward covering enough ground. To do this, count the
|
||||||
|
number of empty ground tiles contained by the smallest rectangle that contains every
|
||||||
|
Elf. (The edges of the rectangle should be aligned to the N/S/E/W directions; the
|
||||||
|
Elves do not have the patience to calculate arbitrary rectangles.) In the above
|
||||||
|
example, that rectangle is:
|
||||||
|
|
||||||
|
......#.....
|
||||||
|
..........#.
|
||||||
|
.#.#..#.....
|
||||||
|
.....#......
|
||||||
|
..#.....#..#
|
||||||
|
#......##...
|
||||||
|
....##......
|
||||||
|
.#........#.
|
||||||
|
...#.#..#...
|
||||||
|
............
|
||||||
|
...#..#..#..
|
||||||
|
|
||||||
|
In this region, the number of empty ground tiles is 110.
|
||||||
|
|
||||||
|
Simulate the Elves' process and find the smallest rectangle that contains the Elves
|
||||||
|
after 10 rounds. How many empty ground tiles does that rectangle contain?
|
||||||
|
|
||||||
|
Your puzzle answer was 4000.
|
||||||
|
|
||||||
|
--- Part Two ---
|
||||||
|
|
||||||
|
It seems you're on the right track. Finish simulating the process and figure out where
|
||||||
|
the Elves need to go. How many rounds did you save them?
|
||||||
|
|
||||||
|
In the example above, the first round where no Elf moved was round 20:
|
||||||
|
|
||||||
|
.......#......
|
||||||
|
....#......#..
|
||||||
|
..#.....#.....
|
||||||
|
......#.......
|
||||||
|
...#....#.#..#
|
||||||
|
#.............
|
||||||
|
....#.....#...
|
||||||
|
..#.....#.....
|
||||||
|
....#.#....#..
|
||||||
|
.........#....
|
||||||
|
....#......#..
|
||||||
|
.......#......
|
||||||
|
|
||||||
|
Figure out where the Elves need to go. What is the number of the first round where no
|
||||||
|
Elf moves?
|
||||||
|
|
||||||
|
Your puzzle answer was 1040.
|
||||||
|
|
||||||
|
Both parts of this puzzle are complete! They provide two gold stars: **
|
||||||
|
|
||||||
|
References
|
||||||
|
|
||||||
|
Visible links
|
||||||
|
. https://adventofcode.com/
|
||||||
|
. https://adventofcode.com/2022/about
|
||||||
|
. https://adventofcode.com/2022/events
|
||||||
|
. 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://adventofcode.com/2022
|
||||||
|
. https://adventofcode.com/2022/day/23/input
|
7
2022/day23/testinput
Normal file
7
2022/day23/testinput
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
....#..
|
||||||
|
..###.#
|
||||||
|
#...#.#
|
||||||
|
.#...##
|
||||||
|
#.###..
|
||||||
|
##.#.##
|
||||||
|
.#..#..
|
6
2022/day23/testinput2
Normal file
6
2022/day23/testinput2
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.....
|
||||||
|
..##.
|
||||||
|
..#..
|
||||||
|
.....
|
||||||
|
..##.
|
||||||
|
.....
|
2
go.mod
2
go.mod
@ -1,6 +1,6 @@
|
|||||||
module git.bullercodeworks.com/brian/adventofcode
|
module git.bullercodeworks.com/brian/adventofcode
|
||||||
|
|
||||||
go 1.13
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/br0xen/termbox-screen v0.0.0-20190712162752-c91f70ac38c6
|
github.com/br0xen/termbox-screen v0.0.0-20190712162752-c91f70ac38c6
|
||||||
|
@ -66,6 +66,13 @@ func (c *Coordinate) SE() Coordinate {
|
|||||||
func (c *Coordinate) GetOrthNeighbors() []Coordinate {
|
func (c *Coordinate) GetOrthNeighbors() []Coordinate {
|
||||||
return []Coordinate{c.North(), c.East(), c.South(), c.West()}
|
return []Coordinate{c.North(), c.East(), c.South(), c.West()}
|
||||||
}
|
}
|
||||||
|
func (c *Coordinate) GetAllNeighbors() []Coordinate {
|
||||||
|
return []Coordinate{
|
||||||
|
c.North(), c.NE(),
|
||||||
|
c.East(), c.SE(),
|
||||||
|
c.South(), c.SW(),
|
||||||
|
c.West(), c.NW()}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Coordinate) GetNorthCoord() *Coordinate {
|
func (c *Coordinate) GetNorthCoord() *Coordinate {
|
||||||
return &Coordinate{
|
return &Coordinate{
|
||||||
|
Loading…
Reference in New Issue
Block a user