diff --git a/README.md b/README.md index ace3459..66ce94b 100644 --- a/README.md +++ b/README.md @@ -27,18 +27,21 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www. | Day | Part 1 | Part 2 | | :---: | :---: | :---: | -| [Day 1](./src/bin/01.rs) | `131.2µs` | `206.6µs` | -| [Day 2](./src/bin/02.rs) | `179.9µs` | `474.6µs` | -| [Day 3](./src/bin/03.rs) | `465.1µs` | `666.7µs` | -| [Day 4](./src/bin/04.rs) | `3.4ms` | `476.1µs` | -| [Day 6](./src/bin/06.rs) | `65.5µs` | `-` | -| [Day 7](./src/bin/07.rs) | `12.2ms` | `-` | -| [Day 8](./src/bin/08.rs) | `109.7µs` | `-` | -| [Day 9](./src/bin/09.rs) | `1.1ms` | `-` | -| [Day 10](./src/bin/10.rs) | `5.7ms` | `-` | -| [Day 13](./src/bin/13.rs) | `2.9ms` | `-` | +| [Day 1](./src/bin/01.rs) | `126.9µs` | `218.4µs` | +| [Day 2](./src/bin/02.rs) | `190.5µs` | `487.3µs` | +| [Day 3](./src/bin/03.rs) | `524.3µs` | `678.5µs` | +| [Day 4](./src/bin/04.rs) | `3.7ms` | `495.5µs` | +| [Day 5](./src/bin/05.rs) | `43.2ms` | `-` | +| [Day 6](./src/bin/06.rs) | `59.8µs` | `-` | +| [Day 7](./src/bin/07.rs) | `11.9ms` | `-` | +| [Day 8](./src/bin/08.rs) | `106.2µs` | `-` | +| [Day 9](./src/bin/09.rs) | `1.0ms` | `-` | +| [Day 10](./src/bin/10.rs) | `10.1ms` | `-` | +| [Day 11](./src/bin/11.rs) | `6.0s` | `-` | +| [Day 12](./src/bin/12.rs) | `4.5ms` | `-` | +| [Day 13](./src/bin/13.rs) | `3.1ms` | `-` | -**Total: 28.08ms** +**Total: 6080.39ms** --- diff --git a/src/bin/04-broken.rs b/src/bin/04.rs.broken similarity index 100% rename from src/bin/04-broken.rs rename to src/bin/04.rs.broken diff --git a/src/bin/05.rs b/src/bin/05.rs index 0ff7e66..519f5d3 100644 --- a/src/bin/05.rs +++ b/src/bin/05.rs @@ -35,9 +35,13 @@ pub fn part_one(input: &str) -> Option { Some(total) } -pub fn part_two(input: &str) -> Option { +#[allow(unreachable_code)] +pub fn part_two(_input: &str) -> Option { + // TODO: Fix this + return None; + // Parse the rules - let mut reader = input.lines(); + let mut reader = _input.lines(); let rules: Vec<_> = reader.by_ref().take_while(|l| !l.is_empty()).map(|r| r.split('|').collect::>()).collect(); // println!("{} lines", rules.len()); @@ -52,7 +56,7 @@ pub fn part_two(input: &str) -> Option { let is_valid = get_is_valid(&rules, &pages); if is_valid { - return t + t } else { // println!("Invalid pages {:?}", pages); @@ -75,7 +79,7 @@ pub fn part_two(input: &str) -> Option { Some(total) } -fn get_is_valid(rules: &Vec>, pages: &Vec<&str>) -> bool { +fn get_is_valid(rules: &[Vec<&str>], pages: &[&str]) -> bool { for (page_a_idx, page_a) in pages.iter().enumerate() { for page_b in &pages[page_a_idx..] { // check for a violation of the rules! @@ -91,7 +95,7 @@ fn find_valid_book<'a>(rules: &Vec>, pages: Vec<&'a str>, remaining_pa let is_valid = get_is_valid(rules, &pages); - if remaining_pages.len() == 0 && is_valid { + if remaining_pages.is_empty() && is_valid { return Some(pages) } @@ -110,10 +114,6 @@ fn find_valid_book<'a>(rules: &Vec>, pages: Vec<&'a str>, remaining_pa }) } -fn factorial(n: usize) -> Option { - (1..n).try_fold(n, usize::checked_mul) -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/bin/06.rs b/src/bin/06.rs index 09facdf..b5a41be 100644 --- a/src/bin/06.rs +++ b/src/bin/06.rs @@ -3,8 +3,8 @@ use itertools::Itertools; advent_of_code::solution!(6); pub fn part_one(input: &str) -> Option { - let mut pos = (0 as isize, 0 as isize); - let mut dir = (-1 as isize, 0 as isize); + let mut pos = (0_isize, 0_isize); + let mut dir = (-1_isize, 0_isize); let grid = input.lines().enumerate().map(|(line_idx, line)| { let chars = line.chars().enumerate().map(|(char_idx, char)| { @@ -34,8 +34,8 @@ pub fn part_one(input: &str) -> Option { if grid[new_pos.0 as usize][new_pos.1 as usize] == '#' { // if it is a blocker, turn 90deg - let directions = vec![(-1, 0), (0, 1), (1, 0), (0, -1), (-1, 0)]; - let new_dir = *directions.iter().skip_while(|d| **d != dir).skip(1).next().unwrap(); + let directions = [(-1, 0), (0, 1), (1, 0), (0, -1), (-1, 0)]; + let new_dir = *directions.iter().skip_while(|d| **d != dir).nth(1).unwrap(); dir.0 = new_dir.0; dir.1 = new_dir.1; } else { @@ -51,7 +51,7 @@ pub fn part_one(input: &str) -> Option { Some(count_spaces(visited) as u32) } -pub fn part_two(input: &str) -> Option { +pub fn part_two(_input: &str) -> Option { None } diff --git a/src/bin/07.rs b/src/bin/07.rs index eaa11bd..c7ca16b 100644 --- a/src/bin/07.rs +++ b/src/bin/07.rs @@ -9,15 +9,15 @@ pub fn part_one(input: &str) -> Option { // println!("LINE: {} = {:?}", total, values); - if can_calc(total, values) { Some(total) } else { None } + if can_calc(total, &values) { Some(total) } else { None } // Some(total) }).sum(); // println!("TOTAL: {}", total); - return Some(total); + Some(total) } -pub fn part_two(input: &str) -> Option { +pub fn part_two(_input: &str) -> Option { None } @@ -26,16 +26,16 @@ pub fn part_two(input: &str) -> Option { // eg 190: 10 19 -- has TWO possible paths, 10 + 19 and 10 * 19 // eg 123: 4 5 6 3 -- has 8 possible paths; 4+5+6+3, 4+5+6*3, ... 4*5*6*3 -fn can_calc(total: usize, values: Vec) -> bool { - let is_valid = values.into_iter().fold(vec![0 as usize], |subtotals, next_value| { +fn can_calc(total: usize, values: &[usize]) -> bool { + let is_valid = values.iter().fold(vec![0_usize], |subtotals, next_value| { process(&subtotals, next_value) }).iter().any(|t| *t == total); is_valid } -fn process(sum: &Vec, next_value: usize) -> Vec { - sum.into_iter().flat_map(|v| { +fn process(sum: &[usize], next_value: &usize) -> Vec { + sum.iter().flat_map(|v| { vec![v + next_value, v * next_value] }).collect() } @@ -46,19 +46,19 @@ mod tests { #[test] fn test_process() { - let sum: Vec = vec![1]; + let sum = [1]; let next_value = 10; - let result = process(&sum, next_value); + let result = process(&sum, &next_value); assert_eq!(result, vec![11, 10]); } #[test] fn test_can_calc() { - let values: Vec = vec![1,2,3,4]; - let total: u32 = 10; + let values = [1,2,3,4]; + let total = 10; - let result = can_calc(total, values); + let result = can_calc(total, &values); assert_eq!(result, true); } diff --git a/src/bin/08.rs b/src/bin/08.rs index 8dda954..fdfb0ff 100644 --- a/src/bin/08.rs +++ b/src/bin/08.rs @@ -14,10 +14,10 @@ pub fn part_one(input: &str) -> Option { for (col_idx, c) in line.chars().enumerate(){ if c != '.' { - if antennas.contains_key(&c) { - antennas.entry(c).and_modify(|v| v.push((row_idx as u32, col_idx as u32))); - } else { + if let std::collections::hash_map::Entry::Vacant(_e) = antennas.entry(c) { antennas.insert(c, vec![(row_idx as u32, col_idx as u32)]); + } else { + antennas.entry(c).and_modify(|v| v.push((row_idx as u32, col_idx as u32))); } } } @@ -39,7 +39,7 @@ pub fn part_one(input: &str) -> Option { Some(locations.count() as u32) } -pub fn part_two(input: &str) -> Option { +pub fn part_two(_input: &str) -> Option { None } diff --git a/src/bin/09.rs b/src/bin/09.rs index 5159557..99353d9 100644 --- a/src/bin/09.rs +++ b/src/bin/09.rs @@ -23,7 +23,7 @@ pub fn part_one(input: &str) -> Option { Some(checksum as u32) } -pub fn part_two(input: &str) -> Option { +pub fn part_two(_input: &str) -> Option { None } @@ -45,18 +45,18 @@ fn move_blocks(mut blocks: Vec>) -> Vec>{ let mut head_ptr = 0; let mut tail_ptr = blocks.len() - 1; - while blocks[tail_ptr] == None { + while Option::is_none(&blocks[tail_ptr]) { tail_ptr -= 1; } while head_ptr <= tail_ptr { - if blocks[head_ptr] == None { + if Option::is_none(&blocks[head_ptr]) { blocks.swap(head_ptr, tail_ptr); } head_ptr += 1; - while blocks[tail_ptr] == None { + while Option::is_none(&blocks[tail_ptr]) { tail_ptr -= 1; } } @@ -65,16 +65,13 @@ fn move_blocks(mut blocks: Vec>) -> Vec>{ } fn get_checksum(blocks: Vec>) -> usize { - let checksum = blocks.into_iter().enumerate().fold(0 as usize, |sum, (idx, id)| { - if id == None { + blocks.into_iter().enumerate().fold(0_usize, |sum, (idx, id)| { + if Option::is_none(&id) { sum } else { - let total = sum + idx.mul(id.unwrap() as usize); - total + sum + idx.mul(id.unwrap()) } - }); - - checksum + }) } #[cfg(test)] diff --git a/src/bin/10.rs b/src/bin/10.rs index 5424afe..8971067 100644 --- a/src/bin/10.rs +++ b/src/bin/10.rs @@ -37,7 +37,7 @@ pub fn part_one(input: &str) -> Option { Some(total_score as u32) } -pub fn part_two(input: &str) -> Option { +pub fn part_two(_input: &str) -> Option { None } @@ -51,9 +51,9 @@ fn can_navigate(grid: &Vec>, start: &Path, end: &Path) -> bool { if start == end { return true } DIRECTIONS.iter().any(|d| { - let next_step = Path { row: &start.row + d.0, col: &start.col + d.1, elevation: start.elevation + 1 }; + let next_step = Path { row: start.row + d.0, col: start.col + d.1, elevation: start.elevation + 1 }; // println!("{:?} ==> {:?} ?", start, end); - is_valid(&next_step) && can_navigate(&grid, &next_step, &end) + is_valid(&next_step) && can_navigate(grid, &next_step, end) }) } diff --git a/src/bin/11.rs b/src/bin/11.rs index 2037234..43557fa 100644 --- a/src/bin/11.rs +++ b/src/bin/11.rs @@ -1,4 +1,4 @@ -use std::ops::{Div, Mul}; +use std::ops::Mul; use itertools::Itertools; @@ -14,7 +14,7 @@ pub fn part_one(input: &str) -> Option { Some(total_count as u32) } -pub fn part_two(input: &str) -> Option { +pub fn part_two(_input: &str) -> Option { None } @@ -29,7 +29,7 @@ fn step_stones(stones: &mut Vec, max_steps: usize) { if stone == "0" { stones[idx] = String::from("1"); } else if stone_length % 2 == 0 { - let mut stone_iter = stone.chars().into_iter(); + let mut stone_iter = stone.chars(); let first_half = stone_iter.by_ref().take(stone_length/2).collect::(); let second_half = stone_iter.by_ref().take(stone_length/2).collect::().parse::().unwrap().to_string(); diff --git a/src/bin/12.rs b/src/bin/12.rs index 5311040..61eca6f 100644 --- a/src/bin/12.rs +++ b/src/bin/12.rs @@ -26,6 +26,7 @@ type Direction = (isize, isize); // } #[derive(Debug)] +#[allow(dead_code)] struct Region { id: u32, edges: usize, @@ -37,7 +38,7 @@ pub fn part_one(input: &str) -> Option { let mut regions: HashMap = HashMap::new(); let mut next_region_id = 1; - while let Some(plot) = find_plot(&plots, |p| p.region_id == None) { + while let Some(plot) = find_plot(&plots, |p| Option::is_none(&p.region_id)) { plots[plot.0][plot.1].region_id = Some(next_region_id); let edge_count = count_edges(&plots, &plot); @@ -56,12 +57,16 @@ pub fn part_one(input: &str) -> Option { Some(total as u32) } -pub fn part_two(input: &str) -> Option { - let mut plots = input.lines().map(|l| l.chars().map(|c| Plot { letter: c, region_id: None }).collect_vec()).collect_vec(); +#[allow(unreachable_code)] +pub fn part_two(_input: &str) -> Option { + // TODO: Get this working + return None; + + let mut plots = _input.lines().map(|l| l.chars().map(|c| Plot { letter: c, region_id: None }).collect_vec()).collect_vec(); let mut regions: HashMap = HashMap::new(); let mut next_region_id = 1; - while let Some(plot) = find_plot(&plots, |p| p.region_id == None) { + while let Some(plot) = find_plot(&plots, |p| Option::is_none(&p.region_id)) { plots[plot.0][plot.1].region_id = Some(next_region_id); let edge_count = count_edges(&plots, &plot); @@ -71,22 +76,21 @@ pub fn part_two(input: &str) -> Option { update_neighbors(&mut plots, &plot, &mut regions); } - let w = plots.iter().map(|p| p.iter().map(|p| p.letter).collect::()).join("\n"); + // let w = plots.iter().map(|p| p.iter().map(|p| p.letter).collect::()).join("\n"); // println!("{}", w); let total = regions.iter().sorted_by_key(|r| r.0).fold(0, |sum, (region_id, region)| { let start_plot = find_plot(&plots, |p| p.region_id == Some(*region_id)).unwrap(); - print!("REGION {}:", region.id); + // print!("REGION {}:", region.id); let edges = traverse_start(&plots, &start_plot); - let total = sum + (region.count * edges); + sum + (region.count * edges) // println!(" = {} * {} = {}", region.count, edges, region.count * edges); - total }); Some(total as u32) } -fn find_plot(plots: &Vec>, predicate: F) -> Option<(usize, usize)> where +fn find_plot(plots: &[Vec], predicate: F) -> Option<(usize, usize)> where F: Fn(&Plot) -> bool { for (row_idx, row) in plots.iter().enumerate() { for (col_idx, plot) in row.iter().enumerate() { @@ -96,7 +100,7 @@ F: Fn(&Plot) -> bool { } } } - return None + None } fn update_neighbors(plots: &mut Vec>, plot: &(usize, usize), regions: &mut HashMap) { @@ -116,7 +120,7 @@ fn update_neighbors(plots: &mut Vec>, plot: &(usize, usize), regions: (0..grid_height as isize).contains(new_row_idx) && (0..grid_width as isize).contains(new_col_idx) && plots[*new_row_idx as usize][*new_col_idx as usize].letter == current_region_letter && - plots[*new_row_idx as usize][*new_col_idx as usize].region_id == None; + Option::is_none(&plots[*new_row_idx as usize][*new_col_idx as usize].region_id); if should_update { let next_plot: (usize, usize) = (*new_row_idx as usize, *new_col_idx as usize); @@ -131,13 +135,13 @@ fn update_neighbors(plots: &mut Vec>, plot: &(usize, usize), regions: } } -fn count_edges(plots: &Vec>, plot: &(usize, usize)) -> usize { +fn count_edges(plots: &[Vec], plot: &(usize, usize)) -> usize { let grid_height = plots.len(); let grid_width = plots[0].len(); - vec![(-1, 0), (1, 0), (0, -1), (0, 1)].iter().filter(|d| { - let new_row = plot.0 as isize + &d.0; - let new_col = plot.1 as isize + &d.1; + [(-1, 0), (1, 0), (0, -1), (0, 1)].iter().filter(|d| { + let new_row = plot.0 as isize + d.0; + let new_col = plot.1 as isize + d.1; !(0..grid_height as isize).contains(&new_row) || !(0..grid_width as isize).contains(&new_col) || @@ -145,13 +149,13 @@ fn count_edges(plots: &Vec>, plot: &(usize, usize)) -> usize { }).count() } -fn traverse_start(plots: &Vec>, plot: &(usize, usize)) -> usize { +fn traverse_start(plots: &[Vec], plot: &(usize, usize)) -> usize { let start_direction: Direction = (0, 1); - let mut prior_plot = plot.clone(); - let mut prior_direction = start_direction.clone(); + let mut prior_plot = *plot; + let mut prior_direction = start_direction; - println!(" at {:?} going {}", plot, debug_direction(start_direction)); + // println!(" at {:?} going {}", plot, debug_direction(start_direction)); // count the number of times we turn a corner let mut corners = 0; @@ -167,7 +171,7 @@ fn traverse_start(plots: &Vec>, plot: &(usize, usize)) -> usize { corners } -fn traverse_step(plots: &Vec>, plot: &(usize, usize), direction: Direction) -> Option<((usize, usize), Direction)> { +fn traverse_step(plots: &[Vec], plot: &(usize, usize), direction: Direction) -> Option<((usize, usize), Direction)> { let grid_height = plots.len(); let grid_width = plots[0].len(); @@ -181,34 +185,35 @@ fn traverse_step(plots: &Vec>, plot: &(usize, usize), direction: Direc }; let ccw_curve = directions.windows(2).find(|dd| dd[0] == direction).map(|dd| dd[1]).unwrap(); - let ccw_plot = get_at(plot.0 as isize + ccw_curve.0 as isize, plot.1 as isize + ccw_curve.1 as isize); - let next_plot = get_at(plot.0 as isize + direction.0 as isize, plot.1 as isize + direction.1 as isize); + let ccw_plot = get_at(plot.0 as isize + ccw_curve.0, plot.1 as isize + ccw_curve.1); + let next_plot = get_at(plot.0 as isize + direction.0, plot.1 as isize + direction.1); // TODO - fix this traversal code - if ccw_plot != None { + if Option::is_some(&ccw_plot) { // if the CCW plot IS in the region, ROTATE CCW - print!("↺ "); - return Some((*plot, ccw_curve)); - } else if next_plot != None { + // print!("↺ "); + Some((*plot, ccw_curve)) + } else if Option::is_some(&next_plot) { // if the NEXT plot IS in the region, MOVE NEXT - print!("{} ", debug_direction(direction)); - return Some((((plot.0 as isize + direction.0 as isize) as usize, (plot.1 as isize + direction.1 as isize) as usize), direction)); + // print!("{} ", debug_direction(direction)); + Some((((plot.0 as isize + direction.0) as usize, (plot.1 as isize + direction.1) as usize), direction)) } else { // if the NEXT plot is NOT in the region, ROTATE CW let cw_curve = directions.iter().rev().collect_vec().windows(2).find(|dd| *dd[0] == direction).map(|dd| *dd[1]).unwrap(); - print!("↻ "); - return Some((*plot, cw_curve )) + // print!("↻ "); + Some((*plot, cw_curve )) } // When we get back to the FIRST plot and are at the same direction, stop counting } +#[allow(dead_code)] fn debug_direction(d: Direction) -> char { - let arrows = HashMap::from([ - ((-1 as isize, 0 as isize), '↑'), - ((1 as isize, 0 as isize), '↓'), - ((0 as isize, -1 as isize), '←'), - ((0 as isize, 1 as isize), '→') + let arrows: HashMap<(isize, isize), char> = HashMap::from([ + ((-1, 0), '↑'), + ((1, 0), '↓'), + ((0, -1), '←'), + ((0, 1), '→') ]); *arrows.get(&d).unwrap_or(&'X') diff --git a/src/bin/13.rs b/src/bin/13.rs index 5151127..3ec302f 100644 --- a/src/bin/13.rs +++ b/src/bin/13.rs @@ -48,13 +48,13 @@ pub fn part_one(input: &str) -> Option { Some(total_tokens) } -pub fn part_two(input: &str) -> Option { +pub fn part_two(_input: &str) -> Option { None } // TODO figure out how to reference-ify this fn find_matches(machine: Machine) -> impl Iterator { - let result = (0..=100).flat_map(move |a_presses| { + (0..=100).flat_map(move |a_presses| { (0..=100).filter_map(move |b_presses| { let pos_x = machine.a_button.x * a_presses + machine.b_button.x * b_presses; let pos_y = machine.a_button.y * a_presses + machine.b_button.y * b_presses; @@ -65,8 +65,7 @@ fn find_matches(machine: Machine) -> impl Iterator { None } }) - }); - result + }) } #[cfg(test)]