Skip to content

Commit

Permalink
feat: Solution Day 17, ⭐ 🌟 w/ Rust and TypeScript
Browse files Browse the repository at this point in the history
  • Loading branch information
icyJoseph committed Dec 17, 2021
1 parent e49d3d3 commit 838b1f7
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 0 deletions.
9 changes: 9 additions & 0 deletions 2021/day-17/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
authors = ["Joseph Chamochumbi <[email protected]>"]
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"}
92 changes: 92 additions & 0 deletions 2021/day-17/src/main.rs
Original file line number Diff line number Diff line change
@@ -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::<Vec<&str>>()[1];
let ranges = coord
.split("..")
.map(|n| parse_num::<isize>(n))
.collect::<Vec<isize>>();
ranges
})
.collect::<Vec<Vec<isize>>>();

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<T: std::str::FromStr>(str: &str) -> T {
match str.trim().parse::<T>() {
Ok(n) => n,
_ => panic!("Error parsing"),
}
}
103 changes: 103 additions & 0 deletions 2021/deno/day-17.ts
Original file line number Diff line number Diff line change
@@ -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<string> = 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);

0 comments on commit 838b1f7

Please sign in to comment.