From 5d54a107d411e9c75f4546e01b9d068051711682 Mon Sep 17 00:00:00 2001 From: Bas Dado Date: Sun, 19 Dec 2021 14:53:25 +0100 Subject: [PATCH] [TASK] Cleaned up (and improved the performance a little) for day 17 --- functions/src/day17.ts | 141 +++----------------------------------- input/day/17-example.http | 6 ++ input/day/17.http | 6 ++ 3 files changed, 21 insertions(+), 132 deletions(-) create mode 100644 input/day/17-example.http create mode 100644 input/day/17.http diff --git a/functions/src/day17.ts b/functions/src/day17.ts index 2c31e8e..f4ae263 100644 --- a/functions/src/day17.ts +++ b/functions/src/day17.ts @@ -53,22 +53,24 @@ class Day17 implements Day { part2(input: string[]): number | string { - // So that means that the only y values that work are those for which two triangle numbers exists, between which the distance falls - // in the target area. - // Following this reasoning, we also know that y is inside the target area after (2 * v_y0) + { the number of triangle numbers between triangle(vy_0) and triangle(?) in y_range) } - const targetArea = TargetArea.parse(input[0]); const v_x0_min = Day17.triangleInvCeil(targetArea.minX); const v_x0_max_static = Day17.triangleInvFloor(targetArea.maxX); - // const maxYSteps0 = Day17.triangleInvCeil(Math.abs(targetArea.minY)); + const maxYStepsBelowZero = Day17.triangleInvCeil(Math.abs(targetArea.minY)); let solutionCount = 0; for (let v_x0 = v_x0_min; v_x0 <= targetArea.maxX; v_x0++) { - const maxSteps = v_x0 <= v_x0_max_static ? 1000 : v_x0_max_static; for (let v_y0 = targetArea.minY; v_y0 < Math.abs(targetArea.minY); v_y0++) { - for (let steps = 1; steps < maxSteps; steps++) { + + // If v_x0 <= v_x0_max_static, we end up in a position where eventually all x-es fall in the valid range + // So in that case, we base the max steps on the y values. + const maxSteps = v_x0 <= v_x0_max_static + ? (v_y0 < 0 ? maxYStepsBelowZero : 2 * v_y0 + 1 + maxYStepsBelowZero) + : v_x0_max_static; + + for (let steps = 1; steps <= maxSteps; steps++) { const xRangeResult = this.isInXAfterSteps(v_x0, steps, targetArea); if (xRangeResult === RangeResult.TOO_HIGH) { break; @@ -86,55 +88,6 @@ class Day17 implements Day { } return solutionCount; - // // We gonna have to semi-brute-force anyway, - // - // // But first, let's find all x-es that perpetually stay inside the target area - // const v_x0_min = Day17.triangleInvCeil(targetArea.minX); - // const v_x0_max_static = Day17.triangleInvFloor(targetArea.maxX); - // - // // const vxStaticCount = (v_x0_max_static - v_x0_min) + 1; - // // - // // Then we count all y's that end up in the target area after v_x0_min steps - // // Note that any - // // if (v_x0_min * 2 + 1 > Math.abs(targetArea.maxY) + 1); - // let vyStaticCount = 0; - // // With a start y speed of 0, we can stay in the target area for at most this many steps: - // const maxYSteps0 = Day17.triangleInvCeil(Math.abs(targetArea.minY)); - // - // for (let vy_0 = targetArea.minY; vy_0 < Math.abs(targetArea.minY); vy_0++) { - // const minSteps = vy_0 > 0 ? Math.max(v_x0_min, 2 * vy_0 + 1) : v_x0_min; - // const maxSteps = vy_0 > 0 ? minSteps + maxYSteps0 : maxYSteps0; - // for (let steps = minSteps; steps < maxSteps; steps++) { - // const rangeResult = this.isInYAfterSteps(vy_0, steps, targetArea); - // if (rangeResult === RangeResult.YES) { - // vyStaticCount++; - // break; - // } else if (rangeResult === RangeResult.TOO_LOW) { - // // We've fallen below the target area, no need to scan this range any further - // break; - // } - // } - // } - // - // const staticSolutions = (v_x0_max_static - v_x0_min + 1) * vyStaticCount; - // - // // Any more numbers of steps will overshoot the x direction - // let dynamicSolutions = 0; - // for (let steps = 1; steps <= v_x0_max_static; steps++) { - // for (let vx_0 = v_x0_min; vx_0 < targetArea.maxX + 1; vx_0++) { - // if (this.isInXAfterSteps(vx_0, steps, targetArea) !== RangeResult.YES) continue; - // for (let vy_0 = targetArea.minY; vy_0 < Math.abs(targetArea.minY) - 1; vy_0++) { - // const rangeResult = this.isInYAfterSteps(vy_0, steps, targetArea); - // if (rangeResult === RangeResult.YES) { - // dynamicSolutions++; - // } else if (rangeResult === RangeResult.TOO_HIGH) { - // // We've fallen below the target area - // break; - // } - // } - // } - // } - // return dynamicSolutions + staticSolutions; } isInXAfterSteps(v_x0: number, steps: number, targetArea: TargetArea): RangeResult { @@ -241,82 +194,6 @@ class TargetArea { else if (y > this.maxY) return RangeResult.TOO_HIGH; else return RangeResult.YES; } - - isIn(x: number, y: number): boolean { - return this.isInX(x) === RangeResult.YES && this.isInY(y) === RangeResult.YES; - } } export default Day17; - -const exampleInput = ["target area: x=20..30, y=-10..-5"]; -run(exampleInput); - -const input = ["target area: x=48..70, y=-189..-148"]; -run(input); - - -function run(input: string[]) { - const day = new Day17(); - console.log(`Part 1: ${day.part1(input)}`); - console.log(`Part 2: ${day.part2(input)}`); -} - - -// Archive: - -// const maxYs: number[] = []; -// const yMinStepInTargets = []; -// const yMaxStepInTargets = []; -// // Array(100).fill([]); -// // Let's first find the y values that reach the highest height and end up in the target area: -// for (let vy0 = 0; vy0 < Math.abs(targetArea.minY) + 1; vy0++) { -// -// let y = 0; -// const ys = [y]; -// let vy = vy0; -// let yMinStepInTarget = -1; -// let yMaxStepInTarget = -1; -// let step = 0; -// while (y > targetArea.minY) { -// y += vy; -// ys.push(y); -// vy--; -// if (targetArea.isInY(y)) { -// if (yMinStepInTarget === -1) { -// yMinStepInTarget = step; -// } -// yMaxStepInTarget = step; -// } -// step++; -// } -// yMinStepInTargets.push(yMinStepInTarget) -// yMaxStepInTargets.push(yMaxStepInTarget) -// // yCache.push(ys); -// maxYs.push(Math.max(...ys)); -// } -// -// // Now we "greedily" go over the found y values -// -// // First we find all x-es between 1 and maxX + 1 (as all others will immediately overshoot), that overlap with the target at some points: -// for (let x = 1; x <= targetArea.maxX + 1; x++) { -// let curSpeed = x; -// let curPosX = 0; -// for (let step = 0; step < (targetArea.maxX + 1) / x; step++) { -// -// curPosX += curSpeed; -// if (targetArea.isInX(curPosX)) { -// // Find y's that given this position and step, match: -// // TODO: find out which y's make sense to check -// for (let y = 0; y < 100; y++) { -// -// -// // f(s) = s * y + -// } -// const { maxY, finalY } = this.simulateY() -// } else if ( curPosX > targetArea.maxX || (curSpeed === 0 && curPosX < targetArea.minX)) { -// break; -// } -// curSpeed--; -// } -// } diff --git a/input/day/17-example.http b/input/day/17-example.http new file mode 100644 index 0000000..50b3361 --- /dev/null +++ b/input/day/17-example.http @@ -0,0 +1,6 @@ +POST http://localhost:5001/advent-of-code-2021-911a8/europe-west1/day-17 +Content-Type: text/plain + +target area: x=20..30, y=-10..-5 + +### diff --git a/input/day/17.http b/input/day/17.http new file mode 100644 index 0000000..4f31676 --- /dev/null +++ b/input/day/17.http @@ -0,0 +1,6 @@ +POST http://localhost:5001/advent-of-code-2021-911a8/europe-west1/day-17 +Content-Type: text/plain + +target area: x=48..70, y=-189..-148 + +###