2021-12-17 - Trick Shot
(original .ipynb)
Day 17 puzzle input is a couple of x/y coordinate range pairs that describe a target box (mine is here). Part 1 involves calculating the highest y position you'd of a probe you chuck at this co-ordinate (there are some weird deceleration calcs given the initial x/y velocities you chuck the probe at). Part 2 involves finding the number of possible ways you can chuck the probe so that it hits the target range.
Really phoning it in today. Couldn't make my brain work and determine a suitable range of velocities to try so just totally busked it.
puzzle_input_str = "target area: x=119..176, y=-141..-84"
test_input_str = "target area: x=20..30, y=-10..-5"
def parse_range(range_str):
start, end = range_str.split("..")
return int(start), int(end)
def parse_input(input_str):
range_str = input_str.removeprefix("target area: ")
x_range, y_range = range_str.split(", ")
return parse_range(x_range.removeprefix("x=")), parse_range(y_range.removeprefix("y="))
def step_x_velocity(x_vel):
if x_vel > 0:
return x_vel - 1
elif x_vel < 0:
return x_vel + 1
return x_vel
def step_y_velocity(y_vel):
return y_vel - 1
def approaching_area(x, y, x_vel, y_vel, x_range, y_range):
x_min, x_max = x_range
y_min, y_max = y_range
above_and_sinking = x_vel == 0 and y > y_max
return above_and_sinking or any((
approaching_point(x, y, x_vel, y_vel, x_min, y_min),
approaching_point(x, y, x_vel, y_vel, x_min, y_max),
approaching_point(x, y, x_vel, y_vel, x_max, y_min),
approaching_point(x, y, x_vel, y_vel, x_max, y_max))
)
def probe_inside_target(x, y, x_range, y_range):
x_min, x_max = x_range
y_min, y_max = y_range
return x >= x_min and x <= x_max and y >= y_min and y <= y_max
def approaching_point(x, y, x_vel, y_vel, target_x, target_y):
approaching_x = abs(x - target_x) > abs(x + x_vel - target_x)
approaching_y = abs(y - target_y) > abs(y + y_vel - target_y)
return approaching_x or approaching_y
def test_velocity(x_range, y_range, x_vel, y_vel):
x, y = 0, 0
max_height = 0
while approaching_area(x, y, x_vel, y_vel, x_range, y_range):
if probe_inside_target(x, y, x_range, y_range):
return True, max_height
x += x_vel
y += y_vel
x_vel = step_x_velocity(x_vel)
y_vel = step_y_velocity(y_vel)
if y > max_height:
max_height = y
return probe_inside_target(x, y, x_range, y_range), max_height
def part_one(input_str):
x_range, y_range = parse_input(input_str)
max_height = 0
for x_vel in range(200):
for y_vel in range(500):
res, height = test_velocity(x_range, y_range, x_vel, y_vel)
if res and height > max_height:
max_height = height
return max_height
assert 45 == part_one(test_input_str)
print("part one:", part_one(puzzle_input_str))
part one: 9870
def part_two(input_str):
x_range, y_range = parse_input(input_str)
count = 0
for x_vel in range(500):
for y_vel in range(-200, 800):
res, _ = test_velocity(x_range, y_range, x_vel, y_vel)
if res:
count += 1
return count
assert 112 == part_two(test_input_str)
print("part two:", part_two(puzzle_input_str))
part two: 5523