solve Day17 Part One in python
This commit is contained in:
parent
bfea3d7501
commit
3c3a481824
104
Day17/README.md
Normal file
104
Day17/README.md
Normal file
@ -0,0 +1,104 @@
|
||||
# Day 17: Clumsy Crucible ---
|
||||
## Part One
|
||||
The lava starts flowing rapidly once the Lava Production Facility is operational. As you leave, the reindeer offers you a parachute, allowing you to quickly reach Gear Island.
|
||||
|
||||
As you descend, your bird's-eye view of Gear Island reveals why you had trouble finding anyone on your way up: half of Gear Island is empty, but the half below you is a giant factory city!
|
||||
|
||||
You land near the gradually-filling pool of lava at the base of your new lavafall. Lavaducts will eventually carry the lava throughout the city, but to make use of it immediately, Elves are loading it into large crucibles on wheels.
|
||||
|
||||
The crucibles are top-heavy and pushed by hand. Unfortunately, the crucibles become very difficult to steer at high speeds, and so it can be hard to go in a straight line for very long.
|
||||
|
||||
To get Desert Island the machine parts it needs as soon as possible, you'll need to find the best way to get the crucible from the lava pool to the machine parts factory. To do this, you need to minimize heat loss while choosing a route that doesn't require the crucible to go in a straight line for too long.
|
||||
|
||||
Fortunately, the Elves here have a map (your puzzle input) that uses traffic patterns, ambient temperature, and hundreds of other parameters to calculate exactly how much heat loss can be expected for a crucible entering any particular city block.
|
||||
|
||||
For example:
|
||||
```
|
||||
2413432311323
|
||||
3215453535623
|
||||
3255245654254
|
||||
3446585845452
|
||||
4546657867536
|
||||
1438598798454
|
||||
4457876987766
|
||||
3637877979653
|
||||
4654967986887
|
||||
4564679986453
|
||||
1224686865563
|
||||
2546548887735
|
||||
4322674655533
|
||||
```
|
||||
|
||||
Each city block is marked by a single digit that represents the amount of heat loss if the crucible enters that block. The starting point, the lava pool, is the top-left city block; the destination, the machine parts factory, is the bottom-right city block. (Because you already start in the top-left block, you don't incur that block's heat loss unless you leave that block and then return to it.)
|
||||
|
||||
Because it is difficult to keep the top-heavy crucible going in a straight line for very long, it can move at most three blocks in a single direction before it must turn 90 degrees left or right. The crucible also can't reverse direction; after entering each city block, it may only turn left, continue straight, or turn right.
|
||||
|
||||
One way to minimize heat loss is this path:
|
||||
|
||||
```
|
||||
2>>34^>>>1323
|
||||
32v>>>35v5623
|
||||
32552456v>>54
|
||||
3446585845v52
|
||||
4546657867v>6
|
||||
14385987984v4
|
||||
44578769877v6
|
||||
36378779796v>
|
||||
465496798688v
|
||||
456467998645v
|
||||
12246868655<v
|
||||
25465488877v5
|
||||
43226746555v>
|
||||
```
|
||||
|
||||
This path never moves more than three consecutive blocks in the same direction and incurs a heat loss of only 102.
|
||||
|
||||
Directing the crucible from the lava pool to the machine parts factory, but not moving more than three consecutive blocks in the same direction, what is the least heat loss it can incur?
|
||||
|
||||
## Part Two
|
||||
The crucibles of lava simply aren't large enough to provide an adequate supply of lava to the machine parts factory. Instead, the Elves are going to upgrade to ultra crucibles.
|
||||
|
||||
Ultra crucibles are even more difficult to steer than normal crucibles. Not only do they have trouble going in a straight line, but they also have trouble turning!
|
||||
|
||||
Once an ultra crucible starts moving in a direction, it needs to move a minimum of four blocks in that direction before it can turn (or even before it can stop at the end). However, it will eventually start to get wobbly: an ultra crucible can move a maximum of ten consecutive blocks without turning.
|
||||
|
||||
In the above example, an ultra crucible could follow this path to minimize heat loss:
|
||||
```
|
||||
2>>>>>>>>1323
|
||||
32154535v5623
|
||||
32552456v4254
|
||||
34465858v5452
|
||||
45466578v>>>>
|
||||
143859879845v
|
||||
445787698776v
|
||||
363787797965v
|
||||
465496798688v
|
||||
456467998645v
|
||||
122468686556v
|
||||
254654888773v
|
||||
432267465553v
|
||||
```
|
||||
|
||||
In the above example, an ultra crucible would incur the minimum possible heat loss of 94.
|
||||
|
||||
Here's another example:
|
||||
```
|
||||
111111111111
|
||||
999999999991
|
||||
999999999991
|
||||
999999999991
|
||||
999999999991
|
||||
```
|
||||
|
||||
Sadly, an ultra crucible would need to take an unfortunate path like this one:
|
||||
```
|
||||
1>>>>>>>1111
|
||||
9999999v9991
|
||||
9999999v9991
|
||||
9999999v9991
|
||||
9999999v>>>>
|
||||
```
|
||||
|
||||
This route causes the ultra crucible to incur the minimum possible heat loss of 71.
|
||||
|
||||
Directing the ultra crucible from the lava pool to the machine parts factory, what is the least heat loss it can incur?
|
109
Day17/python/solution1.py
Normal file
109
Day17/python/solution1.py
Normal file
@ -0,0 +1,109 @@
|
||||
from heapq import heappush, heappop
|
||||
|
||||
# Constants for movement directions
|
||||
DIRECTIONS = [(-1, 0), (1, 0), (0, -1), (0, 1)]
|
||||
|
||||
|
||||
def read_grid(filename):
|
||||
"""
|
||||
Reads the grid of numbers from the given file.
|
||||
"""
|
||||
with open(filename) as f:
|
||||
return [tuple(map(int, line.strip())) for line in f.readlines()]
|
||||
|
||||
|
||||
def is_valid_position(row, col, grid):
|
||||
"""
|
||||
Checks if the given position is within the bounds of the grid.
|
||||
"""
|
||||
return 0 <= row < len(grid) and 0 <= col < len(grid[0])
|
||||
|
||||
|
||||
def find_least_heat_loss(grid):
|
||||
"""
|
||||
Finds the path with the least heat loss in the given grid.
|
||||
"""
|
||||
queue = [(0, 0, 0, 0, 0, 0)] # heat_loss, row, col, dr, dc, n
|
||||
seen = set()
|
||||
|
||||
while queue:
|
||||
heat_loss, row, col, dr, dc, n = heappop(queue)
|
||||
|
||||
# Check if destination is reached
|
||||
if row == len(grid) - 1 and col == len(grid[0]) - 1:
|
||||
return heat_loss
|
||||
|
||||
if (row, col, dr, dc, n) in seen:
|
||||
continue
|
||||
|
||||
seen.add((row, col, dr, dc, n))
|
||||
|
||||
# Continue in the same direction if not moved more than 3 blocks
|
||||
if n < 3 and (dr, dc) != (0, 0):
|
||||
new_row, new_col = row + dr, col + dc
|
||||
if is_valid_position(new_row, new_col, grid):
|
||||
heappush(
|
||||
queue,
|
||||
(
|
||||
heat_loss + grid[new_row][new_col],
|
||||
new_row,
|
||||
new_col,
|
||||
dr,
|
||||
dc,
|
||||
n + 1,
|
||||
),
|
||||
)
|
||||
|
||||
# Explore adjacent directions, avoiding immediate reversals
|
||||
for new_dr, new_dc in DIRECTIONS:
|
||||
if (new_dr, new_dc) in ((dr, dc), (-dr, -dc)):
|
||||
continue
|
||||
|
||||
new_row, new_col = row + new_dr, col + new_dc
|
||||
if is_valid_position(new_row, new_col, grid):
|
||||
heappush(
|
||||
queue,
|
||||
(
|
||||
heat_loss + grid[new_row][new_col],
|
||||
new_row,
|
||||
new_col,
|
||||
new_dr,
|
||||
new_dc,
|
||||
1,
|
||||
),
|
||||
)
|
||||
|
||||
return -1 # Return -1 if no path is found
|
||||
|
||||
|
||||
def test_algorithm():
|
||||
"""
|
||||
Tests the algorithm with test data and asserts the correct output.
|
||||
"""
|
||||
test_grid = read_grid("../test.txt")
|
||||
expected_result = 102 # Expected heat loss
|
||||
result = find_least_heat_loss(test_grid)
|
||||
assert (
|
||||
result == expected_result
|
||||
), f"Test failed: Expected {expected_result}, got {result}"
|
||||
print("Test passed successfully!")
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Main function to run the puzzle solution.
|
||||
"""
|
||||
try:
|
||||
# Run test first
|
||||
test_algorithm()
|
||||
|
||||
# If test passes, run the main puzzle
|
||||
grid = read_grid("../input.txt")
|
||||
result = find_least_heat_loss(grid)
|
||||
print(f"Least heat loss for the main puzzle: {result}")
|
||||
except Exception as e:
|
||||
print(f"Error occurred: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
13
Day17/test.txt
Normal file
13
Day17/test.txt
Normal file
@ -0,0 +1,13 @@
|
||||
2413432311323
|
||||
3215453535623
|
||||
3255245654254
|
||||
3446585845452
|
||||
4546657867536
|
||||
1438598798454
|
||||
4457876987766
|
||||
3637877979653
|
||||
4654967986887
|
||||
4564679986453
|
||||
1224686865563
|
||||
2546548887735
|
||||
4322674655533
|
10
README.md
10
README.md
@ -3,8 +3,8 @@
|
||||
<div><img src="title_image.png" style="margin: 0 auto;" height="300" width="300" ></div>
|
||||
|
||||
![Build Status](https://github.com/wieerwill/advent_of_code_2023/actions/workflows/lint.yml/badge.svg)
|
||||
![Completed](https://img.shields.io/badge/days%20completed-15-red)
|
||||
![Stars](https://img.shields.io/badge/stars%20⭐-29-yellow)
|
||||
![Completed](https://img.shields.io/badge/days%20completed-17-red)
|
||||
![Stars](https://img.shields.io/badge/stars%20⭐-34-yellow)
|
||||
![License](https://img.shields.io/github/license/wieerwill/advent_of_code_2023.svg)
|
||||
|
||||
Welcome to my repository where I share my solutions for the [Advent of Code 2023](https://adventofcode.com/2023). Advent of Code is an annual online event where participants solve a series of programming puzzles released daily from December 1st until December 25th. Each puzzle is a fun and unique challenge designed to test problem-solving skills.
|
||||
@ -49,9 +49,9 @@ I aim to complete each day's puzzle on the same day, but as with any challenge,
|
||||
| 13 | ✅ | ✅ | [Day13 README](/Day13/README.md) |
|
||||
| 14 | ✅ | ❓ | [Day14 README](/Day14/README.md) |
|
||||
| 15 | ✅ | ✅ | [Day15 README](/Day15/README.md) |
|
||||
| 16 | ❓ | ❓ | [Day16 README](/Day16/README.md) |
|
||||
| 17 | ❓ | ❓ | [Day17 README](/Day17/README.md) |
|
||||
| 18 | ❓ | ❓ | [Day18 README](/Day18/README.md) |
|
||||
| 16 | ✅ | ✅ | [Day16 README](/Day16/README.md) |
|
||||
| 17 | ✅ | ❓ | [Day17 README](/Day17/README.md) |
|
||||
| 18 | ✅ | ✅ | [Day18 README](/Day18/README.md) |
|
||||
| 19 | ❓ | ❓ | [Day19 README](/Day19/README.md) |
|
||||
| 20 | ❓ | ❓ | [Day20 README](/Day20/README.md) |
|
||||
| 21 | ❓ | ❓ | [Day21 README](/Day21/README.md) |
|
||||
|
Loading…
Reference in New Issue
Block a user