Day 3 done and pedantic clippy clean up

This commit is contained in:
Dylan Thies
2023-12-03 20:48:26 -05:00
parent 3ac75e55bf
commit ecbaf8f9fe
7 changed files with 259 additions and 14 deletions

View File

@@ -1,9 +1,21 @@
#![warn(clippy::all, clippy::pedantic)]
use nom::{ use nom::{
self, self,
character::complete::{alphanumeric1, newline}, character::complete::{alphanumeric1, newline},
multi::separated_list1, multi::separated_list1,
}; };
/// Day-1 part 1 of AC2023
///
/// # Arguments
/// - input the input for day1 as a string
///
/// # Panics
/// This panics whenever a number isn't present in a line of the input
///
/// # Errors
/// errors when can't parse the input
pub fn part1(input: &str) -> nom::IResult<&str, String> { pub fn part1(input: &str) -> nom::IResult<&str, String> {
let (_, values) = parse_input(input)?; let (_, values) = parse_input(input)?;
println!("{values:?}"); println!("{values:?}");
@@ -11,7 +23,7 @@ pub fn part1(input: &str) -> nom::IResult<&str, String> {
"", "",
values values
.iter() .iter()
.map(|v| v.first().unwrap() * 10 + v.last().unwrap()) .map(|v| v.first().expect("always at least one number") * 10 + v.last().expect("always atleast one number"))
.sum::<u32>() .sum::<u32>()
.to_string(), .to_string(),
)) ))

View File

@@ -1,9 +1,18 @@
#![warn(clippy::all, clippy::pedantic)]
/// Day 1 Part 2 of AOC2023
///
/// # Arguments
/// - puzzle input
///
/// # Panics
/// this panics if there is no numbers in a line
pub fn part2(input: &str) -> String { pub fn part2(input: &str) -> String {
let values = input.lines().map(parse_line).collect::<Vec<Vec<u32>>>(); let values = input.lines().map(parse_line).collect::<Vec<Vec<u32>>>();
println!("{values:?}"); println!("{values:?}");
values values
.iter() .iter()
.map(|v| v.first().unwrap() * 10 + v.last().unwrap()) .map(|v| v.first().expect("There is always at least one number") * 10 + v.last().expect("there is always at least one number"))
.sum::<u32>() .sum::<u32>()
.to_string() .to_string()
} }
@@ -33,7 +42,7 @@ fn parse_line(line: &str) -> Vec<u32> {
} else if reduced_line.starts_with("zero") { } else if reduced_line.starts_with("zero") {
Some(0) Some(0)
} else { } else {
reduced_line.chars().next().unwrap().to_digit(10) reduced_line.chars().next().expect("there is alwayss a character").to_digit(10)
}; };
result result

View File

@@ -1,3 +1,5 @@
#![warn(clippy::all, clippy::pedantic)]
use log::debug; use log::debug;
use nom::{ use nom::{
bytes::complete::tag, bytes::complete::tag,
@@ -41,6 +43,13 @@ impl Game {
} }
} }
/// part2 of day 2 of AOC 2023
///
/// # Arguments
/// - input the puszzle input
///
/// # Panics
/// panics whenever the input isn't parsable
pub fn part1(input: &str) -> String { pub fn part1(input: &str) -> String {
let (_, games) = process_input(input).expect("there should be input"); let (_, games) = process_input(input).expect("there should be input");
debug!("{games:?}"); debug!("{games:?}");

View File

@@ -1,3 +1,5 @@
#![warn(clippy::all, clippy::pedantic)]
use nom::{ use nom::{
bytes::complete::tag, bytes::complete::tag,
character::complete::{self, newline}, character::complete::{self, newline},
@@ -37,6 +39,13 @@ impl Game {
} }
} }
/// part2 of day 2 of AOC 2023
///
/// # Arguments
/// - input the puszzle input
///
/// # Panics
/// panics whenever the input isn't parsable
pub fn part2(input: &str) -> String { pub fn part2(input: &str) -> String {
let (_, games) = process_input(input).expect("there should be input"); let (_, games) = process_input(input).expect("there should be input");
games.iter().map(Game::to_power).sum::<u64>().to_string() games.iter().map(Game::to_power).sum::<u64>().to_string()

View File

@@ -8,5 +8,5 @@ repository.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
nom.workspace = true
itertools.workspace = true itertools.workspace = true
log.workspace = true

View File

@@ -1,18 +1,129 @@
#![warn(clippy::all, clippy::pedantic)]
use std::collections::BTreeMap;
pub fn part1 (_input: &str) -> String { #[derive(Debug)]
"Not Finished".to_string() struct SerialNumber {
pub no: u64,
pub start: (usize, usize),
pub end: (usize, usize),
}
impl SerialNumber {
fn generate_adjacent(&self) -> Vec<(usize, usize)> {
let start_row = if self.start.0 == 0 {
0
} else {
self.start.0 - 1
};
let start_line = if self.start.1 == 0 {
0
} else {
self.start.1 - 1
};
(start_row..=(self.end.0 + 1))
.flat_map(|x| (start_line..=(self.end.1 + 1)).map(move |y| (x, y)))
.collect()
}
}
#[must_use]
pub fn part1(input: &str) -> String {
let (serials, symbols) = parse_input(input);
serials
.iter()
.filter(|x| {
x.generate_adjacent()
.iter()
.any(|t| symbols.get(t).is_some())
})
.map(|x| x.no)
.sum::<u64>()
.to_string()
}
fn parse_input(input: &str) -> (Vec<SerialNumber>, BTreeMap<(usize, usize), char>) {
let mut numbers = Vec::new();
let mut symbols = BTreeMap::new();
for (line_no, line) in input.lines().enumerate() {
let mut prev_char = None;
let mut cur_no = 0_u64;
let mut cur_no_row_start = 0_usize;
for (row_no, c) in line.chars().enumerate() {
if let Some(d) = c.to_digit(10) {
if prev_char.is_some() {
cur_no = cur_no * 10 + u64::from(d);
} else {
cur_no = u64::from(d);
cur_no_row_start = row_no;
}
prev_char = Some(c);
} else {
if prev_char.is_some() {
//handle saving number off
numbers.push(SerialNumber {
no: cur_no,
start: (cur_no_row_start, line_no),
end: (row_no - 1, line_no),
});
}
prev_char = None;
if c == '.' {
//move along space
continue;
}
//store symbol
let _ = symbols.insert((row_no, line_no), c);
}
}
//need to account for new line numbers
if prev_char.is_some() {
numbers.push( SerialNumber {
no: cur_no,
start: (cur_no_row_start, line_no),
end: (line.len() - 1, line_no),
});
}
}
(numbers, symbols)
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
const INPUT: &str = ""; const INPUT: &str = "467..114..
...*......
..35..633.
......#...
617*......
.....+.58.
..592.....
......755.
...$.*....
.664.598..";
const INPUT2: &str="12.......*..
+.........34
.......-12..
..78........
..*....60...
78.........9
.5.....23..$
8...90*12...
............
2.2......12.
.*.........*
1.1..503+.56";
#[test] #[test]
fn part1_works() { fn part1_works() {
let result = part1(INPUT); let result = part1(INPUT);
assert_eq!(result, "Not Finished".to_string()); assert_eq!(result, "4361".to_string());
}
} }
#[test]
fn part1_works_more() {
let result = part1(INPUT2);
assert_eq!(result, "925".to_string());
}
}

View File

@@ -1,18 +1,113 @@
#![warn(clippy::all, clippy::pedantic)]
use std::collections::BTreeMap;
pub fn part2 (_input: &str) -> String { #[derive(Debug)]
"Not Finished".to_string() struct SerialNumber {
pub no: u64,
pub start: (usize, usize),
pub end: (usize, usize),
}
impl SerialNumber {
fn is_adjacent(&self, pos: (usize, usize)) -> bool {
usize::abs_diff(self.start.1, pos.1) < 2
&& self.start.0 < 2 + pos.0
&& pos.0 < 2 + self.end.0
}
}
#[must_use]
pub fn part2(input: &str) -> String {
let (serials, symbols) = parse_input(input);
symbols
.iter()
.filter_map(|(key, value)| if *value == '*' { Some(*key) } else { None })
.filter_map(|pos| {
let serials = serials
.iter()
.filter_map(|serial| {
if serial.is_adjacent(pos) {
Some(serial.no)
} else {
None
}
})
.collect::<Vec<u64>>();
if serials.len() == 2 {
Some(serials[0] * serials[1])
} else {
None
}
})
.sum::<u64>()
.to_string()
//find all serials next to '*' and map with '*' location
}
fn parse_input(input: &str) -> (Vec<SerialNumber>, BTreeMap<(usize, usize), char>) {
let mut numbers = Vec::new();
let mut symbols = BTreeMap::new();
for (line_no, line) in input.lines().enumerate() {
let mut prev_char = None;
let mut cur_no = 0_u64;
let mut cur_no_row_start = 0_usize;
for (row_no, c) in line.chars().enumerate() {
if let Some(d) = c.to_digit(10) {
if prev_char.is_some() {
cur_no = cur_no * 10 + u64::from(d);
} else {
cur_no = u64::from(d);
cur_no_row_start = row_no;
}
prev_char = Some(c);
} else {
if prev_char.is_some() {
//handle saving number off
numbers.push(SerialNumber {
no: cur_no,
start: (cur_no_row_start, line_no),
end: (row_no - 1, line_no),
});
}
prev_char = None;
if c == '.' {
//move along space
continue;
}
//store symbol
let _ = symbols.insert((row_no, line_no), c);
}
}
//need to account for new line numbers
if prev_char.is_some() {
numbers.push(SerialNumber {
no: cur_no,
start: (cur_no_row_start, line_no),
end: (line.len() - 1, line_no),
});
}
}
(numbers, symbols)
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
const INPUT: &str = ""; const INPUT: &str = "467..114..
...*......
..35..633.
......#...
617*......
.....+.58.
..592.....
......755.
...$.*....
.664.598..";
#[test] #[test]
fn part2_works() { fn part2_works() {
let result = part2(INPUT); let result = part2(INPUT);
assert_eq!(result, "Not Finished".to_string()); assert_eq!(result, "467835".to_string());
} }
} }