Solved 2024/13 P1
This commit is contained in:
parent
f4bc6772f7
commit
2926202888
@ -14,33 +14,27 @@ input_f = 'input'
|
|||||||
# #
|
# #
|
||||||
#########################################
|
#########################################
|
||||||
|
|
||||||
def get_neighbors(grid,node,visited):
|
directions = {
|
||||||
#print('@',node,' - Visited',visited)
|
|
||||||
|
|
||||||
directions = ['up','down','left','right']
|
|
||||||
offsets = {
|
|
||||||
'up': (-1, 0),
|
'up': (-1, 0),
|
||||||
'down': (1, 0),
|
'down': (1, 0),
|
||||||
'left': (0, -1),
|
'left': (0, -1),
|
||||||
'right': (0, 1),
|
'right': (0, 1),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_neighbors(grid,node,visited):
|
||||||
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
126
2024/13/13.md
Normal 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
69
2024/13/solution.py
Normal 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.
6
fred.py
6
fred.py
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user