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