Parallelised the execution of each day
This commit is contained in:
parent
ed05221dff
commit
43e3a8ac35
@ -4,7 +4,9 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
async-trait = "0.1.74"
|
||||||
fancy-regex = "0.12.0"
|
fancy-regex = "0.12.0"
|
||||||
itertools = "0.12.0"
|
itertools = "0.12.0"
|
||||||
strum = "0.25.0"
|
strum = "0.25.0"
|
||||||
strum_macros = "0.25.3"
|
strum_macros = "0.25.3"
|
||||||
|
tokio = {version = "1.34.0", features = ["full"]}
|
||||||
|
24
src/main.rs
24
src/main.rs
@ -5,8 +5,9 @@ use std::error::Error;
|
|||||||
|
|
||||||
use solutions::*;
|
use solutions::*;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
#[tokio::main]
|
||||||
let days: Vec<Box<dyn Solution>> = vec![
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let days: Vec<Box<dyn Solution + Sync>> = vec![
|
||||||
Box::new(day01::Day01 {}),
|
Box::new(day01::Day01 {}),
|
||||||
Box::new(day02::Day02 {}),
|
Box::new(day02::Day02 {}),
|
||||||
Box::new(day03::Day03 {}),
|
Box::new(day03::Day03 {}),
|
||||||
@ -15,9 +16,24 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
Box::new(day06::Day06 {}),
|
Box::new(day06::Day06 {}),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let mut t = vec![];
|
||||||
|
|
||||||
// Run through and generate solutions
|
// Run through and generate solutions
|
||||||
for day in days.iter().rev() {
|
for day in days.leak().iter().rev() {
|
||||||
day.run()?;
|
let task = tokio::spawn(async { day.run().unwrap() });
|
||||||
|
t.push(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut days = vec![];
|
||||||
|
for thread in t {
|
||||||
|
days.push(thread.await?);
|
||||||
|
}
|
||||||
|
|
||||||
|
for day in days {
|
||||||
|
println!("========= Day {} ==========", day.day);
|
||||||
|
println!("Part1 Result: {}", day.part1);
|
||||||
|
println!("Part2 Result: {}", day.part2);
|
||||||
|
println!("========= {}ms =========", day.time.as_millis());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -24,7 +24,7 @@ impl Solution for Day01 {
|
|||||||
fn part1(
|
fn part1(
|
||||||
&self,
|
&self,
|
||||||
input: &mut Vec<String>,
|
input: &mut Vec<String>,
|
||||||
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
|
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
|
||||||
const REG: &str = r#"[0-9]"#;
|
const REG: &str = r#"[0-9]"#;
|
||||||
let mut total: u32 = 0;
|
let mut total: u32 = 0;
|
||||||
for line in input {
|
for line in input {
|
||||||
@ -37,7 +37,7 @@ impl Solution for Day01 {
|
|||||||
fn part2(
|
fn part2(
|
||||||
&self,
|
&self,
|
||||||
input: &mut Vec<String>,
|
input: &mut Vec<String>,
|
||||||
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
|
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
|
||||||
const REG: &str = r#"[0-9]|one|two|three|four|five|six|seven|eight|nine"#;
|
const REG: &str = r#"[0-9]|one|two|three|four|five|six|seven|eight|nine"#;
|
||||||
let mut total: u32 = 0;
|
let mut total: u32 = 0;
|
||||||
for line in input {
|
for line in input {
|
||||||
|
@ -10,7 +10,7 @@ impl Solution for Day02 {
|
|||||||
fn part1(
|
fn part1(
|
||||||
&self,
|
&self,
|
||||||
input: &mut Vec<String>,
|
input: &mut Vec<String>,
|
||||||
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
|
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
|
||||||
// Read games
|
// Read games
|
||||||
// Parse into regex with colour to get the number of colours for each game
|
// Parse into regex with colour to get the number of colours for each game
|
||||||
// Create an is Game Valid function
|
// Create an is Game Valid function
|
||||||
@ -31,7 +31,7 @@ impl Solution for Day02 {
|
|||||||
fn part2(
|
fn part2(
|
||||||
&self,
|
&self,
|
||||||
input: &mut Vec<String>,
|
input: &mut Vec<String>,
|
||||||
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
|
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
|
||||||
let mut power = 0u32;
|
let mut power = 0u32;
|
||||||
for game in input.iter().enumerate() {
|
for game in input.iter().enumerate() {
|
||||||
let mut min_count: HashMap<&str, u32> =
|
let mut min_count: HashMap<&str, u32> =
|
||||||
|
@ -8,7 +8,7 @@ impl Solution for Day03 {
|
|||||||
fn part1(
|
fn part1(
|
||||||
&self,
|
&self,
|
||||||
input: &mut Vec<String>,
|
input: &mut Vec<String>,
|
||||||
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
|
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
|
||||||
// Get data into a byte array
|
// Get data into a byte array
|
||||||
let lines = input.iter().map(|s| s.as_bytes()).collect::<Vec<_>>();
|
let lines = input.iter().map(|s| s.as_bytes()).collect::<Vec<_>>();
|
||||||
let mut symbols: HashMap<(usize, usize, char), Vec<usize>> = HashMap::new();
|
let mut symbols: HashMap<(usize, usize, char), Vec<usize>> = HashMap::new();
|
||||||
@ -23,7 +23,7 @@ impl Solution for Day03 {
|
|||||||
fn part2(
|
fn part2(
|
||||||
&self,
|
&self,
|
||||||
input: &mut Vec<String>,
|
input: &mut Vec<String>,
|
||||||
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
|
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
|
||||||
// Get data into a byte array
|
// Get data into a byte array
|
||||||
let lines = input.iter().map(|s| s.as_bytes()).collect::<Vec<_>>();
|
let lines = input.iter().map(|s| s.as_bytes()).collect::<Vec<_>>();
|
||||||
let mut symbols: HashMap<(usize, usize, char), Vec<usize>> = HashMap::new();
|
let mut symbols: HashMap<(usize, usize, char), Vec<usize>> = HashMap::new();
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
|
||||||
use super::Solution;
|
use super::Solution;
|
||||||
|
|
||||||
pub struct Day04 {}
|
pub struct Day04 {}
|
||||||
@ -9,7 +8,7 @@ impl Solution for Day04 {
|
|||||||
fn part1(
|
fn part1(
|
||||||
&self,
|
&self,
|
||||||
input: &mut Vec<String>,
|
input: &mut Vec<String>,
|
||||||
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
|
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
|
||||||
// Remove Card XXX: at start
|
// Remove Card XXX: at start
|
||||||
let cards: Vec<&str> = input
|
let cards: Vec<&str> = input
|
||||||
.iter()
|
.iter()
|
||||||
@ -29,7 +28,7 @@ impl Solution for Day04 {
|
|||||||
fn part2(
|
fn part2(
|
||||||
&self,
|
&self,
|
||||||
input: &mut Vec<String>,
|
input: &mut Vec<String>,
|
||||||
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
|
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
|
||||||
// Remove Card XXX: at start and append card index
|
// Remove Card XXX: at start and append card index
|
||||||
let cards: Vec<(usize, &str)> = input
|
let cards: Vec<(usize, &str)> = input
|
||||||
.iter()
|
.iter()
|
||||||
@ -45,7 +44,9 @@ impl Solution for Day04 {
|
|||||||
|
|
||||||
// Check if we are looking at a winning card
|
// Check if we are looking at a winning card
|
||||||
let winning_nums = self.get_count_winning_numbers(card)?;
|
let winning_nums = self.get_count_winning_numbers(card)?;
|
||||||
if winning_nums == 0 { continue; }
|
if winning_nums == 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// We have a winning card... add the next cards resulting * num of current card
|
// We have a winning card... add the next cards resulting * num of current card
|
||||||
for j in 0..winning_nums {
|
for j in 0..winning_nums {
|
||||||
@ -53,7 +54,7 @@ impl Solution for Day04 {
|
|||||||
copy_counts[*i + j + 1] += copy_counts[*i];
|
copy_counts[*i + j + 1] += copy_counts[*i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Box::new(copy_counts.iter().sum::<u32>()))
|
Ok(Box::new(copy_counts.iter().sum::<u32>()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,49 +7,63 @@ impl Solution for Day05 {
|
|||||||
fn part1(
|
fn part1(
|
||||||
&self,
|
&self,
|
||||||
input: &mut Vec<String>,
|
input: &mut Vec<String>,
|
||||||
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
|
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
|
||||||
let (seeds, maps) = self.get_mappings(input)?;
|
let (seeds, maps) = self.get_mappings(input)?;
|
||||||
let locations = maps.iter().fold(seeds, |seeds, mappings|
|
let locations = maps.iter().fold(seeds, |seeds, mappings| {
|
||||||
seeds.iter().map(|&seed|
|
seeds
|
||||||
mappings.iter()
|
.iter()
|
||||||
.find(|&&(_, src, range)| (src..src+range).contains(&seed))
|
.map(|&seed| {
|
||||||
.map(|(dst, src, _)| dst + seed - src)
|
mappings
|
||||||
.unwrap_or(seed)
|
.iter()
|
||||||
).collect()
|
.find(|&&(_, src, range)| (src..src + range).contains(&seed))
|
||||||
);
|
.map(|(dst, src, _)| dst + seed - src)
|
||||||
|
.unwrap_or(seed)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
});
|
||||||
Ok(Box::new(*locations.iter().min().unwrap()))
|
Ok(Box::new(*locations.iter().min().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(
|
fn part2(
|
||||||
&self,
|
&self,
|
||||||
input: &mut Vec<String>,
|
input: &mut Vec<String>,
|
||||||
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
|
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
|
||||||
let (seeds, maps) = self.get_mappings(input)?;
|
let (seeds, maps) = self.get_mappings(input)?;
|
||||||
|
|
||||||
let seeds = seeds.iter()
|
let seeds = seeds
|
||||||
|
.iter()
|
||||||
.tuples()
|
.tuples()
|
||||||
.map(|(&a, len)| (a, a + len))
|
.map(|(&a, len)| (a, a + len))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let locations = maps.iter().fold(seeds, |seeds, mappings|
|
let locations = maps.iter().fold(seeds, |seeds, mappings| {
|
||||||
seeds.iter().flat_map(|&(start, end)| {
|
seeds
|
||||||
let mut mapped = Vec::new();
|
.iter()
|
||||||
let mut unmapped = vec![(start, end)];
|
.flat_map(|&(start, end)| {
|
||||||
for &(dst, src, len) in mappings {
|
let mut mapped = Vec::new();
|
||||||
let mut m = Vec::new();
|
let mut unmapped = vec![(start, end)];
|
||||||
for (start, end) in unmapped {
|
for &(dst, src, len) in mappings {
|
||||||
let a = (start, end.min(src));
|
let mut m = Vec::new();
|
||||||
let b = (start.max(src), (src+len).min(end));
|
for (start, end) in unmapped {
|
||||||
let c = ((src+len).max(start), end);
|
let a = (start, end.min(src));
|
||||||
if a.0 < a.1 { m.push(a); }
|
let b = (start.max(src), (src + len).min(end));
|
||||||
if b.0 < b.1 { mapped.push((b.0-src+dst, b.1-src+dst)); }
|
let c = ((src + len).max(start), end);
|
||||||
if c.0 < c.1 { m.push(c); }
|
if a.0 < a.1 {
|
||||||
}
|
m.push(a);
|
||||||
unmapped = m;
|
}
|
||||||
}
|
if b.0 < b.1 {
|
||||||
mapped.extend(unmapped);
|
mapped.push((b.0 - src + dst, b.1 - src + dst));
|
||||||
mapped
|
}
|
||||||
}).collect()
|
if c.0 < c.1 {
|
||||||
);
|
m.push(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unmapped = m;
|
||||||
|
}
|
||||||
|
mapped.extend(unmapped);
|
||||||
|
mapped
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
});
|
||||||
Ok(Box::new(locations.iter().map(|&(s, _)| s).min().unwrap()))
|
Ok(Box::new(locations.iter().map(|&(s, _)| s).min().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,21 +73,31 @@ impl Solution for Day05 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Day05 {
|
impl Day05 {
|
||||||
fn get_mappings(&self, input: &Vec<String>) -> Result<(Vec<usize>, Vec<Vec<(usize, usize, usize)>>), Box<dyn std::error::Error>> {
|
fn get_mappings(
|
||||||
let seeds: Vec<usize> = input[0].split_whitespace()
|
&self,
|
||||||
.skip(1)
|
input: &Vec<String>,
|
||||||
.map(|s| s.parse().unwrap())
|
) -> Result<(Vec<usize>, Vec<Vec<(usize, usize, usize)>>), Box<dyn std::error::Error>> {
|
||||||
.collect::<Vec<_>>();
|
let seeds: Vec<usize> = input[0]
|
||||||
|
.split_whitespace()
|
||||||
|
.skip(1)
|
||||||
|
.map(|s| s.parse().unwrap())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let maps: Vec<Vec<(usize, usize, usize)>> = input[2..input.len()].join("\n")
|
let maps: Vec<Vec<(usize, usize, usize)>> = input[2..input.len()]
|
||||||
.split("\n\n").map(|s|
|
.join("\n")
|
||||||
s.split('\n').skip(1).map(|l|
|
.split("\n\n")
|
||||||
l.split_whitespace()
|
.map(|s| {
|
||||||
.map(|s| s.parse().unwrap())
|
s.split('\n')
|
||||||
.collect_tuple()
|
.skip(1)
|
||||||
.unwrap()
|
.map(|l| {
|
||||||
).collect::<Vec<_>>()
|
l.split_whitespace()
|
||||||
).collect::<Vec<_>>();
|
.map(|s| s.parse().unwrap())
|
||||||
|
.collect_tuple()
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
Ok((seeds, maps))
|
Ok((seeds, maps))
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,14 @@ impl Solution for Day06 {
|
|||||||
fn part1(
|
fn part1(
|
||||||
&self,
|
&self,
|
||||||
_input: &mut Vec<String>,
|
_input: &mut Vec<String>,
|
||||||
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
|
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
|
||||||
Ok(Box::new("Ready"))
|
Ok(Box::new("Ready"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(
|
fn part2(
|
||||||
&self,
|
&self,
|
||||||
_input: &mut Vec<String>,
|
_input: &mut Vec<String>,
|
||||||
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
|
) -> Result<Box<dyn std::fmt::Display + Sync>, Box<dyn std::error::Error>> {
|
||||||
Ok(Box::new("Ready"))
|
Ok(Box::new("Ready"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,34 +9,27 @@ use crate::utils::{self, get_input};
|
|||||||
use std::{error::Error, fmt::Display, time::SystemTime};
|
use std::{error::Error, fmt::Display, time::SystemTime};
|
||||||
|
|
||||||
pub trait Solution {
|
pub trait Solution {
|
||||||
fn part1(&self, input: &mut Vec<String>) -> Result<Box<dyn Display>, Box<dyn Error>>;
|
fn part1(&self, input: &mut Vec<String>) -> Result<Box<dyn Display + Sync>, Box<dyn Error>>;
|
||||||
fn part2(&self, input: &mut Vec<String>) -> Result<Box<dyn Display>, Box<dyn Error>>;
|
fn part2(&self, input: &mut Vec<String>) -> Result<Box<dyn Display + Sync>, Box<dyn Error>>;
|
||||||
fn get_day(&self) -> u8;
|
fn get_day(&self) -> u8;
|
||||||
|
|
||||||
fn run(&self) -> Result<(), Box<dyn std::error::Error>> {
|
fn run(&self) -> Result<Run, Box<dyn std::error::Error>> {
|
||||||
println!("========== Day {} ==========", self.get_day());
|
|
||||||
let start_time = SystemTime::now();
|
let start_time = SystemTime::now();
|
||||||
println!(
|
let run = Run {
|
||||||
"Part1 Test: {}",
|
part1: self.part1(get_input(self.get_day(), utils::InputType::Actual)?.as_mut())?,
|
||||||
self.part1(get_input(self.get_day(), utils::InputType::Test1)?.as_mut())?
|
part2: self.part2(get_input(self.get_day(), utils::InputType::Actual)?.as_mut())?,
|
||||||
);
|
day: self.get_day(),
|
||||||
println!(
|
time: SystemTime::now().duration_since(start_time)?,
|
||||||
"Part1 Result: {}",
|
};
|
||||||
self.part1(get_input(self.get_day(), utils::InputType::Actual)?.as_mut())?
|
Ok(run)
|
||||||
);
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"Part2 Test: {}",
|
|
||||||
self.part2(get_input(self.get_day(), utils::InputType::Test2)?.as_mut())?
|
|
||||||
);
|
|
||||||
println!(
|
|
||||||
"Part2 Result: {}",
|
|
||||||
self.part2(get_input(self.get_day(), utils::InputType::Actual)?.as_mut())?
|
|
||||||
);
|
|
||||||
println!(
|
|
||||||
"========= {}ms =========",
|
|
||||||
SystemTime::now().duration_since(start_time)?.as_millis()
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Run {
|
||||||
|
pub part1: Box<dyn Display + Sync>,
|
||||||
|
pub part2: Box<dyn Display + Sync>,
|
||||||
|
pub day: u8,
|
||||||
|
pub time: core::time::Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for Run {}
|
||||||
|
@ -5,6 +5,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Enum used to specify input
|
/// Enum used to specify input
|
||||||
|
#[allow(unused)]
|
||||||
pub enum InputType {
|
pub enum InputType {
|
||||||
Test1,
|
Test1,
|
||||||
Test2,
|
Test2,
|
||||||
|
Loading…
Reference in New Issue
Block a user