summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--data/2021/17.txt1
-rw-r--r--src/2021/17/mod.rs88
-rw-r--r--src/2021/mod.rs4
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)),
}