From 8958ba9361cdc7f0299bbbf92a06bb64476f01fc Mon Sep 17 00:00:00 2001 From: Keenan Tims Date: Fri, 20 Dec 2024 23:20:14 -0800 Subject: [PATCH] day21: part 1 solution --- .aoc_tiles/tiles/2024/21.png | Bin 3283 -> 6539 bytes README.md | 5 +- src/day21.rs | 206 +++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 4 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 src/day21.rs diff --git a/.aoc_tiles/tiles/2024/21.png b/.aoc_tiles/tiles/2024/21.png index 1094c33b09a9603735019ae64679098cfa027b46..007aeb9c6756fffc8f6d42f8e3013873a0f9ef7a 100644 GIT binary patch literal 6539 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 literal 3283 zcmXX}cRX9)`%e`mW>wUzR;x;hQB)PJT1BcgLPV^fM(s_F{&6_Hnm~Z0h;lJ{u^HrtAgy_}lF>2PnXIBT#d~06g z>t0RPp0r3!PaRY@1v@k~9q`KA5jorBStH->HwHFaEa+sGg28ZCthgFf7x$#54s0R? z<-MC#7M zMbM|l#=xG$8@ARVAuYYO`J=+4M44sk8Jz5{;5ys5|9k!sLdJ^(13gBg7xyG3*7# zNH+r-E^KXWUG@mqi8PHsS)xCWMMW_j{#^6c`=}D!pDA6rJoH)Ziilo+fBz<#Y;~fl z?3tyR3j_dg(~ylN3B!D!_qRo=FJ+pG*xY1`L0j26;>8@ zCQ}7I?Te3za15SB2Yfl$+pDRo%N`&pzdjJRARGcoyVI%?dYYS-=5w$)H8C-iW!^FKTBq8 zguhYh=7`PC$jC@ZDKIV_7EIW?_Wq5RDC6f~2vLrkd528ukdQ{ufnG3b3n=+lY8I$s z#Uv!K7|cRWOoVQ5!>#LE%;u^;a)+Wi#oAV~{kV*ZMjflCa`o)Bv?6gVela=5bq_!01$i<8qI zX@#Dzbtxjx=jz=A6*U=cWU_i(%~bG0HSd`Np=`Rezo-nveX)tC%Qr_xM_2o^?u8ut zyP2;8U{f*K-PIK*@X+`4_$cST+cueu_gMN~`)YEi&zWqb$s=XeHi0#}ckf6dU=^(k#JK}QwxjJ)gOWhM*W@L-K)#X z;^vL1KH(Z8L?w@5ir=5(=SurNF%Ut))|Ug>Wo6<}kPH&*yY;h{LK>K^ePv>3cxCkG zx;KD9nMp~~uMeEPVbPAAqr@Qh;b4f;?RJ&GQ~aKPS%p~{P}eNHvQhgJYdnhH;Tpi2!x{N9|O$_OG?D#>{RRdvxKU-*zSaVU%&H1Qg1;*)rs3 z>i{_l>q5wd0*4tN8e&hpJFylWA3xU``bf~MP^->3$$FWq0uXAjcQ(KN7m*Uw?I5d{ zrX0CX?y9Yd&wGtOiu69SbD~K+98kR?gDILm%BY)B}!~ViP62dTUeo`VTo_+)1|BC6_Yuz z!p%)*#G+?|1;O7MhxqU)bZ%q>U5jjLY((4Gh`=%{gN{54XK8zTd&kGeV~rQ&7VE*s ztqJdEqgbXceOrVw2WC!8N^ofhpHO{tb^9u6m2nRN|;BdHtf)3aEX=nMSS)gH|R|^bOOhHQNF_=Q~Q7m~#I6S;T zMwJ~f7BHY2^?^oco(lre=h~R85UfD=u1>QEnRF#lcbBw|SBA~6|NGh1mr=vD$CM8L zgHk?x*lNU1Kge7h)ResHnYS9eM;<JkfZZ?H&tU_Z!z46$qu{E8610=2=t zaB^}g>5ds{rpqhP?4fN=v+J?D%@yA0IC}fo2Pnbk*T8h~+~;gUkJc})w*T=`R^5w2 zdUhOs5t38`05l#L*4NjkqoX^titM;SKrA|*vqNXTArlz-~}EB>r+) z8jo_dHmj;g-HtFaj{pAq`@ZYU;l`xoG5ppHK;Z^m`Gy7g`9vZylXZ5P zL~4J<Q+4!a(t+YkvJ;zta-P_$rk+g;N*Af*$_wAb%3taO<@u9uIvrlml&7@ z6!(DO5#}-gU@=7?o{AFuchPP3dmHQPGQ4pP+K-W0T^DJW9U+hZ;@Uepj#{Sk`p7aF z|0N#FAc66TCNs7_Z(|DsYiWQukxH0`;2i@qBrE zIBM*czA4=ubhtNg8H?G*g`FDR)|o+v2j1 zg$&QT5{mI;8~5;Kw5Aa%okH;Xg4SG!fMyIR{hq-n=;Ln;?B7i9bSibHTcUF42G+vy zVIDmFlxvSm67HZJ-91(V*u=-pILmGE2nyj+?z%MCLqZ;^G0cmUKsh2;o G3i}@#ikkQU diff --git a/README.md b/README.md index ee1f321..46d6e9c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- 2024 - 39 ⭐ - Rust + 2024 - 40 ⭐ - Rust

@@ -62,4 +62,7 @@ + + + diff --git a/src/day21.rs b/src/day21.rs new file mode 100644 index 0000000..9fa3caf --- /dev/null +++ b/src/day21.rs @@ -0,0 +1,206 @@ +use aoc_runner_derive::aoc; +use itertools::Itertools; +use std::iter::repeat_n; + +trait KeypadRobot { + fn new() -> Self; + fn press(&mut self, target: u8) -> Vec>; +} + +#[derive(Clone, Copy, Debug)] +struct NumberKeypadRobot { + pointing_at: u8, +} + +impl NumberKeypadRobot { + fn pos_of(button: u8) -> (i8, i8) { + match button { + b'7' => (0, 0), + b'8' => (1, 0), + b'9' => (2, 0), + b'4' => (0, 1), + b'5' => (1, 1), + b'6' => (2, 1), + b'1' => (0, 2), + b'2' => (1, 2), + b'3' => (2, 2), + b'X' => (0, 3), + b'0' => (1, 3), + b'A' => (2, 3), + c => unimplemented!("unexpected character {}", c), + } + } +} +impl KeypadRobot for NumberKeypadRobot { + fn new() -> Self { + Self { pointing_at: b'A' } + } + fn press(&mut self, target: u8) -> Vec> { + let cur_pos = Self::pos_of(self.pointing_at); + let goal_pos = Self::pos_of(target); + let x_ofs = goal_pos.0 - cur_pos.0; + let y_ofs = goal_pos.1 - cur_pos.1; + + let mut paths = Vec::new(); + + if (cur_pos.0 + x_ofs, cur_pos.1) != Self::pos_of(b'X') { + let mut x_first = Vec::new(); + x_first.extend(repeat_n(if x_ofs > 0 { b'>' } else { b'<' }, x_ofs.abs() as usize)); + x_first.extend(repeat_n(if y_ofs > 0 { b'v' } else { b'^' }, y_ofs.abs() as usize)); + x_first.push(b'A'); + paths.push(x_first); + } + if (cur_pos.0, cur_pos.1 + y_ofs) != Self::pos_of(b'X') { + let mut y_first = Vec::new(); + y_first.extend(repeat_n(if y_ofs > 0 { b'v' } else { b'^' }, y_ofs.abs() as usize)); + y_first.extend(repeat_n(if x_ofs > 0 { b'>' } else { b'<' }, x_ofs.abs() as usize)); + y_first.push(b'A'); + paths.push(y_first); + } + if paths.is_empty() { + panic!("all paths lead to the void"); + } + paths.dedup(); + self.pointing_at = target; + paths + } +} + +#[derive(Clone, Copy, Debug)] +struct DirectionKeypadRobot { + pointing_at: u8, + child: Option, +} + +impl DirectionKeypadRobot { + fn pos_of(target: u8) -> (i8, i8) { + match target { + b'X' => (0, 0), + b'^' => (1, 0), + b'A' => (2, 0), + b'<' => (0, 1), + b'v' => (1, 1), + b'>' => (2, 1), + c => unimplemented!("unexpected char {}", c), + } + } + fn move_to(&mut self, target: u8) -> Vec { + let cur_pos = Self::pos_of(self.pointing_at); + let goal_pos = Self::pos_of(target); + let x_ofs = goal_pos.0 - cur_pos.0; + let y_ofs = goal_pos.1 - cur_pos.1; + + self.pointing_at = target; + + if (cur_pos.0 + x_ofs, cur_pos.1) != Self::pos_of(b'X') { + let mut x_first = Vec::new(); + x_first.extend(repeat_n(if x_ofs > 0 { b'>' } else { b'<' }, x_ofs.abs() as usize)); + x_first.extend(repeat_n(if y_ofs > 0 { b'v' } else { b'^' }, y_ofs.abs() as usize)); + x_first.push(b'A'); + return x_first; + } + if (cur_pos.0, cur_pos.1 + y_ofs) != Self::pos_of(b'X') { + let mut y_first = Vec::new(); + y_first.extend(repeat_n(if y_ofs > 0 { b'v' } else { b'^' }, y_ofs.abs() as usize)); + y_first.extend(repeat_n(if x_ofs > 0 { b'>' } else { b'<' }, x_ofs.abs() as usize)); + y_first.push(b'A'); + return y_first; + } + panic!("all routes lead to the void"); + } + fn path_to(&mut self, moves: &Vec) -> Vec { + let prev_point = self.pointing_at; + let mut path = Vec::new(); + for m in moves { + path.append(&mut self.move_to(*m)); + } + self.pointing_at = prev_point; + path + } +} +impl KeypadRobot for DirectionKeypadRobot { + fn new() -> Self { + Self { + pointing_at: b'A', + child: None, + } + } + fn press(&mut self, target: u8) -> Vec> { + let path_options = self.child.as_mut().unwrap().press(target); + // for each path option, find our shortest route + let mut candidate_paths = Vec::new(); + for child_path in path_options { + let candidate_path = self.path_to(&child_path); + candidate_paths.push(candidate_path); + } + candidate_paths + } +} + +struct Code(Vec); + +impl Code { + fn num_val(&self) -> i64 { + String::from_utf8_lossy(&self.0.as_slice()[0..3]).parse().unwrap() + } +} + +fn parse(input: &str) -> Vec { + let mut codes = Vec::new(); + for code in input.lines() { + codes.push(Code(code.as_bytes().to_vec())) + } + codes +} + +#[aoc(day21, part1)] +fn part1(input: &str) -> i64 { + let codes = parse(input); + let mut sum = 0; + for code in &codes { + let numpad = NumberKeypadRobot::new(); + let mut robot1 = DirectionKeypadRobot::new(); + robot1.child = Some(numpad); + + let mut robot2 = DirectionKeypadRobot::new(); + robot2.child = Some(robot1); + + let mut path = Vec::new(); + for button in &code.0 { + let paths = robot2.press(*button); + path.push(paths); + } + let paths = path.clone().into_iter() + .multi_cartesian_product() + .map(|c| c.iter().flatten().map(|c| *c as char).join("")).collect_vec(); + let best = paths.iter().map(|p| p.len()).min().unwrap() as i64; + let score = code.num_val() * best; + sum += score; + } + sum +} + +#[aoc(day21, part2)] +fn part2(input: &str) -> i64 { + todo!() +} + +#[cfg(test)] +mod tests { + use super::*; + const EXAMPLE: &str = "029A +980A +179A +456A +379A"; + + #[test] + fn part1_example() { + assert_eq!(part1(EXAMPLE), 126384); + } + + #[test] + fn part2_example() { + assert_eq!(part2(EXAMPLE), 0); + } +} diff --git a/src/lib.rs b/src/lib.rs index 0d05b93..0a534d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ pub mod day18; pub mod day19; pub mod day2; pub mod day20; +pub mod day21; pub mod day3; pub mod day4; pub mod day5;