Day 3 done and pedantic clippy clean up
This commit is contained in:
@@ -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(),
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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:?}");
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user