diff options
Diffstat (limited to 'src/bin')
-rw-r--r-- | src/bin/2023/day3.rs | 114 | ||||
-rw-r--r-- | src/bin/2023/main.rs | 2 |
2 files changed, 116 insertions, 0 deletions
diff --git a/src/bin/2023/day3.rs b/src/bin/2023/day3.rs new file mode 100644 index 0000000..2f7dcb0 --- /dev/null +++ b/src/bin/2023/day3.rs @@ -0,0 +1,114 @@ +#![allow(dead_code)] +#![allow(unused_variables)] + +use advent_of_code::prelude::*; + +pub fn parse(fh: File) -> Result<Grid<u8>> { + Ok(parse::grid(parse::raw_lines(fh), |c, _, _| c)) +} + +pub fn part1(schematic: Grid<u8>) -> Result<i64> { + let mut numbers = vec![]; + for row in schematic.each_row() { + let mut current_number = None; + for col in schematic.each_col() { + let c = schematic[row][col]; + if c.is_ascii_digit() { + match current_number { + Some(n) => { + current_number = Some(n * 10 + i64::from(c - b'0')) + } + None => current_number = Some(i64::from(c - b'0')), + } + } else if let Some(n) = current_number.take() { + numbers.push((n, row, col)); + } + } + if let Some(n) = current_number.take() { + numbers.push((n, row, schematic.cols())); + } + } + + let mut total = 0; + 'number: for (n, row, col) in numbers { + let len = n.ilog10() + 1; + for offset in 0..=n.ilog10() { + let col = Col(col.0 - usize::try_from(offset).unwrap() - 1); + for (row, col) in schematic.adjacent(row, col, true) { + let c = schematic[row][col]; + if !c.is_ascii_digit() && c != b'.' { + total += n; + continue 'number; + } + } + } + } + + Ok(total) +} + +pub fn part2(schematic: Grid<u8>) -> Result<i64> { + let mut numbers = vec![]; + for row in schematic.each_row() { + let mut current_number = None; + for col in schematic.each_col() { + let c = schematic[row][col]; + if c.is_ascii_digit() { + match current_number { + Some(n) => { + current_number = Some(n * 10 + i64::from(c - b'0')) + } + None => current_number = Some(i64::from(c - b'0')), + } + } else if let Some(n) = current_number.take() { + numbers.push((n, row, col)); + } + } + if let Some(n) = current_number.take() { + numbers.push((n, row, schematic.cols())); + } + } + + let mut gears: HashMap<_, HashSet<_>> = HashMap::new(); + for (n, nrow, ncol) in numbers { + let len = n.ilog10() + 1; + for offset in 0..=n.ilog10() { + for (grow, gcol) in schematic.adjacent( + nrow, + Col(ncol.0 - usize::try_from(offset).unwrap() - 1), + true, + ) { + let c = schematic[grow][gcol]; + if c == b'*' { + gears + .entry((grow, gcol)) + .or_default() + .insert((n, nrow, ncol)); + } + } + } + } + + Ok(gears + .values() + .filter_map(|s| { + if s.len() == 2 { + Some(s.iter().map(|(n, _, _)| n).product::<i64>()) + } else { + None + } + }) + .sum()) +} + +#[test] +fn test() { + assert_eq!( + part1(parse(parse::data(2023, 3).unwrap()).unwrap()).unwrap(), + 540212 + ); + assert_eq!( + part2(parse(parse::data(2023, 3).unwrap()).unwrap()).unwrap(), + 87605697 + ); +} diff --git a/src/bin/2023/main.rs b/src/bin/2023/main.rs index cb9aa54..652bf26 100644 --- a/src/bin/2023/main.rs +++ b/src/bin/2023/main.rs @@ -13,6 +13,7 @@ use advent_of_code::prelude::*; mod day1; mod day2; +mod day3; // NEXT MOD #[paw::main] @@ -21,6 +22,7 @@ fn main(opt: Opt) -> Result<()> { match opt.day { 1 => advent_of_code::day!(2023, opt.day, opt.puzzle, day1), 2 => advent_of_code::day!(2023, opt.day, opt.puzzle, day2), + 3 => advent_of_code::day!(2023, opt.day, opt.puzzle, day3), // NEXT PART _ => panic!("unknown day {}", opt.day), } |