From c975128587c4509b595774497f60f4a5b0bac574 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Tue, 21 Dec 2021 09:43:50 -0700 Subject: [PATCH] Add day17 problem + solution --- day17/input.txt | 1 + day17/p1.nim | 69 +++++++++++++++++++++++++ day17/p2.nim | 54 ++++++++++++++++++++ day17/prob.md | 122 ++++++++++++++++++++++++++++++++++++++++++++ day17/testinput.txt | 1 + 5 files changed, 247 insertions(+) create mode 100644 day17/input.txt create mode 100644 day17/p1.nim create mode 100644 day17/p2.nim create mode 100644 day17/prob.md create mode 100644 day17/testinput.txt diff --git a/day17/input.txt b/day17/input.txt new file mode 100644 index 0000000..480448f --- /dev/null +++ b/day17/input.txt @@ -0,0 +1 @@ +target area: x=48..70, y=-189..-148 diff --git a/day17/p1.nim b/day17/p1.nim new file mode 100644 index 0000000..3e52b54 --- /dev/null +++ b/day17/p1.nim @@ -0,0 +1,69 @@ +import os, math, sets +import std/[strutils, sequtils, strscans] + +proc calculateInitialVelocity(endSum: int): float = + # This is the inverse of S = N(N+1)/2 + # which is N = root(2*S + 1/4) - 1/2 + math.sqrt(2*endSum.float + 1/4) - 1/2 + +proc sum1toN(N: int): float = + N*(N+1)/2 + +proc main() = + let fileName = paramStr(1) + + let (_, lowerX, upperX, lowerY, _) = fileName.readFile().strip().scanTuple("target area: x=$i..$i, y=$i..$i") + + + # in order to maximize y, we must maximize X first + # we do this by calculating the exact value of the + # initial X velocity that will get us within lowerX..upperX + var xMaxSteps: HashSet[(int, int)] + + for x in lowerX .. upperX: + let initialXVel = calculateInitialVelocity(x) + # it's an integer with no floating point value + if (initialXVel - int(initialXVel).float) == 0: + xMaxSteps.incl((initialXVel.int, int(x.float - initialXVel))) + + + # This part involves a bit of math, but hear me out. In order to get the + # max height, we must get the max initial Y velocity because they are directly + # proportional to eachother. + # + # --- at the top, YVel = 0, numSteps = N(N+1)/2 because of the sum law + # + # / \ + # / \ + # / \ + # / \ + # / YVel = initYVel \ YVel = -initYVel + #--- y = 0 --------------- y = 0 ----------------- + # + # \ on the next step, y = -initVel - 1, + # and that means if we can still get within + # lowerY..upperY, we have found the max initYVel + # + # So this means that the max initYVel is + # + # lowerY = -initVel - 1, then solving for initVel, we get + # initVel = -lowerY - 1, for y < 0 and if maxStepsX <= numStepsY, since after maxStepsX + # x will never change again since it's velocity will be 0 + # + # maxStepsY = initYVel * 2 + 2 + # + # one +1 for the zero step at the top of the curve, and one for the last step + # from y = 0 to y = -initVel - 1 + + + let maxInitYVel = -lowerY - 1 + let maxStepsY = maxInitYVel*2 + 2 + + let allXStepsLowerEqual = xMaxSteps.allIt(it[1] <= maxStepsY) + + if allXStepsLowerEqual: + echo "Max height: ", maxInitYVel.sum1toN().int + else: + echo "Failure" + +main() diff --git a/day17/p2.nim b/day17/p2.nim new file mode 100644 index 0000000..416ae46 --- /dev/null +++ b/day17/p2.nim @@ -0,0 +1,54 @@ +import os +import std/[strutils, strscans] + +type + Velocity = tuple[x, y: int] + +proc main() = + let fileName = paramStr(1) + + let (_, lowerX, upperX, lowerY, upperY) = fileName.readFile().strip().scanTuple("target area: x=$i..$i, y=$i..$i") + + # The maximum value initXVel can be is upperX, since that will take only one step + # and will be within lowerX..upperX + # The min value initXVel can be is zero, since negative values will only move + # backwards + # + # The maximum value initYVel can be was found in p1, so we can just use it here + # The min value it can be is lowerY, if lowerX <= initXVel <= upperX + + let maxInitYVel = -lowerY - 1 + + var allPossibleVels: seq[Velocity] + + for xVel in 0 .. upperX: + block YBlock: + for yVel in countDown(maxInitYVel, lowerY): + var initVels = (x: xVel, y: yVel) + var currentPoint = (x: 0, y: 0) + + var vels = initVels + + while currentPoint.x < upperX and currentPoint.y > lowerY: + if vels.x == 0 and currentPoint.x < lowerX: + # Can't ever make it + break YBlock + if vels.y + currentPoint.y < lowerY: + # blow past the lowerY val + break + + currentPoint.x += vels.x + currentPoint.y += vels.y + + if currentPoint.x in lowerX..upperX and currentPoint.y in lowerY..upperY: + allPossibleVels.add(initVels) + break + + if vels.x > 0: + vels.x.dec + vels.y.dec + + + echo "Max pairs: ", allPossibleVels.len + +main() diff --git a/day17/prob.md b/day17/prob.md new file mode 100644 index 0000000..4ec0fcf --- /dev/null +++ b/day17/prob.md @@ -0,0 +1,122 @@ +--- Day 17: Trick Shot --- +You finally decode the Elves' message. HI, the message says. You continue searching for the sleigh keys. + +Ahead of you is what appears to be a large ocean trench. Could the keys have fallen into it? You'd better send a probe to investigate. + +The probe launcher on your submarine can fire the probe with any integer velocity in the x (forward) and y (upward, or downward if negative) directions. For example, an initial x,y velocity like 0,10 would fire the probe straight up, while an initial velocity like 10,-1 would fire the probe forward at a slight downward angle. + +The probe's x,y position starts at 0,0. Then, it will follow some trajectory by moving in steps. On each step, these changes occur in the following order: + +The probe's x position increases by its x velocity. +The probe's y position increases by its y velocity. +Due to drag, the probe's x velocity changes by 1 toward the value 0; that is, it decreases by 1 if it is greater than 0, increases by 1 if it is less than 0, or does not change if it is already 0. +Due to gravity, the probe's y velocity decreases by 1. +For the probe to successfully make it into the trench, the probe must be on some trajectory that causes it to be within a target area after any step. The submarine computer has already calculated this target area (your puzzle input). For example: + +target area: x=20..30, y=-10..-5 +This target area means that you need to find initial x,y velocity values such that after any step, the probe's x position is at least 20 and at most 30, and the probe's y position is at least -10 and at most -5. + +Given this target area, one initial velocity that causes the probe to be within the target area after any step is 7,2: + +.............#....#............ +.......#..............#........ +............................... +S........................#..... +............................... +............................... +...........................#... +............................... +....................TTTTTTTTTTT +....................TTTTTTTTTTT +....................TTTTTTTT#TT +....................TTTTTTTTTTT +....................TTTTTTTTTTT +....................TTTTTTTTTTT +In this diagram, S is the probe's initial position, 0,0. The x coordinate increases to the right, and the y coordinate increases upward. In the bottom right, positions that are within the target area are shown as T. After each step (until the target area is reached), the position of the probe is marked with #. (The bottom-right # is both a position the probe reaches and a position in the target area.) + +Another initial velocity that causes the probe to be within the target area after any step is 6,3: + +...............#..#............ +...........#........#.......... +............................... +......#..............#......... +............................... +............................... +S....................#......... +............................... +............................... +............................... +.....................#......... +....................TTTTTTTTTTT +....................TTTTTTTTTTT +....................TTTTTTTTTTT +....................TTTTTTTTTTT +....................T#TTTTTTTTT +....................TTTTTTTTTTT +Another one is 9,0: + +S........#..................... +.................#............. +............................... +........................#...... +............................... +....................TTTTTTTTTTT +....................TTTTTTTTTT# +....................TTTTTTTTTTT +....................TTTTTTTTTTT +....................TTTTTTTTTTT +....................TTTTTTTTTTT +One initial velocity that doesn't cause the probe to be within the target area after any step is 17,-4: + +S.............................................................. +............................................................... +............................................................... +............................................................... +.................#............................................. +....................TTTTTTTTTTT................................ +....................TTTTTTTTTTT................................ +....................TTTTTTTTTTT................................ +....................TTTTTTTTTTT................................ +....................TTTTTTTTTTT..#............................. +....................TTTTTTTTTTT................................ +............................................................... +............................................................... +............................................................... +............................................................... +................................................#.............. +............................................................... +............................................................... +............................................................... +............................................................... +............................................................... +............................................................... +..............................................................# +The probe appears to pass through the target area, but is never within it after any step. Instead, it continues down and to the right - only the first few steps are shown. + +If you're going to fire a highly scientific probe out of a super cool probe launcher, you might as well do it with style. How high can you make the probe go while still reaching the target area? + +In the above example, using an initial velocity of 6,9 is the best you can do, causing the probe to reach a maximum y position of 45. (Any higher initial y velocity causes the probe to overshoot the target area entirely.) + +Find the initial velocity that causes the probe to reach the highest y position and still eventually be within the target area after any step. What is the highest y position it reaches on this trajectory? + +--- Part Two --- +Maybe a fancy trick shot isn't the best idea; after all, you only have one probe, so you had better not miss. + +To get the best idea of what your options are for launching the probe, you need to find every initial velocity that causes the probe to eventually be within the target area after any step. + +In the above example, there are 112 different initial velocity values that meet these criteria: + +23,-10 25,-9 27,-5 29,-6 22,-6 21,-7 9,0 27,-7 24,-5 +25,-7 26,-6 25,-5 6,8 11,-2 20,-5 29,-10 6,3 28,-7 +8,0 30,-6 29,-8 20,-10 6,7 6,4 6,1 14,-4 21,-6 +26,-10 7,-1 7,7 8,-1 21,-9 6,2 20,-7 30,-10 14,-3 +20,-8 13,-2 7,3 28,-8 29,-9 15,-3 22,-5 26,-8 25,-8 +25,-6 15,-4 9,-2 15,-2 12,-2 28,-9 12,-3 24,-6 23,-7 +25,-10 7,8 11,-3 26,-7 7,1 23,-9 6,0 22,-10 27,-6 +8,1 22,-8 13,-4 7,6 28,-6 11,-4 12,-4 26,-9 7,4 +24,-10 23,-8 30,-8 7,0 9,-1 10,-1 26,-5 22,-9 6,5 +7,5 23,-6 28,-10 10,-2 11,-1 20,-9 14,-2 29,-7 13,-3 +23,-5 24,-8 27,-9 30,-7 28,-5 21,-10 7,9 6,6 21,-5 +27,-10 7,2 30,-9 21,-8 22,-7 24,-9 20,-6 6,9 29,-5 +8,-2 27,-8 30,-5 24,-7 +How many distinct initial velocity values cause the probe to be within the target area after any step? diff --git a/day17/testinput.txt b/day17/testinput.txt new file mode 100644 index 0000000..a07e02d --- /dev/null +++ b/day17/testinput.txt @@ -0,0 +1 @@ +target area: x=20..30, y=-10..-5