This commit is contained in:
2024-12-18 08:12:54 -06:00
parent 2091f6c894
commit 130904c604
12 changed files with 2188 additions and 276 deletions

View File

@@ -1,276 +0,0 @@
package main
import (
"errors"
"fmt"
h "git.bullercodeworks.com/brian/adventofcode/helpers"
)
func main() {
inp := h.StdinToStringSlice()
part1(inp)
// fmt.Println()
// part2(inp)
}
var (
N = h.Coordinate{X: 0, Y: -1}
E = h.Coordinate{X: 1, Y: 0}
S = h.Coordinate{X: 0, Y: 1}
W = h.Coordinate{X: -1, Y: 0}
)
var (
scoreTrack map[h.Coordinate]int
bestCostToEnd map[h.Coordinate]int
)
func part1(inpS []string) {
inp := h.StringSliceToCoordByteMap(inpS)
scoreTrack = make(map[h.Coordinate]int)
bestCostToEnd = make(map[h.Coordinate]int)
start, _ := inp.FindFirst('S')
end, _ := inp.FindFirst('E')
inp.Put(start, '.')
bestCostToEnd[end] = 0
cd := CD{c: start, d: E}
solve(inp, cd, end, 0, []h.Coordinate{cd.c})
best, ok := scoreTrack[end]
if !ok {
panic(errors.New("no path to end found"))
}
fmt.Println("Best Score:", best)
bestSeats := make(map[h.Coordinate]byte)
for i := range bestPaths {
for j := range bestPaths[i] {
bestSeats[bestPaths[i][j]] = byte('0' + i)
}
}
printBestSeats(inp, bestSeats)
fmt.Println("Seats:", len(bestSeats))
}
var bestPaths [][]h.Coordinate
func solve(inp h.CoordByteMap, start CD, end h.Coordinate, score int, currPath []h.Coordinate) int {
// tryMove takes the cd that we're moving to and the cost to move there
// and returns the cost to get from that cd to the end
tryMove := func(c CD, cost int) int {
if inp.ContainsCoord(c.c) && inp.Get(c.c) != '#' {
// printPathMap(inp, c, end, currPath)
// poi := h.Coordinate{X: 3, Y: 10}
// time.Sleep(time.Second / 20)
nextScore := score + cost
v, ok := bestCostToEnd[c.c]
//if c.c.Equals(poi) {
// fmt.Println("Current Scoretrack[poi] =", v)
// fmt.Println("Next Score =", nextScore)
// time.Sleep(time.Second * 5)
//}
if !ok || v >= nextScore {
nxtPath := make([]h.Coordinate, len(currPath))
copy(nxtPath, currPath)
nxtPath = append(nxtPath, c.c)
// Check end conditions
if c.c.Equals(end) {
if !ok || v > nextScore { // New Best
fmt.Println("New Best Path")
scoreTrack[end] = nextScore
bestPaths = [][]h.Coordinate{nxtPath}
} else if v == nextScore { // Another Best Path
fmt.Println("Adding path to best paths")
bestPaths = append(bestPaths, nxtPath)
}
return cost
}
// Not the end, but keep going
scoreTrack[c.c] = nextScore
solve(inp, c, end, nextScore, nxtPath)
}
}
return h.MAX_INT
}
// Test forward
cost := tryMove(start.move(), 1)
// Test CW
if wrk := tryMove(start.turnCW().move(), 1001); wrk < cost {
cost = wrk
}
// Test CCW
if wrk := tryMove(start.turnCCW().move(), 1001); wrk < cost {
cost = wrk
}
bestCostToEnd[start.c] = cost
return cost
}
func printPathMap(inp h.CoordByteMap, loc CD, end h.Coordinate, path []h.Coordinate) {
fmt.Print(h.CLEAR_SCREEN)
wrk := inp.Copy()
wrk.ReplaceAll('.', ' ')
for i := range path {
wrk.Put(path[i], 'o')
}
wrk.Put(loc.c, loc.Byte())
fmt.Println(wrk)
if v, ok := scoreTrack[end]; ok {
fmt.Printf("Best Score: %v (Paths: %d)\n", v, len(bestPaths))
} else {
fmt.Println("Waiting on best score...")
}
}
func printBestSeats(inp h.CoordByteMap, seats map[h.Coordinate]byte) {
fmt.Print(h.CLEAR_SCREEN)
wrk := inp.Copy()
wrk.ReplaceAll('.', ' ')
for k, v := range seats {
wrk.Put(k, byte(0+v))
}
fmt.Println(wrk)
}
/*
func part2(inpS []string) {
inp := h.StringSliceToCoordByteMap(inpS)
scoreTrack = make(map[h.Coordinate]int)
start, _ := inp.FindFirst('S')
end, _ := inp.FindFirst('E')
inp.Put(start, '.')
cd := CD{c: start, d: E}
lookForSeats(inp, cd, end, 0, []h.Coordinate{cd.c})
_, ok := scoreTrack[end]
if !ok {
panic(errors.New("no path to end found"))
}
bestSeats := make(map[h.Coordinate]int)
for i := range bestPaths {
for j := range bestPaths[i] {
bestSeats[bestPaths[i][j]] = i
}
}
fmt.Println("Number of Seats:", len(bestSeats))
}
func coordInPath(c h.Coordinate, path []h.Coordinate) bool {
for i := range path {
if path[i].Equals(c) {
return true
}
}
return false
}
func lookForSeats(inp h.CoordByteMap, start CD, end h.Coordinate, score int, path []h.Coordinate) int {
// Check for finished:
if start.c.Equals(end) {
v, ok := scoreTrack[end]
if !ok || v > score {
// We have a new best path
bestPaths = [][]h.Coordinate{path}
scoreTrack[end] = score
} else if scoreTrack[end] == score {
bestPaths = append(bestPaths, path)
}
return score
}
// Helper func
canMoveTo := func(p h.Coordinate) bool {
return inp.ContainsCoord(p) && inp.Get(p) != '#'
}
// Keep moving:
tryMove := func(c CD, cost int) {
if canMoveTo(c.c) {
// Check if this path has alread gone through this spot
nxtPath := make([]h.Coordinate, len(path))
copy(nxtPath, path)
if coordInPath(c.c, nxtPath) {
return
}
// Ok, now what's the best score we end up if we make this move?
nextScore := score + cost
n, ok := scoreTrack[c.c]
if !ok || n > nextScore {
lookForSeats(inp, c, end, nextScore, append(nxtPath, c.c))
}
}
}
// Test forward
tryMove(start.move(), 1)
// Test CW
tryMove(start.turnCW().move(), 1001)
// Test CCW
tryMove(start.turnCCW().move(), 1001)
return scoreTrack[start.c]
}
*/
type CD struct {
c h.Coordinate
d h.Coordinate
}
func (cd CD) move() CD {
return CD{
c: cd.c.Add(cd.d),
d: cd.d,
}
}
func (cd CD) turnCW() CD {
var newD h.Coordinate
switch cd.d {
case N:
newD = E
case E:
newD = S
case S:
newD = W
case W:
newD = N
}
return CD{
c: cd.c,
d: newD,
}
}
func (cd CD) turnCCW() CD {
var newD h.Coordinate
switch cd.d {
case N:
newD = W
case E:
newD = N
case S:
newD = E
case W:
newD = S
}
return CD{
c: cd.c,
d: newD,
}
}
func (cd CD) Byte() byte {
switch cd.d {
case N:
return '^'
case E:
return '>'
case S:
return 'v'
case W:
return '<'
}
return '?'
}

190
2024/day16/problem Normal file
View File

@@ -0,0 +1,190 @@
Advent of Code
--- Day 16: Reindeer Maze ---
It's time again for the [16]Reindeer Olympics! This year, the big event is
the Reindeer Maze, where the Reindeer compete for the lowest score.
You and The Historians arrive to search for the Chief right as the event
is about to start. It wouldn't hurt to watch a little, right?
The Reindeer start on the Start Tile (marked S) facing East and need to
reach the End Tile (marked E). They can move forward one tile at a time
(increasing their score by 1 point), but never into a wall (#). They can
also rotate clockwise or counterclockwise 90 degrees at a time (increasing
their score by 1000 points).
To figure out the best place to sit, you start by grabbing a map (your
puzzle input) from a nearby kiosk. For example:
###############
#.......#....E#
#.#.###.#.###.#
#.....#.#...#.#
#.###.#####.#.#
#.#.#.......#.#
#.#.#####.###.#
#...........#.#
###.#.#####.#.#
#...#.....#.#.#
#.#.#.###.#.#.#
#.....#...#.#.#
#.###.#.#.#.#.#
#S..#.....#...#
###############
There are many paths through this maze, but taking any of the best paths
would incur a score of only 7036. This can be achieved by taking a total
of 36 steps forward and turning 90 degrees a total of 7 times:
###############
#.......#....E#
#.#.###.#.###^#
#.....#.#...#^#
#.###.#####.#^#
#.#.#.......#^#
#.#.#####.###^#
#..>>>>>>>>v#^#
###^#.#####v#^#
#>>^#.....#v#^#
#^#.#.###.#v#^#
#^....#...#v#^#
#^###.#.#.#v#^#
#S..#.....#>>^#
###############
Here's a second example:
#################
#...#...#...#..E#
#.#.#.#.#.#.#.#.#
#.#.#.#...#...#.#
#.#.#.#.###.#.#.#
#...#.#.#.....#.#
#.#.#.#.#.#####.#
#.#...#.#.#.....#
#.#.#####.#.###.#
#.#.#.......#...#
#.#.###.#####.###
#.#.#...#.....#.#
#.#.#.#####.###.#
#.#.#.........#.#
#.#.#.#########.#
#S#.............#
#################
In this maze, the best paths cost 11048 points; following one such path
would look like this:
#################
#...#...#...#..E#
#.#.#.#.#.#.#.#^#
#.#.#.#...#...#^#
#.#.#.#.###.#.#^#
#>>v#.#.#.....#^#
#^#v#.#.#.#####^#
#^#v..#.#.#>>>>^#
#^#v#####.#^###.#
#^#v#..>>>>^#...#
#^#v###^#####.###
#^#v#>>^#.....#.#
#^#v#^#####.###.#
#^#v#^........#.#
#^#v#^#########.#
#S#>>^..........#
#################
Note that the path shown above includes one 90 degree turn as the very
first move, rotating the Reindeer from facing East to facing North.
Analyze your map carefully. What is the lowest score a Reindeer could
possibly get?
Your puzzle answer was 72400.
--- Part Two ---
Now that you know what the best paths look like, you can figure out the
best spot to sit.
Every non-wall tile (S, ., or E) is equipped with places to sit along the
edges of the tile. While determining which of these tiles would be the
best spot to sit depends on a whole bunch of factors (how comfortable the
seats are, how far away the bathrooms are, whether there's a pillar
blocking your view, etc.), the most important factor is whether the tile
is on one of the best paths through the maze. If you sit somewhere else,
you'd miss all the action!
So, you'll need to determine which tiles are part of any best path through
the maze, including the S and E tiles.
In the first example, there are 45 tiles (marked O) that are part of at
least one of the various best paths through the maze:
###############
#.......#....O#
#.#.###.#.###O#
#.....#.#...#O#
#.###.#####.#O#
#.#.#.......#O#
#.#.#####.###O#
#..OOOOOOOOO#O#
###O#O#####O#O#
#OOO#O....#O#O#
#O#O#O###.#O#O#
#OOOOO#...#O#O#
#O###.#.#.#O#O#
#O..#.....#OOO#
###############
In the second example, there are 64 tiles that are part of at least one of
the best paths:
#################
#...#...#...#..O#
#.#.#.#.#.#.#.#O#
#.#.#.#...#...#O#
#.#.#.#.###.#.#O#
#OOO#.#.#.....#O#
#O#O#.#.#.#####O#
#O#O..#.#.#OOOOO#
#O#O#####.#O###O#
#O#O#..OOOOO#OOO#
#O#O###O#####O###
#O#O#OOO#..OOO#.#
#O#O#O#####O###.#
#O#O#OOOOOOO..#.#
#O#O#O#########.#
#O#OOO..........#
#################
Analyze your map further. How many tiles are part of at least one of the
best paths through the maze?
Your puzzle answer was 435.
Both parts of this puzzle are complete! They provide two gold stars: **
At this point, you should [17]return to your Advent calendar and try
another puzzle.
If you still want to see it, you can [18]get your puzzle input.
References
Visible links
1. https://adventofcode.com/
2. https://adventofcode.com/2024/about
3. https://adventofcode.com/2024/events
5. https://adventofcode.com/2024/settings
6. https://adventofcode.com/2024/auth/logout
7. Advent of Code Supporter
https://adventofcode.com/2024/support
8. https://adventofcode.com/2024
9. https://adventofcode.com/2024
10. https://adventofcode.com/2024/support
12. https://adventofcode.com/2024/leaderboard
13. https://adventofcode.com/2024/stats
16. https://adventofcode.com/2015/day/14
17. https://adventofcode.com/2024
18. https://adventofcode.com/2024/day/16/input