diff --git a/input/day10.test.txt b/input/day10.test.txt new file mode 100644 index 0000000..7bb1248 --- /dev/null +++ b/input/day10.test.txt @@ -0,0 +1,8 @@ +89010123 +78121874 +87430965 +96549874 +45678903 +32019012 +01329801 +10456732 \ No newline at end of file diff --git a/input/day10.txt b/input/day10.txt new file mode 100644 index 0000000..dbdbad8 --- /dev/null +++ b/input/day10.txt @@ -0,0 +1,55 @@ +0123450128945212434498107654876212322345432110787870123 +1214563287654302345347278923945003411276741025696983254 +2307874390901201436256361010232156500985891234899874765 +3458965481896543457101454322121267898764210348760565856 +4547889332787612898654456541010128709654321409651487943 +9656971245610502348742363456723489214545670512342396512 +8746560330541461059231072019894876523039987651229603401 +0130450101232878762108981923785955432128896560318712101 +1221321432543969456676870831276843201017698431105657892 +4349898540158950387985106740189652122012587120234598761 +0456797643267341293234203651076561043403436011231034650 +1245687653212210982178312312345878654312345190345125141 +4334567064307807891089425405658969763233438987656776032 +5321018165616906702376596534787439890120107678949889120 +6910789278965215610345687321096521763011234589030672101 +7821898347654334321256786543212310652101347654121543432 +6734787658901223456105897610105432543276978903443430563 +2105676987911010897834978923076501034789877412352321694 +3456989876854323708929870134589632385676966543261430785 +4367810105763432612210165245678745690123457898170567014 +3210121234176501523878954354776544787430342347089698923 +2345665893080787438965410167889432156561231456798789654 +1058756702191898341014321054974321047892120321887018763 +0569845212012567634323015123125410430121011010986323454 +6578954307623498765487654304034543221030345654345432125 +5434356788545349854599001216787652107845210787216701034 +0125643699237898703678104325894567856956789891209834345 +7876212765103203612363215454383898945787698900340125876 +0980101894454114503054356965212432430694543215489876965 +1098234583467023212125407870106541021583210676098920145 +2347899602898908763256910187017865652678701587187813236 +3256678711743219854567823298894976569549652490296704367 +0100345620651278343289654350765987478230743321345410198 +9251201234230341230178760541034300300121890120034326789 +8349212945145650789078921632133211212010581631128965632 +7658767876054787632107634780124504321123498745489874541 +6107323945763096549616543995435665210898589654788103450 +5236014539892124328723012876343786789867670123694012367 +4345867622101015610654322301212891270184561054543231018 +2109988913412126789961001454309750301293432163210102309 +3458776804569234697872156545678543432789430673456943212 +4567566543678985586543267836787612545676521982987856103 +0103457012987876487434586927898707654568701201276547894 +1212388967876567393325698810989898965439632320567030985 +0327890658905058212016784543298781012344543011498121076 +9456541243014149801134569650185632307655676322399876125 +8767632332123232100123678745670546998764985431087565436 +3498234501104343034598988764321457884643891056016501098 +2567107698612352125667639058901210745012342347121432167 +1989278786783961012787540147654323654321435218930345236 +0876989695894878109896039236569456788760324306543210145 +0105874504185769854385128545478998699354413457850105256 +1234763213096854763014537654360187543263509766969876567 +2303452342187943212323456963201236984102678876878103498 +3212301056789810103410567870102345676101278987989012567 diff --git a/src/day10.rs b/src/day10.rs new file mode 100644 index 0000000..0dd7bd9 --- /dev/null +++ b/src/day10.rs @@ -0,0 +1,43 @@ +use crate::spatial::{Point, adjacent_cardinal, adjacent_cardinal_points, all_coords, flood}; +use std::collections::{BTreeSet, HashMap}; + +pub fn day10_part1(input: &str) -> String { + let topomap = parse(input); + let digraph = topomap_to_digraph(&topomap); + let reachable = all_coords(topomap[0].len(), topomap.len()) + .filter(|pt| topomap[pt.row][pt.col] == 0) + .map(|pt| flood(&digraph, pt)) + .map(|set| set.iter().filter(|pt| topomap[pt.row][pt.col] == 9).count()) + .sum::(); + reachable.to_string() +} + +pub fn day10_part2(input: &str) -> String { + todo!() +} + +fn parse(input: &str) -> Vec> { + input + .lines() + .map(|line| { + line.chars() + .map(|c| c.to_digit(10).unwrap() as u8) + .collect() + }) + .collect() +} +///adjacency list in graph format +fn topomap_to_digraph(topomap: &[Vec]) -> Vec>> { + let mut digraph = vec![vec![vec![]; topomap[0].len()]; topomap.len()]; + for row in 0..topomap.len() { + for col in 0..topomap[0].len() { + let adj = adjacent_cardinal_points(topomap, Point { row, col }); + digraph[row][col] = adj + .into_iter() + .filter(|pt| topomap[pt.row][pt.col] == 1 + topomap[row][col]) + .collect(); + } + } + + digraph +} diff --git a/src/lib.rs b/src/lib.rs index 9bd26be..6ff18d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -345,11 +345,28 @@ pub mod day6; pub mod day7; pub mod day8; pub mod day9; +pub mod day10; +pub mod spatial; #[cfg(test)] mod tests { use super::*; + #[test] + fn day10_part1_test() { + let test_result = day10::day10_part1(include_str!("../input/day10.test.txt")); + assert_eq!(test_result, "36"); + let result = day10::day10_part1(include_str!("../input/day10.txt")); + assert_eq!(result, "820"); + } + // #[test] + // fn day10_part2_test() { + // let test_result = day10::day10_part2(include_str!("../input/day10.test.txt")); + // assert_eq!(test_result, "2858"); + // // let result = day10::day10_part2(include_str!("../input/day10.txt")); + // // assert_eq!(result, "6476642796832"); + // } + #[test] fn day9_part1_test() { let test_result = day9::day9_part1(include_str!("../input/day9.test.txt")); diff --git a/src/spatial.rs b/src/spatial.rs new file mode 100644 index 0000000..e538a86 --- /dev/null +++ b/src/spatial.rs @@ -0,0 +1,71 @@ +use std::collections::BTreeSet; + +use itertools::Itertools; + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct Point { + pub row: usize, + pub col: usize, +} +pub fn all_coords(width: usize, height: usize) -> impl Iterator { + (0..height) + .cartesian_product(0..width) + .map(|(row, col)| Point { row, col }) +} + +///Never Eat Shredded Wheat +pub fn adjacent_cardinal(grid: &[Vec], coords: Point) -> [Option; 4] { + let mut retval = [const { None }; 4]; + let (row, col) = (coords.row, coords.col); + + if row > 0 { + retval[0] = Some(grid[row - 1][col]) //N + } + if col < grid[0].len() - 1 { + retval[1] = Some(grid[row][col + 1]) //E + } + if row < grid.len() - 1 { + retval[2] = Some(grid[row + 1][col]) //S + } + if col > 0 { + retval[3] = Some(grid[row][col - 1]) //N + } + + retval +} + +pub fn adjacent_cardinal_points(grid: &[Vec], coords: Point) -> Vec { + let mut retval = vec![]; + let (row, col) = (coords.row, coords.col); + + if row > 0 { + retval.push(Point { row: row - 1, col }) //N + } + if col < grid[0].len() - 1 { + retval.push(Point { row, col: col + 1 }) //E + } + if row < grid.len() - 1 { + retval.push(Point { row: row + 1, col }) //S + } + if col > 0 { + retval.push(Point { row, col: col - 1 }) //W + } + + retval +} + +//2d spatial digraph +pub fn flood(digraph: &[Vec>], start: Point) -> BTreeSet { + let mut reachable = BTreeSet::new(); + let mut frontier = BTreeSet::from_iter([start]); + + while let Some(cursor) = frontier.pop_first() { + reachable.insert(cursor); + let next = BTreeSet::from_iter(digraph[cursor.row][cursor.col].iter().cloned()); + for &point in next.difference(&reachable) { + frontier.insert(point); + } + } + + reachable +}