2022 Day 20 Complete!
This commit is contained in:
parent
33d1a7c3c6
commit
6a843e488c
@ -5,6 +5,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||||
)
|
)
|
||||||
@ -42,8 +43,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
part1(inp)
|
if part == 1 || part == -1 {
|
||||||
part2(inp)
|
part1(inp)
|
||||||
|
}
|
||||||
|
if part == 2 || part == -1 {
|
||||||
|
part2(inp)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func part1(inp []string) {
|
func part1(inp []string) {
|
||||||
@ -74,49 +79,122 @@ func part1(inp []string) {
|
|||||||
fmt.Println(nopeCount)
|
fmt.Println(nopeCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Sensor struct {
|
||||||
|
c h.Coordinate // Sensor Position
|
||||||
|
b h.Coordinate // Beacon Position
|
||||||
|
d int // Distance
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Sensor) isInRange(c h.Coordinate) bool { return s.c.Distance(c) <= s.d }
|
||||||
|
|
||||||
|
func (s Sensor) String() string { return s.c.String() }
|
||||||
|
|
||||||
func part2(inp []string) {
|
func part2(inp []string) {
|
||||||
min_x, max_x := math.MaxInt, math.MinInt
|
var sensors []Sensor
|
||||||
var spots [][]int
|
|
||||||
for i := range inp {
|
for i := range inp {
|
||||||
s, b := strToCoords(inp[i])
|
s := Sensor{}
|
||||||
xs, ys, xb, yb := s.X, s.Y, b.X, b.Y
|
s.c, s.b = strToCoords(inp[i])
|
||||||
dist := s.Distance(b)
|
s.d = s.c.Distance(s.b)
|
||||||
l, r := xs-dist, xs+dist
|
sensors = append(sensors, s)
|
||||||
min_x = h.Min(min_x, l)
|
|
||||||
max_x = h.Max(max_x, r)
|
|
||||||
spots = append(spots, []int{xs, ys, xb, yb, dist})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
max := testRow * 2
|
max := testRow * 2
|
||||||
var found h.Coordinate
|
found := []h.Coordinate{}
|
||||||
SEARCH:
|
// Check around each sensor, the beacon must be it's distance + 1
|
||||||
for y := 0; y <= max; y++ {
|
for _, sensor := range sensors {
|
||||||
for x := 0; x <= max; x++ {
|
d := sensor.d + 1
|
||||||
fmt.Printf("Testing %d,%d...", x, y)
|
testEnds := []h.Coordinate{
|
||||||
var nope bool
|
{X: sensor.c.X, Y: sensor.c.Y - d},
|
||||||
for _, c := range spots {
|
{X: sensor.c.X + d, Y: sensor.c.Y},
|
||||||
if x == c[2] && y == c[3] {
|
{X: sensor.c.X, Y: sensor.c.Y + d},
|
||||||
break
|
{X: sensor.c.X - d, Y: sensor.c.Y},
|
||||||
}
|
}
|
||||||
if h.ManhattanDistance(x, y, c[0], c[1]) <= c[4] {
|
printMap(sensors, max, max, h.Coordinate{X: math.MinInt, Y: math.MinInt})
|
||||||
nope = true
|
var tstX, tstY int
|
||||||
break
|
for i := 0; i < 3; i++ {
|
||||||
|
// Test all spots between testEnds[i] & testEnds[i+1]
|
||||||
|
for tstX != testEnds[i+1].X && tstY != testEnds[i+1].Y {
|
||||||
|
if testEnds[i].X < testEnds[i+1].X {
|
||||||
|
tstX++
|
||||||
|
if testEnds[i].Y < testEnds[i+1].Y {
|
||||||
|
tstY++
|
||||||
|
} else {
|
||||||
|
tstY--
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tstX--
|
||||||
|
if testEnds[i].Y < testEnds[i+1].Y {
|
||||||
|
tstY++
|
||||||
|
} else {
|
||||||
|
tstY--
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !nope {
|
if tstX <= max && tstY <= max {
|
||||||
fmt.Println("Yup")
|
fmt.Print(h.CLEAR_SCREEN)
|
||||||
found = h.Coordinate{X: x, Y: y}
|
printMap(sensors, max, max, h.Coordinate{X: tstX, Y: tstY})
|
||||||
break SEARCH
|
fmt.Println("Testing", tstX, ",", tstY)
|
||||||
|
time.Sleep(time.Second / 10)
|
||||||
|
if testSpot(tstX, tstY, sensors) {
|
||||||
|
found = append(found, h.Coordinate{X: tstX, Y: tstY})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fmt.Println("Nope")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("# Part 2")
|
fmt.Println("# Part 2")
|
||||||
fmt.Println(found)
|
fmt.Println(found)
|
||||||
fmt.Println((found.X * 4000000) + found.Y)
|
//fmt.Println((found.X * 4000000) + found.Y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func printMap(m [][]int) {
|
func testSpot(x, y int, sensors []Sensor) bool {
|
||||||
|
var wasInRange bool
|
||||||
|
for i := range sensors {
|
||||||
|
if sensors[i].isInRange(h.Coordinate{X: x, Y: y}) {
|
||||||
|
wasInRange = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !wasInRange
|
||||||
|
}
|
||||||
|
|
||||||
|
func printMap(sensors []Sensor, ceilX, ceilY int, tstPos h.Coordinate) {
|
||||||
|
minX, maxX, minY, maxY := math.MaxInt, math.MinInt, math.MaxInt, math.MinInt
|
||||||
|
for i := range sensors {
|
||||||
|
minX = h.Min(sensors[i].b.X, minX)
|
||||||
|
maxX = h.Max(sensors[i].b.X, maxX)
|
||||||
|
minY = h.Min(sensors[i].b.Y, minY)
|
||||||
|
maxY = h.Max(sensors[i].b.Y, maxY)
|
||||||
|
}
|
||||||
|
for y := minY; y <= maxY; y++ {
|
||||||
|
for x := minX; x <= maxX; x++ {
|
||||||
|
wrk := h.Coordinate{X: x, Y: y}
|
||||||
|
var found bool
|
||||||
|
for _, sensor := range sensors {
|
||||||
|
if sensor.c.Equals(wrk) {
|
||||||
|
fmt.Print("S")
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
} else if sensor.b.Equals(wrk) {
|
||||||
|
fmt.Print("B")
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
} else if sensor.isInRange(wrk) {
|
||||||
|
fmt.Print("#")
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
if wrk.Equals(tstPos) {
|
||||||
|
fmt.Print(h.FILL_CHAR)
|
||||||
|
} else {
|
||||||
|
fmt.Print(".")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func strToCoords(s string) (h.Coordinate, h.Coordinate) {
|
func strToCoords(s string) (h.Coordinate, h.Coordinate) {
|
||||||
|
@ -57,6 +57,7 @@ func (v *Volcano) TrackStepCount(from *Room, to *Room, visited []*Room) int {
|
|||||||
if !IsRoomIn(t, visited) {
|
if !IsRoomIn(t, visited) {
|
||||||
fmt.Println(" Haven't Visited")
|
fmt.Println(" Haven't Visited")
|
||||||
wrk := v.TrackStepCount(t, to, append(visited, t)) + 1
|
wrk := v.TrackStepCount(t, to, append(visited, t)) + 1
|
||||||
|
fmt.Println(" From", from, "to", to, "in", wrk)
|
||||||
minSteps = h.Min(minSteps, wrk)
|
minSteps = h.Min(minSteps, wrk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5000
2022/day20/input
Normal file
5000
2022/day20/input
Normal file
File diff suppressed because it is too large
Load Diff
101
2022/day20/main.go
Normal file
101
2022/day20/main.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Node struct {
|
||||||
|
value int
|
||||||
|
prev *Node
|
||||||
|
next *Node
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
inp := h.StdinToStringSlice()
|
||||||
|
part1(inp)
|
||||||
|
part2(inp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func part1(inp []string) {
|
||||||
|
var list []*Node
|
||||||
|
var first *Node
|
||||||
|
for i := range inp {
|
||||||
|
n := &Node{value: h.Atoi(inp[i])}
|
||||||
|
if n.value == 0 {
|
||||||
|
first = n
|
||||||
|
}
|
||||||
|
list = append(list, n)
|
||||||
|
}
|
||||||
|
initList(list)
|
||||||
|
mixAll(list)
|
||||||
|
fmt.Println("# Part 1")
|
||||||
|
fmt.Println(getCoords(first))
|
||||||
|
}
|
||||||
|
|
||||||
|
func part2(inp []string) {
|
||||||
|
key := 811589153
|
||||||
|
var list []*Node
|
||||||
|
var first *Node
|
||||||
|
for i := range inp {
|
||||||
|
n := &Node{value: h.Atoi(inp[i]) * key}
|
||||||
|
if n.value == 0 {
|
||||||
|
first = n
|
||||||
|
}
|
||||||
|
list = append(list, n)
|
||||||
|
}
|
||||||
|
initList(list)
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
mixAll(list)
|
||||||
|
}
|
||||||
|
fmt.Println("# Part 2")
|
||||||
|
fmt.Println(getCoords(first))
|
||||||
|
}
|
||||||
|
|
||||||
|
func initList(list []*Node) {
|
||||||
|
list[0].prev = list[len(list)-1]
|
||||||
|
list[len(list)-1].next = list[0]
|
||||||
|
for i := 1; i < len(list); i++ {
|
||||||
|
list[i].prev = list[i-1]
|
||||||
|
list[i-1].next = list[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func move(n *Node, count int) *Node {
|
||||||
|
for count < 0 {
|
||||||
|
n = n.prev
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
for count > 0 {
|
||||||
|
n = n.next
|
||||||
|
count--
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func mix(n *Node, listLen int) {
|
||||||
|
t := n.prev
|
||||||
|
n.prev.next = n.next
|
||||||
|
n.next.prev = n.prev
|
||||||
|
t = move(t, n.value%(listLen-1))
|
||||||
|
n.prev = t
|
||||||
|
n.next = t.next
|
||||||
|
n.prev.next = n
|
||||||
|
n.next.prev = n
|
||||||
|
}
|
||||||
|
|
||||||
|
func mixAll(list []*Node) {
|
||||||
|
for _, n := range list {
|
||||||
|
mix(n, len(list))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCoords(first *Node) int {
|
||||||
|
var res int
|
||||||
|
for i, n := 0, first; i < 3; i++ {
|
||||||
|
n = move(n, 1000)
|
||||||
|
res += n.value
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
151
2022/day20/problem
Normal file
151
2022/day20/problem
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
Advent of Code
|
||||||
|
br0xen (AoC++) 31*
|
||||||
|
|
||||||
|
--- Day 20: Grove Positioning System ---
|
||||||
|
|
||||||
|
It's finally time to meet back up with the Elves. When you try to contact them, however, you get no reply. Perhaps
|
||||||
|
you're out of range?
|
||||||
|
|
||||||
|
You know they're headed to the grove where the star fruit grows, so if you can figure out where that is, you should
|
||||||
|
be able to meet back up with them.
|
||||||
|
|
||||||
|
Fortunately, your handheld device has a file (your puzzle input) that contains the grove's coordinates!
|
||||||
|
Unfortunately, the file is encrypted - just in case the device were to fall into the wrong hands.
|
||||||
|
|
||||||
|
Maybe you can decrypt it?
|
||||||
|
|
||||||
|
When you were still back at the camp, you overheard some Elves talking about coordinate file encryption. The main
|
||||||
|
operation involved in decrypting the file is called mixing.
|
||||||
|
|
||||||
|
The encrypted file is a list of numbers. To mix the file, move each number forward or backward in the file a number
|
||||||
|
of positions equal to the value of the number being moved. The list is circular, so moving a number off one end of
|
||||||
|
the list wraps back around to the other end as if the ends were connected.
|
||||||
|
|
||||||
|
For example, to move the 1 in a sequence like 4, 5, 6, 1, 7, 8, 9, the 1 moves one position forward: 4, 5, 6, 7, 1,
|
||||||
|
8, 9. To move the -2 in a sequence like 4, -2, 5, 6, 7, 8, 9, the -2 moves two positions backward, wrapping around:
|
||||||
|
4, 5, 6, 7, 8, -2, 9.
|
||||||
|
|
||||||
|
The numbers should be moved in the order they originally appear in the encrypted file. Numbers moving around during
|
||||||
|
the mixing process do not change the order in which the numbers are moved.
|
||||||
|
|
||||||
|
Consider this encrypted file:
|
||||||
|
|
||||||
|
1
|
||||||
|
2
|
||||||
|
-3
|
||||||
|
3
|
||||||
|
-2
|
||||||
|
0
|
||||||
|
4
|
||||||
|
|
||||||
|
Mixing this file proceeds as follows:
|
||||||
|
|
||||||
|
Initial arrangement:
|
||||||
|
1, 2, -3, 3, -2, 0, 4
|
||||||
|
|
||||||
|
1 moves between 2 and -3:
|
||||||
|
2, 1, -3, 3, -2, 0, 4
|
||||||
|
|
||||||
|
2 moves between -3 and 3:
|
||||||
|
1, -3, 2, 3, -2, 0, 4
|
||||||
|
|
||||||
|
-3 moves between -2 and 0:
|
||||||
|
1, 2, 3, -2, -3, 0, 4
|
||||||
|
|
||||||
|
3 moves between 0 and 4:
|
||||||
|
1, 2, -2, -3, 0, 3, 4
|
||||||
|
|
||||||
|
-2 moves between 4 and 1:
|
||||||
|
1, 2, -3, 0, 3, 4, -2
|
||||||
|
|
||||||
|
0 does not move:
|
||||||
|
1, 2, -3, 0, 3, 4, -2
|
||||||
|
|
||||||
|
4 moves between -3 and 0:
|
||||||
|
1, 2, -3, 4, 0, 3, -2
|
||||||
|
|
||||||
|
Then, the grove coordinates can be found by looking at the 1000th, 2000th, and 3000th numbers after the value 0,
|
||||||
|
wrapping around the list as necessary. In the above example, the 1000th number after 0 is 4, the 2000th is -3, and
|
||||||
|
the 3000th is 2; adding these together produces 3.
|
||||||
|
|
||||||
|
Mix your encrypted file exactly once. What is the sum of the three numbers that form the grove coordinates?
|
||||||
|
|
||||||
|
Your puzzle answer was 9687.
|
||||||
|
|
||||||
|
--- Part Two ---
|
||||||
|
|
||||||
|
The grove coordinate values seem nonsensical. While you ponder the mysteries of Elf encryption, you suddenly
|
||||||
|
remember the rest of the decryption routine you overheard back at camp.
|
||||||
|
|
||||||
|
First, you need to apply the decryption key, 811589153. Multiply each number by the decryption key before you
|
||||||
|
begin; this will produce the actual list of numbers to mix.
|
||||||
|
|
||||||
|
Second, you need to mix the list of numbers ten times. The order in which the numbers are mixed does not change
|
||||||
|
during mixing; the numbers are still moved in the order they appeared in the original, pre-mixed list. (So, if -3
|
||||||
|
appears fourth in the original list of numbers to mix, -3 will be the fourth number to move during each round of
|
||||||
|
mixing.)
|
||||||
|
|
||||||
|
Using the same example as above:
|
||||||
|
|
||||||
|
Initial arrangement:
|
||||||
|
811589153, 1623178306, -2434767459, 2434767459, -1623178306, 0, 3246356612
|
||||||
|
|
||||||
|
After 1 round of mixing:
|
||||||
|
0, -2434767459, 3246356612, -1623178306, 2434767459, 1623178306, 811589153
|
||||||
|
|
||||||
|
After 2 rounds of mixing:
|
||||||
|
0, 2434767459, 1623178306, 3246356612, -2434767459, -1623178306, 811589153
|
||||||
|
|
||||||
|
After 3 rounds of mixing:
|
||||||
|
0, 811589153, 2434767459, 3246356612, 1623178306, -1623178306, -2434767459
|
||||||
|
|
||||||
|
After 4 rounds of mixing:
|
||||||
|
0, 1623178306, -2434767459, 811589153, 2434767459, 3246356612, -1623178306
|
||||||
|
|
||||||
|
After 5 rounds of mixing:
|
||||||
|
0, 811589153, -1623178306, 1623178306, -2434767459, 3246356612, 2434767459
|
||||||
|
|
||||||
|
After 6 rounds of mixing:
|
||||||
|
0, 811589153, -1623178306, 3246356612, -2434767459, 1623178306, 2434767459
|
||||||
|
|
||||||
|
After 7 rounds of mixing:
|
||||||
|
0, -2434767459, 2434767459, 1623178306, -1623178306, 811589153, 3246356612
|
||||||
|
|
||||||
|
After 8 rounds of mixing:
|
||||||
|
0, 1623178306, 3246356612, 811589153, -2434767459, 2434767459, -1623178306
|
||||||
|
|
||||||
|
After 9 rounds of mixing:
|
||||||
|
0, 811589153, 1623178306, -2434767459, 3246356612, 2434767459, -1623178306
|
||||||
|
|
||||||
|
After 10 rounds of mixing:
|
||||||
|
0, -2434767459, 1623178306, 3246356612, -1623178306, 2434767459, 811589153
|
||||||
|
|
||||||
|
The grove coordinates can still be found in the same way. Here, the 1000th number after 0 is 811589153, the 2000th
|
||||||
|
is 2434767459, and the 3000th is -1623178306; adding these together produces 1623178306.
|
||||||
|
|
||||||
|
Apply the decryption key and mix your encrypted file ten times. What is the sum of the three numbers that form the
|
||||||
|
grove coordinates?
|
||||||
|
|
||||||
|
Your puzzle answer was 1338310513297.
|
||||||
|
|
||||||
|
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/20/input
|
7
2022/day20/testinput
Normal file
7
2022/day20/testinput
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
1
|
||||||
|
2
|
||||||
|
-3
|
||||||
|
3
|
||||||
|
-2
|
||||||
|
0
|
||||||
|
4
|
Loading…
Reference in New Issue
Block a user