From 838b1f7661e9b29e0cc226892fbb7f4c561398a7 Mon Sep 17 00:00:00 2001 From: Joseph Chamochumbi Date: Fri, 17 Dec 2021 08:21:34 +0100 Subject: [PATCH] feat: Solution Day 17, :star: :star2: w/ Rust and TypeScript --- 2021/day-17/Cargo.toml | 9 ++++ 2021/day-17/src/main.rs | 92 +++++++++++++++++++++++++++++++++++ 2021/deno/day-17.ts | 103 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 204 insertions(+) create mode 100644 2021/day-17/Cargo.toml create mode 100644 2021/day-17/src/main.rs create mode 100644 2021/deno/day-17.ts diff --git a/2021/day-17/Cargo.toml b/2021/day-17/Cargo.toml new file mode 100644 index 0000000..806ac37 --- /dev/null +++ b/2021/day-17/Cargo.toml @@ -0,0 +1,9 @@ +[package] +authors = ["Joseph Chamochumbi "] +edition = "2018" +name = "day-17" +version = "0.1.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +aoc = {git = "https://github.com/icyJoseph/advent-of-code.git"} diff --git a/2021/day-17/src/main.rs b/2021/day-17/src/main.rs new file mode 100644 index 0000000..57e1afe --- /dev/null +++ b/2021/day-17/src/main.rs @@ -0,0 +1,92 @@ +use aoc; + +fn solve(raw: String) -> () { + let spec = raw + .trim() + .replace("target area: ", "") + .split(", ") + .map(|entry| { + let coord = entry.split("=").collect::>()[1]; + let ranges = coord + .split("..") + .map(|n| parse_num::(n)) + .collect::>(); + ranges + }) + .collect::>>(); + + let lower_y = spec[1][0]; + + let initial_dy = lower_y.abs() - 1; + + let max_y = initial_dy * (initial_dy + 1) / 2; + + println!("Part One: {:?}", max_y); + + let lower_x = spec[0][0]; + + let upper_x = spec[0][1]; + let upper_y = spec[1][1]; + + let min_dx = { + let mut value = 0; + + loop { + if value * (value + 1) > 2 * lower_x { + break; + } + value += 1; + } + + value + }; + + use std::collections::HashSet; + + let mut initial: HashSet<(isize, isize)> = HashSet::new(); + + let x_range = lower_x..=upper_x; + let y_range = lower_y..=upper_y; + + for dx in min_dx..=upper_x { + for dy in lower_y..=lower_y.abs() { + let mut velocity = [dx, dy]; + let mut position = [0, 0]; + + loop { + if x_range.contains(&position[0]) && y_range.contains(&position[1]) { + initial.insert((dx, dy)); + } + + if velocity[0] == 0 { + if !x_range.contains(&position[0]) { + break; + } + } + + if position[1] < lower_y && velocity[1] < 0 { + break; + } + + position = [position[0] + velocity[0], position[1] + velocity[1]]; + + velocity = [velocity[0] - velocity[0].signum(), velocity[1] - 1]; + } + } + } + println!("Part Two: {:?}", initial.len()); +} + +fn main() { + let input = aoc::get_input(2021, 17); + + solve(input); +} + +// Utilities +fn parse_num(str: &str) -> T { + match str.trim().parse::() { + Ok(n) => n, + _ => panic!("Error parsing"), + } +} diff --git a/2021/deno/day-17.ts b/2021/deno/day-17.ts new file mode 100644 index 0000000..c5ccd13 --- /dev/null +++ b/2021/deno/day-17.ts @@ -0,0 +1,103 @@ +const input = await Deno.readTextFile("./input/day-17.in"); +// const input = await Deno.readTextFile("./input/example.in"); + +const target = input + .replace("target area: ", "") + .split(", ") + .map((range) => range.split("=")[1].split("..").map(Number)); + +const [xRange, yRange] = target; + +type Position = { x: number; y: number }; +type Velocity = { dx: number; dy: number }; + +const updatePosition = (position: Position, velocity: Velocity): Position => { + return { + x: position.x + velocity.dx, + y: position.y + velocity.dy + }; +}; + +const updateVelocity = (velocity: Velocity): Velocity => { + // drag effect + const dx = velocity.dx - Math.sign(velocity.dx); + // gravity + const dy = velocity.dy - 1; + return { dx, dy }; +}; + +const inRange = (range: number[], coord: number) => { + return coord >= range[0] && coord <= range[1]; +}; + +const inTargetArea = ( + xRange: number[], + yRange: number[], + position: Position +) => { + const inYArea = position.y >= yRange[0] && position.y <= yRange[1]; + const inXArea = position.x >= xRange[0] && position.x <= xRange[1]; + + return inYArea && inXArea; +}; + +let minDx = 0; + +while (1) { + if ((minDx * (minDx + 1)) / 2 > xRange[0]) { + break; + } + minDx = minDx + 1; +} + +const maxDx = xRange[1]; + +const initialDy = Math.abs(yRange[0]) - 1; + +const maxY = (initialDy * (initialDy + 1)) / 2; + +/** + * Part One + */ +console.log("Part One:", maxY); + +/** + * Part Two + */ + +const initial: Set = new Set(); + +for (let dx = minDx; dx <= maxDx; dx++) { + for (let dy = yRange[0]; dy <= -yRange[0]; dy++) { + const init = `${dx}.${dy}`; + let velocity = { dx, dy }; + let position = { x: 0, y: 0 }; + + while (1) { + if (inTargetArea(xRange, yRange, position)) { + initial.add(init); + + break; + } + + if ( + (velocity.dx === 0 && position.x < xRange[0]) || + position.x > xRange[1] + ) { + // falling down out of the target + break; + } + + if (position.y < yRange[0] && velocity.dy < 0) { + // falling down out of the target + break; + } + + position = updatePosition(position, velocity); + // update speed + velocity = updateVelocity(velocity); + } + } +} + +console.log("Part Two:", initial.size);