Solved 2024/13 P1

This commit is contained in:
FrederikBaerentsen 2024-12-13 21:42:53 +01:00
parent f4bc6772f7
commit 2926202888
5 changed files with 209 additions and 48 deletions

View File

@ -14,33 +14,27 @@ input_f = 'input'
# # # #
######################################### #########################################
def get_neighbors(grid,node,visited): directions = {
#print('@',node,' - Visited',visited) 'up': (-1, 0),
'down': (1, 0),
'left': (0, -1),
'right': (0, 1),
}
directions = ['up','down','left','right'] def get_neighbors(grid,node,visited):
offsets = {
'up': (-1, 0),
'down': (1, 0),
'left': (0, -1),
'right': (0, 1),
}
neighbors = [] neighbors = []
for d in directions: for d in directions.keys():
t = get_value_in_direction(grid,node) t = get_value_in_direction(grid,node)
if get_value_in_direction(grid,node,d) == t: if get_value_in_direction(grid,node,d) == t:
n = addTuples(offsets[d],node) n = addTuples(directions[d],node)
if n not in visited: if n not in visited:
neighbors.append(n) neighbors.append(n)
#print(n)
visited.append(n) visited.append(n)
neighbors+=get_neighbors(grid,n,visited) neighbors+=get_neighbors(grid,n,visited)
return neighbors return neighbors
def part1(): def part1():
grid = toGrid(input_f) grid = toGrid(input_f)
#nprint(grid)
values = {}
visited = [] visited = []
total_plots = [] total_plots = []
for r,row in enumerate(grid): for r,row in enumerate(grid):
@ -54,20 +48,15 @@ def part1():
plot += x plot += x
if pos not in plot: if pos not in plot:
plot.append(pos) plot.append(pos)
if current not in values:
values[current] = []
total_plots.append(plot) total_plots.append(plot)
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
result = 0 result = 0
for v in total_plots: for v in total_plots:
sides = 0 sides = 0
for x,y in v: for x,y in v:
for dx, dy in directions.values():
for dx, dy in directions:
neighbor = (x + dx, y + dy) neighbor = (x + dx, y + dy)
if neighbor in v: if neighbor in v:
sides += 1 sides += 1
@ -88,29 +77,6 @@ print('Part 1:',part1(), '\t', round((time.time() - start_time)*1000), 'ms')
# # # #
######################################### #########################################
def get_neighbors_and_corners(grid,node,visited):
directions = ['up','down','left','right']
offsets = {
'up': (-1, 0),
'down': (1, 0),
'left': (0, -1),
'right': (0, 1),
}
neighbors = []
for d in directions:
if get_value_in_direction(grid,node,d) == get_value_in_direction(grid,node):
n = addTuples(offsets[d],node)
if n not in visited:
neighbors.append(n)
visited.append(n)
neighbors += get_neighbors_and_corners(grid,n,visited)
return neighbors
def rotate_90_clockwise(grid:list) -> list:
return [list(row) for row in zip(*grid[::-1])]
def part2(): def part2():
grid = toGrid(input_f) grid = toGrid(input_f)
#print(grid) #print(grid)
@ -126,7 +92,7 @@ def part2():
current = get_value_in_direction(grid,pos) current = get_value_in_direction(grid,pos)
if pos not in visited: if pos not in visited:
x = get_neighbors_and_corners(grid,pos,visited) x = get_neighbors(grid,pos,visited)
plot += x plot += x
if pos not in plot: if pos not in plot:
plot.append(pos) plot.append(pos)

126
2024/13/13.md Normal file
View File

@ -0,0 +1,126 @@
## \-\-- Day 13: Claw Contraption \-\--
Next up: the [lobby](/2020/day/24) of a resort on a tropical island. The
Historians take a moment to admire the hexagonal floor tiles before
spreading out.
Fortunately, it looks like the resort has a new
[arcade](https://en.wikipedia.org/wiki/Amusement_arcade)! Maybe you can
win some prizes from the [claw
machines](https://en.wikipedia.org/wiki/Claw_machine)?
The claw machines here are a little unusual. Instead of a joystick or
directional buttons to control the claw, these machines have two buttons
labeled `A` and `B`. Worse, you can\'t just put in a token and play; it
costs *3 tokens* to push the `A` button and *1 token* to push the `B`
button.
With a little experimentation, you figure out that each machine\'s
buttons are configured to move the claw a specific amount to the *right*
(along the `X` axis) and a specific amount *forward* (along the `Y`
axis) each time that button is pressed.
Each machine contains one *prize*; to win the prize, the claw must be
positioned *exactly* above the prize on both the `X` and `Y` axes.
You wonder: what is the smallest number of tokens you would have to
spend to win as many prizes as possible? You assemble a list of every
machine\'s button behavior and prize location (your puzzle input). For
example:
Button A: X+94, Y+34
Button B: X+22, Y+67
Prize: X=8400, Y=5400
Button A: X+26, Y+66
Button B: X+67, Y+21
Prize: X=12748, Y=12176
Button A: X+17, Y+86
Button B: X+84, Y+37
Prize: X=7870, Y=6450
Button A: X+69, Y+23
Button B: X+27, Y+71
Prize: X=18641, Y=10279
This list describes the button configuration and prize location of four
different claw machines.
For now, consider just the first claw machine in the list:
- Pushing the machine\'s `A` button would move the claw `94` units
along the `X` axis and `34` units along the `Y` axis.
- Pushing the `B` button would move the claw `22` units along the `X`
axis and `67` units along the `Y` axis.
- The prize is located at `X=8400`, `Y=5400`; this means that from the
claw\'s initial position, it would need to move exactly `8400` units
along the `X` axis and exactly `5400` units along the `Y` axis to be
perfectly aligned with the prize in this machine.
The cheapest way to win the prize is by pushing the `A` button `80`
times and the `B` button `40` times. This would line up the claw along
the `X` axis (because `80*94 + 40*22 = 8400`) and along the `Y` axis
(because `80*34 + 40*67 = 5400`). Doing this would cost `80*3` tokens
for the `A` presses and
`40*1` for the `B` presses, a total of `280` tokens.
For the second and fourth claw machines, there is no combination of A
and B presses that will ever win a prize.
For the third claw machine, the cheapest way to win the prize is by
pushing the `A` button `38` times and the `B` button `86` times. Doing
this would cost a total of `200` tokens.
So, the most prizes you could possibly win is two; the minimum tokens
you would have to spend to win all (two) prizes is `480`.
You estimate that each button would need to be pressed *no more than
`100` times* to win a prize. How else would someone be expected to play?
Figure out how to win as many prizes as possible. *What is the fewest
tokens you would have to spend to win all possible prizes?*
Your puzzle answer was `30973`.
The first half of this puzzle is complete! It provides one gold star: \*
## \-\-- Part Two \-\-- {#part2}
As you go to win the first prize, you discover that the claw is nowhere
near where you expected it would be. Due to a unit conversion error in
your measurements, the position of every prize is actually
`10000000000000` higher on both the `X` and `Y` axis!
Add `10000000000000` to the `X` and `Y` position of every prize. After
making this change, the example above would now look like this:
Button A: X+94, Y+34
Button B: X+22, Y+67
Prize: X=10000000008400, Y=10000000005400
Button A: X+26, Y+66
Button B: X+67, Y+21
Prize: X=10000000012748, Y=10000000012176
Button A: X+17, Y+86
Button B: X+84, Y+37
Prize: X=10000000007870, Y=10000000006450
Button A: X+69, Y+23
Button B: X+27, Y+71
Prize: X=10000000018641, Y=10000000010279
Now, it is only possible to win a prize on the second and fourth claw
machines. Unfortunately, it will take *many more than `100` presses* to
do so.
Using the corrected prize coordinates, figure out how to win as many
prizes as possible. *What is the fewest tokens you would have to spend
to win all possible prizes?*
Answer:
Although it hasn\'t changed, you can still [get your puzzle
input](13/input).

69
2024/13/solution.py Normal file
View File

@ -0,0 +1,69 @@
#!/bin/python3
import sys,time,re
from sympy import *
from pprint import pprint
sys.path.insert(0, '../../')
from fred import list2int,get_re,nprint,lprint,loadFile
start_time = time.time()
input_f = 'input'
#########################################
# #
# Part 1 #
# #
#########################################
def part1():
instructions = []
with open(input_f) as file:
for line in file:
match = get_re(r".*X[\+|=](\d+), Y[\+|=](\d+)",line.rstrip())
if match:
instructions.append(list2int([match.group(1),match.group(2)]))
#print(instructions)
a_cost = 3
b_cost = 1
a = ()
b = ()
r = ()
x,y = symbols('x y',integer=True)
result = 0
for idx, inst in enumerate(instructions):
#print(inst)
if idx%3 == 0:
a = (inst[0],inst[1])
elif idx%3 == 1:
b = (inst[0],inst[1])
elif idx%3 == 2:
r = (inst[0],inst[1])
eq1 = Eq(a[0]*x + b[0]*y,r[0])
eq2 = Eq(a[1]*x + b[1]*y,r[1])
s = solve((eq1,eq2),(x,y))
#print(s)
if s:
result += s[x]*a_cost
result += s[y]*b_cost
#input()
return result
start_time = time.time()
print('Part 1:',part1(), '\t\t', round((time.time() - start_time)*1000), 'ms')
#########################################
# #
# Part 2 #
# #
#########################################
def part1():
return
start_time = time.time()
print('Part 2:',part1(), '\t\t', round((time.time() - start_time)*1000), 'ms')

Binary file not shown.

View File

@ -313,7 +313,7 @@ def grid_valid(x, y, grid):
cols = len(grid[0]) cols = len(grid[0])
return 0 <= x < rows and 0 <= y < cols return 0 <= x < rows and 0 <= y < cols
def get_re(pattern, str): def get_re(pattern, line):
""" """
Returns a match object if the pattern matches the string, else None. Returns a match object if the pattern matches the string, else None.
@ -327,10 +327,10 @@ def get_re(pattern, str):
Raises: Raises:
TypeError: If str is not a string. TypeError: If str is not a string.
""" """
if not isinstance(str, str): if not isinstance(line, str):
raise TypeError("Input string must be of type str.") raise TypeError("Input string must be of type str.")
match = re.match(pattern, str) match = re.match(pattern, line)
if match: if match:
return match return match
return None return None