[WIP] Day 17 part 1 solved

This commit is contained in:
2021-12-19 12:15:50 +01:00
parent da579fbfac
commit 2c3c1f8f08
3 changed files with 225 additions and 47 deletions

View File

@@ -7,7 +7,8 @@
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
"logs": "firebase functions:log",
"debug-day17": "ts-node src/day17.ts"
},
"engines": {
"node": "16"
@@ -24,6 +25,7 @@
"eslint-config-google": "^0.14.0",
"eslint-plugin-import": "^2.22.0",
"firebase-functions-test": "^0.2.0",
"ts-node": "^10.4.0",
"typescript": "^3.8.0"
},
"private": true

View File

@@ -2,58 +2,74 @@ import Day from "./day";
class Day17 implements Day {
// steps = 3
// y = 1 -> 1 + 0 + -1 = 0
// y = 2 -> 2 + 1 + 0 = 3
// y = 3 -> 3 + 2 + 1 = 6
// y = 4 -> 4 + 3 + 2 = 9
// y = 5 -> 5 + 4 + 3 = 12
// steps = 4
// y = 1 -> -2
// y = 2 -> 2
// y = 3 -> 6
// y = 4 -> 10
// y = 0
// steps = 1 -> 0 = 0
// steps = 2 -> 0 - 1 = -1
// steps = 3 -> 0 - 1 - 2 = -3
// steps = 4 -> 0 - 1- 2 - 3= -6
// steps = 5 -> 0-1-2-3-4 = -10
// steps = 6 -> 0-1-2-3-4-5 = -15
// v = -1 * x
// Theoretically, the displacement should be:
// s(t) = s_0 + v_0 t + 1/2 a t^2
// Filling that in for s_0 = 0 and a = -1, we get:
// s(t) = v_0 t - 1/2 t ^ 2
// But that gives us non-integer values, for example when t = 3, we get: v_0 * 3 - 4.5
part1(input: string[]): number | string {
const targetArea = TargetArea.parse(input[0]);
// 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++) {
// Assuming v_y0 > 0, the maximum height the probe reaches is triangle(y).
// After reaching the top, the probe starts falling back down, taking "v_y0" steps to get back to a height of 0.
// After that it has a speed of v_y0 - 1.
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++) {
// steps = 3
// y = 1 -> 1 + 0 + -1 = 0
// y = 2 -> 2 + 1 + 0 = 3
// y = 3 -> 3 + 2 + 1 = 6
// y = 4 -> 4 + 3 + 2 = 9
// y = 5 -> 5 + 4 + 3 = 12
// Note that the triangle value of x must be at least the minimal x of the target area, otherwise the probe won't
// reach the target area before it's velocity reaches zero:
const vx0_min = this.triangleInvCeil(targetArea.minX);
// Calculate the x-position we reach after v_x0 steps:
const x_min = this.triangle(vx0_min);
// steps = 4
// y = 1 -> -2
// y = 2 -> 2
// y = 3 -> 6
// y = 4 -> 10
// y = 0
// steps = 1 -> 0 = 0
// steps = 2 -> 0 - 1 = -1
// steps = 3 -> 0 - 1 - 2 = -3
// steps = 4 -> 0 - 1- 2 - 3= -6
// steps = 5 -> 0-1-2-3-4 = -10
// steps = 6 -> 0-1-2-3-4-5 = -15
// v = -1 * x
// pos = -.5 * steps^2 + y * steps
// f(s) = s * y +
}
const { maxY, finalY } = this.simulateY()
} else if ( curPosX > targetArea.maxX || (curSpeed === 0 && curPosX < targetArea.minX)) {
break;
}
curSpeed--;
}
if (targetArea.isInX(x_min)) {
// We have an x-speed that reaches the target area in x_min steps and stays there (e.g. reaches velocity zero in the target area),
// so we can just find the biggest y that at some point ends up in the target area.
// We already know that the y speed when the "probe" comes down is:
// -v_y0 - 1
// So if we choose as starting y that is one higher than the minimal y value, we end up in the bottom of the target area, while reaching the maximum height:
const vy0_max = Math.abs(targetArea.minY) - 1;
return this.triangle(vy0_max);
} else {
throw Error("fuck :)");
}
return 0;
}
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]);
// TODO implement
return 0;
}
simulateY(initialSpeedY: number, steps: number): { maxY: number, finalY: number} {
let curSpeed = initialSpeedY;
@@ -69,9 +85,12 @@ class Day17 implements Day {
return { finalY: y, maxY: maxY };
}
part2(input: string[]): number | string {
// TODO implement
return 0;
triangle(n: number): number {
return (n*(n + 1)) / 2;
}
triangleInvCeil(x: number): number {
return Math.ceil((Math.sqrt(8 * x + 1) - 1) / 2);
}
}
@@ -121,3 +140,75 @@ class TargetArea {
}
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--;
// }
// }

View File

@@ -23,6 +23,18 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
"@cspotcode/source-map-consumer@0.8.0":
version "0.8.0"
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b"
integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==
"@cspotcode/source-map-support@0.7.0":
version "0.7.0"
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5"
integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==
dependencies:
"@cspotcode/source-map-consumer" "0.8.0"
"@eslint/eslintrc@^0.4.3":
version "0.4.3"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
@@ -278,6 +290,26 @@
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
"@tsconfig/node10@^1.0.7":
version "1.0.8"
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9"
integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==
"@tsconfig/node12@^1.0.7":
version "1.0.9"
resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c"
integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==
"@tsconfig/node14@^1.0.0":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2"
integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==
"@tsconfig/node16@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e"
integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==
"@types/body-parser@*":
version "1.19.2"
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0"
@@ -474,11 +506,21 @@ acorn-jsx@^5.3.1:
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
acorn-walk@^8.1.1:
version "8.2.0"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
acorn@^7.4.0:
version "7.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
acorn@^8.4.1:
version "8.6.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895"
integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==
agent-base@6:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
@@ -530,6 +572,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"
arg@^4.1.0:
version "4.1.3"
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
argparse@^1.0.7:
version "1.0.10"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
@@ -745,6 +792,11 @@ cors@^2.8.5:
object-assign "^4"
vary "^1"
create-require@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
cross-spawn@^7.0.2:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
@@ -814,6 +866,11 @@ dicer@^0.3.0:
dependencies:
streamsearch "0.1.2"
diff@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
doctrine@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
@@ -1903,6 +1960,11 @@ make-dir@^3.0.0:
dependencies:
semver "^6.0.0"
make-error@^1.1.1:
version "1.3.6"
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
@@ -2515,6 +2577,24 @@ tr46@~0.0.3:
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
ts-node@^10.4.0:
version "10.4.0"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7"
integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==
dependencies:
"@cspotcode/source-map-support" "0.7.0"
"@tsconfig/node10" "^1.0.7"
"@tsconfig/node12" "^1.0.7"
"@tsconfig/node14" "^1.0.0"
"@tsconfig/node16" "^1.0.2"
acorn "^8.4.1"
acorn-walk "^8.1.1"
arg "^4.1.0"
create-require "^1.1.0"
diff "^4.0.1"
make-error "^1.1.1"
yn "3.1.1"
tsconfig-paths@^3.11.0:
version "3.12.0"
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz#19769aca6ee8f6a1a341e38c8fa45dd9fb18899b"
@@ -2740,6 +2820,11 @@ yargs@^16.1.1:
y18n "^5.0.5"
yargs-parser "^20.2.2"
yn@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"