diff options
-rw-r--r-- | data/2021/17.txt | 1 | ||||
-rw-r--r-- | src/2021/17/mod.rs | 88 | ||||
-rw-r--r-- | src/2021/mod.rs | 4 |
3 files changed, 93 insertions, 0 deletions
diff --git a/data/2021/17.txt b/data/2021/17.txt new file mode 100644 index 0000000..c115821 --- /dev/null +++ b/data/2021/17.txt @@ -0,0 +1 @@ +target area: x=179..201, y=-109..-63 diff --git a/src/2021/17/mod.rs b/src/2021/17/mod.rs new file mode 100644 index 0000000..5343360 --- /dev/null +++ b/src/2021/17/mod.rs @@ -0,0 +1,88 @@ +fn fire( + mut xv: i64, + mut yv: i64, + xrange: &std::ops::RangeInclusive<i64>, + yrange: &std::ops::RangeInclusive<i64>, +) -> Option<i64> { + let mut xpos = 0; + let mut ypos = 0; + let mut max_height = 0; + loop { + if xrange.contains(&xpos) && yrange.contains(&ypos) { + return Some(max_height); + } else if (xv >= 0 && xpos > *xrange.end()) + || (xv <= 0 && xpos < *xrange.start()) + || (ypos < *yrange.start()) + { + return None; + } + + xpos += xv; + ypos += yv; + if ypos > max_height { + max_height = ypos; + } + match xv.cmp(&0) { + std::cmp::Ordering::Greater => { + xv -= 1; + } + std::cmp::Ordering::Less => { + xv += 1; + } + _ => {} + } + yv -= 1; + } +} + +pub fn part1() -> anyhow::Result<i64> { + let rx = regex::Regex::new( + r"target area: x=(-?\d+)..(-?\d+), y=(-?\d+)..(-?\d+)", + ) + .unwrap(); + let line = data_lines!()?.next().unwrap(); + let captures = rx.captures(&line).unwrap(); + let xrange: std::ops::RangeInclusive<i64> = + captures[1].parse().unwrap()..=captures[2].parse().unwrap(); + let yrange: std::ops::RangeInclusive<i64> = + captures[3].parse().unwrap()..=captures[4].parse().unwrap(); + + let mut max_height = 0; + for xv in *xrange.start().min(&0)..=*xrange.end().max(&0) { + for yv in *yrange.start().min(&0) + ..=yrange.start().abs().max(yrange.end().abs()) + { + if let Some(height) = fire(xv, yv, &xrange, &yrange) { + if height > max_height { + max_height = height; + } + } + } + } + Ok(max_height) +} + +pub fn part2() -> anyhow::Result<i64> { + let rx = regex::Regex::new( + r"target area: x=(-?\d+)..(-?\d+), y=(-?\d+)..(-?\d+)", + ) + .unwrap(); + let line = data_lines!()?.next().unwrap(); + let captures = rx.captures(&line).unwrap(); + let xrange: std::ops::RangeInclusive<i64> = + captures[1].parse().unwrap()..=captures[2].parse().unwrap(); + let yrange: std::ops::RangeInclusive<i64> = + captures[3].parse().unwrap()..=captures[4].parse().unwrap(); + + let mut count = 0; + for xv in *xrange.start().min(&0)..=*xrange.end().max(&0) { + for yv in *yrange.start().min(&0) + ..=yrange.start().abs().max(yrange.end().abs()) + { + if fire(xv, yv, &xrange, &yrange).is_some() { + count += 1; + } + } + } + Ok(count) +} diff --git a/src/2021/mod.rs b/src/2021/mod.rs index e11a0ee..e31d57e 100644 --- a/src/2021/mod.rs +++ b/src/2021/mod.rs @@ -30,6 +30,8 @@ mod day14; mod day15; #[path = "16/mod.rs"] mod day16; +#[path = "17/mod.rs"] +mod day17; // NEXT MOD pub fn run(day: u8, puzzle: u8) -> anyhow::Result<i64> { @@ -66,6 +68,8 @@ pub fn run(day: u8, puzzle: u8) -> anyhow::Result<i64> { (15, 2) => day15::part2(), (16, 1) => day16::part1(), (16, 2) => day16::part2(), + (17, 1) => day17::part1(), + (17, 2) => day17::part2(), // NEXT PART _ => Err(anyhow::anyhow!("unknown puzzle {}-{}", day, puzzle)), } |