This commit is contained in:
parent
d2f0553716
commit
ad781231e9
1
input/day17
Normal file
1
input/day17
Normal file
|
@ -0,0 +1 @@
|
|||
target area: x=277..318, y=-92..-53
|
105
src/day17.rs
Normal file
105
src/day17.rs
Normal file
|
@ -0,0 +1,105 @@
|
|||
use std::cmp::Ordering;
|
||||
use crate::Day;
|
||||
|
||||
pub struct Day17 {
|
||||
x_min: i32,
|
||||
x_max: i32,
|
||||
y_min: i32,
|
||||
y_max: i32,
|
||||
}
|
||||
|
||||
impl Day for Day17 {
|
||||
fn init(content: String) -> anyhow::Result<Self> {
|
||||
let c = content.split(' ').skip(1).collect::<Vec<_>>();
|
||||
let (x_min, x_max) = c[1][2..(c[1].len() - 1)].split_once("..").unwrap();
|
||||
let (y_min, y_max) = c[2][2..].split_once("..").unwrap();
|
||||
|
||||
Ok(Day17 {
|
||||
x_min: x_min.parse()?,
|
||||
x_max: x_max.parse()?,
|
||||
y_min: y_min.parse()?,
|
||||
y_max: y_max.parse()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn part1(&self) -> anyhow::Result<String> {
|
||||
let mut hits = Vec::new();
|
||||
for dx in 0..=self.x_max {
|
||||
for dy in -100..250 {
|
||||
let points = self.calc((dx, dy));
|
||||
if self.hits(&points) {
|
||||
hits.push(max_height(&points).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(format!("{}", hits.iter().max().unwrap()))
|
||||
}
|
||||
|
||||
fn part2(&self) -> anyhow::Result<String> {
|
||||
let mut hits = Vec::new();
|
||||
for dx in 0..=self.x_max {
|
||||
for dy in -100..250 {
|
||||
let points = self.calc((dx, dy));
|
||||
if self.hits(&points) {
|
||||
hits.push((dx, dy));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(format!("{}", hits.len()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Day17 {
|
||||
fn hits(&self, points: &[(i32, i32)]) -> bool {
|
||||
points.iter().any(|&(x, y)| x >= self.x_min && x <= self.x_max && y >= self.y_min && y <= self.y_max)
|
||||
}
|
||||
|
||||
fn calc(&self, initial_velocity: (i32, i32)) -> Vec<(i32, i32)> {
|
||||
let mut steps = vec![(0, 0)];
|
||||
let mut velocity = initial_velocity;
|
||||
|
||||
loop {
|
||||
let (x, y) = steps.last().unwrap();
|
||||
let (x, y) = (x + velocity.0, y + velocity.1);
|
||||
if x > self.x_max || y < self.y_min {
|
||||
break;
|
||||
}
|
||||
steps.push((x, y));
|
||||
match velocity.0.cmp(&0) {
|
||||
Ordering::Less => velocity.0 += 1,
|
||||
Ordering::Equal => {}
|
||||
Ordering::Greater => velocity.0 -= 1,
|
||||
}
|
||||
velocity.1 -= 1;
|
||||
}
|
||||
steps
|
||||
}
|
||||
}
|
||||
|
||||
fn max_height(points: &[(i32, i32)]) -> Option<i32> {
|
||||
points.iter().map(|&x| x.1).max()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{Day, day_tests};
|
||||
use crate::day17::Day17;
|
||||
|
||||
const INPUT: &str = "target area: x=20..30, y=-10..-5";
|
||||
|
||||
#[test]
|
||||
fn part1_test() -> anyhow::Result<()> {
|
||||
let d = Day17::init(INPUT.to_string())?;
|
||||
assert_eq!("45", d.part1()?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_test() -> anyhow::Result<()> {
|
||||
let d = Day17::init(INPUT.to_string())?;
|
||||
assert_eq!("112", d.part2()?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
day_tests!(Day17, "17", "4186", "2709");
|
||||
}
|
|
@ -19,6 +19,7 @@ use crate::day13::Day13;
|
|||
use crate::day14::Day14;
|
||||
use crate::day15::Day15;
|
||||
use crate::day16::Day16;
|
||||
use crate::day17::Day17;
|
||||
|
||||
mod day;
|
||||
mod day01;
|
||||
|
@ -37,6 +38,7 @@ mod day13;
|
|||
mod day14;
|
||||
mod day15;
|
||||
mod day16;
|
||||
mod day17;
|
||||
|
||||
fn load_input(day: &str) -> Result<String> {
|
||||
read_to_string(format!("./input/day{}", day)).map_err(|x| x.into())
|
||||
|
@ -87,7 +89,8 @@ fn main() -> anyhow::Result<()> {
|
|||
Box::new(Day13::init(load_input("13")?)?),
|
||||
Box::new(Day14::init(load_input("14")?)?),
|
||||
Box::new(Day15::init(load_input("15")?)?),
|
||||
Box::new(Day16::init(load_input("16")?)?),];
|
||||
Box::new(Day16::init(load_input("16")?)?),
|
||||
Box::new(Day17::init(load_input("17")?)?),];
|
||||
|
||||
let _verbosity = matches.occurrences_of("v");
|
||||
if matches.is_present("all") {
|
||||
|
|
Loading…
Reference in a new issue