diff --git a/Cargo.lock b/Cargo.lock index 14e1446..4408e62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,8 +7,15 @@ name = "advent_2023" version = "0.1.0" dependencies = [ "itertools", + "num", ] +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "either" version = "1.9.0" @@ -23,3 +30,79 @@ checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" dependencies = [ "either", ] + +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] diff --git a/Cargo.toml b/Cargo.toml index 9fc82ee..f5fc635 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,4 @@ edition = "2021" [dependencies] itertools = "0.12.0" +num = "0.4.1" diff --git a/src/days/day1.rs b/src/days/day1.rs index 3ff4af5..b497059 100644 --- a/src/days/day1.rs +++ b/src/days/day1.rs @@ -1,10 +1,12 @@ use std::{path::Path, vec}; +use itertools::Itertools; + use crate::{input::read_into_vec, error::AdventError}; -fn process(lines: Vec::) -> Result { - let calibrations: Vec = lines.iter().map(|v| { +fn process(lines: Vec::) -> Result { + let calibrations = lines.iter().map(|v| { let first_digit = v.as_bytes() .iter() .skip_while(|i| { @@ -18,14 +20,14 @@ fn process(lines: Vec::) -> Result { .skip_while(|i| { **i < 48u8 || **i > 57u8 }) .take(1).collect::>()[0]; - (*first_digit - 48) as u32 * 10 + (*last_digit - 48) as u32 + (*first_digit - 48) as u64 * 10 + (*last_digit - 48) as u64 - }).collect(); + }).collect_vec(); - Ok(calibrations.iter().sum::()) + Ok(calibrations.iter().sum()) } -pub fn one() -> Result { +pub fn one() -> Result { let lines: Vec = read_into_vec::(Path::new("resources/input1.txt"))?; Ok(process(lines)?) } @@ -33,7 +35,7 @@ pub fn one() -> Result { struct Mutation(usize, char); struct Pattern(&'static str, char); -pub fn two() -> Result { +pub fn two() -> Result { let mut lines = read_into_vec(Path::new("resources/input1.txt"))?; let mut mutations = Vec::::new(); diff --git a/src/days/day2.rs b/src/days/day2.rs index 720a7eb..0368db1 100644 --- a/src/days/day2.rs +++ b/src/days/day2.rs @@ -20,7 +20,7 @@ impl FromStr for Group { fn from_str(s: &str) -> Result { let split = s.split(' ').collect::>(); - Ok(Group{count: u32::from_str(split[0])?, color: Color::from_str(split[1])?}) + Ok(Group{count: u64::from_str(split[0])?, color: Color::from_str(split[1])?}) } } @@ -42,7 +42,7 @@ impl FromStr for Game { fn from_str(s: &str) -> Result { let split = s.split(':').collect::>(); - let id = u32::from_str(split[0].split(' ').collect::>()[1])?; + let id = u64::from_str(split[0].split(' ').collect::>()[1])?; let pulls = split[1]; let mut res = Vec::::new(); for pull in pulls.split(',') { @@ -62,7 +62,7 @@ enum Color { #[derive(Debug)] struct Group { - count: u32, + count: u64, color: Color, } @@ -73,14 +73,14 @@ struct Pull { #[derive(Debug)] struct Game { - id: u32, + id: u64, pulls: Vec } -pub fn one() -> Result { +pub fn one() -> Result { let games: Vec = read_into_vec(Path::new("resources/input2.txt"))?; - let mut sum: u32 = 0; + let mut sum: u64 = 0; let max_red = 12; let max_green = 13; @@ -103,14 +103,14 @@ pub fn one() -> Result { Ok(sum) } -pub fn two() -> Result { +pub fn two() -> Result { let games: Vec = read_into_vec(Path::new("resources/input2.txt"))?; - let mut power: u32 = 0; + let mut power: u64 = 0; for game in games.iter() { - let mut max_nr_red = 0; - let mut max_nr_green = 0; - let mut max_nr_blue = 0; + let mut max_nr_red = 0u64; + let mut max_nr_green = 0u64; + let mut max_nr_blue = 0u64; for pull in game.pulls.iter() { for group in pull.groups.iter() { match group.color { diff --git a/src/days/day3.rs b/src/days/day3.rs index 7f6bf45..2586b70 100644 --- a/src/days/day3.rs +++ b/src/days/day3.rs @@ -6,7 +6,7 @@ use crate::{input::read_into_vec, error::AdventError}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Number { - value: u32, + value: u64, position: u8, length: u8 } @@ -179,9 +179,9 @@ fn filter_gears(rows: &mut Vec) -> &mut Vec { rows } -pub fn one() -> Result { +pub fn one() -> Result { let rows = read_into_vec::(Path::new("resources/input3.txt"))?; - let mut sum: u32 = 0; + let mut sum: u64 = 0; for (i, row) in rows.iter().enumerate() { for number in row.numbers.iter() { let coords = gen_coords_number(i, number); @@ -199,10 +199,10 @@ pub fn one() -> Result { Ok(sum) } -pub fn two() -> Result { +pub fn two() -> Result { let mut rows = read_into_vec::(Path::new("resources/input3.txt"))?; rows = filter_gears(&mut rows).clone(); - let mut sum: u32 = 0; + let mut sum: u64 = 0; for (i, row) in rows.iter().enumerate() { for symbol in row.symbols.iter() { let coords = gen_coords_symbol(i, symbol); diff --git a/src/days/day4.rs b/src/days/day4.rs index c637b73..3f5d81d 100644 --- a/src/days/day4.rs +++ b/src/days/day4.rs @@ -32,7 +32,7 @@ struct ScratchGame { winning_numbers: HashSet } -pub fn one() -> Result { +pub fn one() -> Result { let games = read_into_vec::(Path::new("resources/input4.txt"))?; Ok(games.into_iter().fold(Ok(0), |acc: Result, game: ScratchGame| { let acc = acc?; @@ -41,12 +41,12 @@ pub fn one() -> Result { 0 => 0, x => (2 as u64).pow((x-1).try_into()?) }) - })? as u32) + })? as u64) } -pub fn two() -> Result { +pub fn two() -> Result { let games = read_into_vec::(Path::new("resources/input4.txt"))?; - let mut vec = Vec::::new(); + let mut vec = Vec::::new(); vec.resize(games.len(), 1); Ok(games.into_iter().fold(0, | acc, game | { diff --git a/src/days/day5.rs b/src/days/day5.rs index f92b6aa..d926d78 100644 --- a/src/days/day5.rs +++ b/src/days/day5.rs @@ -214,15 +214,15 @@ impl FromStr for Almanac { } } -pub fn one() -> Result +pub fn one() -> Result { let almanac = read_into::(Path::new("resources/input5.txt".into()))?; - Ok(almanac.find_closest(true)?) + Ok(almanac.find_closest(true)? as u64) } -pub fn two() -> Result +pub fn two() -> Result { let mut almanac = read_into::(Path::new("resources/input5.txt".into()))?; almanac.interpret_range(); - Ok(almanac.find_closest(false)?) + Ok(almanac.find_closest(false)? as u64) } \ No newline at end of file diff --git a/src/days/day6.rs b/src/days/day6.rs index 44f9f53..ef1b58b 100644 --- a/src/days/day6.rs +++ b/src/days/day6.rs @@ -87,14 +87,14 @@ pub fn number_of_record_beating_chances(max_time: i128, record: i128) -> u32 { (answer2.ceil() - answer1.ceil()) as u32 } -pub fn one() -> Result { +pub fn one() -> Result { let overview = read_into::(Path::new("resources/input6.txt"))?; Ok(overview.records.iter().fold(1, |acc, record| { acc * number_of_record_beating_chances(record.time.into(), record.distance.into()) - })) + }) as u64) } -pub fn two() -> Result { +pub fn two() -> Result { let record = read_into::(Path::new("resources/input6.txt"))?; - Ok(number_of_record_beating_chances(record.time.into(), record.distance.into())) + Ok(number_of_record_beating_chances(record.time.into(), record.distance.into()) as u64) } \ No newline at end of file diff --git a/src/days/day7.rs b/src/days/day7.rs index d9b9cf4..a0e4d12 100644 --- a/src/days/day7.rs +++ b/src/days/day7.rs @@ -421,18 +421,18 @@ impl FromStr for LineTwo { } } -pub fn one() -> Result { +pub fn one() -> Result { let mut lines = read_into_vec::(Path::new("resources/input7.txt".into()))?; lines.sort(); Ok(lines.iter().enumerate().fold(0, |acc, (rank, hand)| { acc + (rank as u32 + 1) * hand.bid - })) + }) as u64) } -pub fn two() -> Result { +pub fn two() -> Result { let mut lines = read_into_vec::(Path::new("resources/input7.txt".into()))?; lines.sort(); Ok(lines.iter().enumerate().fold(0, |acc, (rank, hand)| { acc + (rank as u32 + 1) * hand.bid - })) + }) as u64) } \ No newline at end of file diff --git a/src/days/day8.rs b/src/days/day8.rs index 8cd26ae..104ed5e 100644 --- a/src/days/day8.rs +++ b/src/days/day8.rs @@ -1,6 +1,7 @@ use std::{path::Path, str::FromStr, collections::HashMap}; use itertools::Itertools; +use num::integer::gcd; use crate::{error::AdventError, input::read_into}; @@ -105,35 +106,38 @@ fn is_end1(node: &String) -> bool { node == &"ZZZ".to_string() } -fn is_end2(nodes: &Vec) -> bool { - nodes.iter().all(|x| { - x.ends_with('Z') - }) +fn is_end2(node: &String) -> bool { + node.ends_with('Z') } -pub fn one() -> Result { +pub fn one() -> Result { let map = read_into::(Path::new("resources/input8.txt"))?.0; let mut node = map.start[0].clone(); for (i, direction) in map.directions.iter().cycle().enumerate() { node = map.take_step(&node, direction)?; if is_end1(&node) { - return Ok(i as u32 +1); + return Ok(i as u64 + 1); } } panic!("Cycle iterator should never terminate") } -pub fn two() -> Result { +pub fn two() -> Result { let map = read_into::(Path::new("resources/input8.txt"))?.0; let mut nodes = map.start.clone(); - for (i, direction) in map.directions.iter().cycle().enumerate() { - nodes = nodes.iter().map(|current| { - map.take_step(¤t, direction) - }).collect::,AdventError>>()?.iter().unique().map(|x| x.clone()).collect_vec(); - - if is_end2(&nodes) { - return Ok(i as u32 +1); + let iterations = nodes.iter_mut().map(|current| { + for (i, direction) in map.directions.iter().cycle().enumerate() { + current.clone_from(&map.take_step(current, direction)?); + if is_end2(¤t) { + return Ok((i + 1) as u64); + } } - } - panic!("Cycle iterator should never terminate") + panic!("Cycle iterator should never terminate") + }).collect::, AdventError>>()?; + let mut iter = iterations.into_iter(); + let acc = iter.next().unwrap() as u64; + Ok(iter.fold(Ok(acc), |acc, i| -> Result { + let accumulator = acc?; + return Ok(i * accumulator / gcd(i, accumulator)); + })?) } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c3eba50..a56417b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,14 +11,14 @@ use crate::error::AdventError; fn main() -> Result<(), AdventError> { let days = vec![ - (day1::one as fn() -> Result, day1::two as fn() -> Result), - (day2::one as fn() -> Result, day2::two as fn() -> Result), - (day3::one as fn() -> Result, day3::two as fn() -> Result), - (day4::one as fn() -> Result, day4::two as fn() -> Result), - (day5::one as fn() -> Result, day5::two as fn() -> Result), - (day6::one as fn() -> Result, day6::two as fn() -> Result), - (day7::one as fn() -> Result, day7::two as fn() -> Result), - (day8::one as fn() -> Result, day8::two as fn() -> Result), + (day1::one as fn() -> Result, day1::two as fn() -> Result), + (day2::one as fn() -> Result, day2::two as fn() -> Result), + (day3::one as fn() -> Result, day3::two as fn() -> Result), + (day4::one as fn() -> Result, day4::two as fn() -> Result), + (day5::one as fn() -> Result, day5::two as fn() -> Result), + (day6::one as fn() -> Result, day6::two as fn() -> Result), + (day7::one as fn() -> Result, day7::two as fn() -> Result), + (day8::one as fn() -> Result, day8::two as fn() -> Result), ]; if env::args().len() == 1 { @@ -26,7 +26,7 @@ fn main() -> Result<(), AdventError> { let one_result = one()?; let two_result = two()?; Ok((one_result, two_result)) - }).enumerate().map(|(index, r): (usize, Result<(u32, u32), AdventError>)| { + }).enumerate().map(|(index, r): (usize, Result<(u64, u64), AdventError>)| { match r { Ok((res1, res2)) => println!("{}: ({}, {})", index + 1, res1, res2), Err(e) => println!("Error: {}", e.0)