-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Solution Day 17, ⭐ 🌟 w/ Rust and TypeScript
- Loading branch information
Showing
3 changed files
with
204 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); |