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"
|
||||
|
||||
[dependencies]
|
||||
async-trait = "0.1.74"
|
||||
fancy-regex = "0.12.0"
|
||||
itertools = "0.12.0"
|
||||
strum = "0.25.0"
|
||||
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::*;
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let days: Vec<Box<dyn Solution>> = vec![
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
let days: Vec<Box<dyn Solution + Sync>> = vec![
|
||||
Box::new(day01::Day01 {}),
|
||||
Box::new(day02::Day02 {}),
|
||||
Box::new(day03::Day03 {}),
|
||||
@ -15,9 +16,24 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
Box::new(day06::Day06 {}),
|
||||
];
|
||||
|
||||
let mut t = vec![];
|
||||
|
||||
// Run through and generate solutions
|
||||
for day in days.iter().rev() {
|
||||
day.run()?;
|
||||
for day in days.leak().iter().rev() {
|
||||
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(())
|
||||
|
@ -24,7 +24,7 @@ impl Solution for Day01 {
|
||||
fn part1(
|
||||
&self,
|
||||
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]"#;
|
||||
let mut total: u32 = 0;
|
||||
for line in input {
|
||||
@ -37,7 +37,7 @@ impl Solution for Day01 {
|
||||
fn part2(
|
||||
&self,
|
||||
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"#;
|
||||
let mut total: u32 = 0;
|
||||
for line in input {
|
||||
|
@ -10,7 +10,7 @@ impl Solution for Day02 {
|
||||
fn part1(
|
||||
&self,
|
||||
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
|
||||
// Parse into regex with colour to get the number of colours for each game
|
||||
// Create an is Game Valid function
|
||||
@ -31,7 +31,7 @@ impl Solution for Day02 {
|
||||
fn part2(
|
||||
&self,
|
||||
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;
|
||||
for game in input.iter().enumerate() {
|
||||
let mut min_count: HashMap<&str, u32> =
|
||||
|
@ -8,7 +8,7 @@ impl Solution for Day03 {
|
||||
fn part1(
|
||||
&self,
|
||||
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
|
||||
let lines = input.iter().map(|s| s.as_bytes()).collect::<Vec<_>>();
|
||||
let mut symbols: HashMap<(usize, usize, char), Vec<usize>> = HashMap::new();
|
||||
@ -23,7 +23,7 @@ impl Solution for Day03 {
|
||||
fn part2(
|
||||
&self,
|
||||
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
|
||||
let lines = input.iter().map(|s| s.as_bytes()).collect::<Vec<_>>();
|
||||
let mut symbols: HashMap<(usize, usize, char), Vec<usize>> = HashMap::new();
|
||||
|
@ -1,6 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
||||
use super::Solution;
|
||||
|
||||
pub struct Day04 {}
|
||||
@ -9,7 +8,7 @@ impl Solution for Day04 {
|
||||
fn part1(
|
||||
&self,
|
||||
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
|
||||
let cards: Vec<&str> = input
|
||||
.iter()
|
||||
@ -29,7 +28,7 @@ impl Solution for Day04 {
|
||||
fn part2(
|
||||
&self,
|
||||
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
|
||||
let cards: Vec<(usize, &str)> = input
|
||||
.iter()
|
||||
@ -45,7 +44,9 @@ impl Solution for Day04 {
|
||||
|
||||
// Check if we are looking at a winning 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
|
||||
for j in 0..winning_nums {
|
||||
|
@ -7,49 +7,63 @@ impl Solution for Day05 {
|
||||
fn part1(
|
||||
&self,
|
||||
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 locations = maps.iter().fold(seeds, |seeds, mappings|
|
||||
seeds.iter().map(|&seed|
|
||||
mappings.iter()
|
||||
.find(|&&(_, src, range)| (src..src+range).contains(&seed))
|
||||
.map(|(dst, src, _)| dst + seed - src)
|
||||
.unwrap_or(seed)
|
||||
).collect()
|
||||
);
|
||||
let locations = maps.iter().fold(seeds, |seeds, mappings| {
|
||||
seeds
|
||||
.iter()
|
||||
.map(|&seed| {
|
||||
mappings
|
||||
.iter()
|
||||
.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()))
|
||||
}
|
||||
|
||||
fn part2(
|
||||
&self,
|
||||
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 = seeds.iter()
|
||||
let seeds = seeds
|
||||
.iter()
|
||||
.tuples()
|
||||
.map(|(&a, len)| (a, a + len))
|
||||
.collect::<Vec<_>>();
|
||||
let locations = maps.iter().fold(seeds, |seeds, mappings|
|
||||
seeds.iter().flat_map(|&(start, end)| {
|
||||
let mut mapped = Vec::new();
|
||||
let mut unmapped = vec![(start, end)];
|
||||
for &(dst, src, len) in mappings {
|
||||
let mut m = Vec::new();
|
||||
for (start, end) in unmapped {
|
||||
let a = (start, end.min(src));
|
||||
let b = (start.max(src), (src+len).min(end));
|
||||
let c = ((src+len).max(start), end);
|
||||
if a.0 < a.1 { m.push(a); }
|
||||
if b.0 < b.1 { mapped.push((b.0-src+dst, b.1-src+dst)); }
|
||||
if c.0 < c.1 { m.push(c); }
|
||||
}
|
||||
unmapped = m;
|
||||
}
|
||||
mapped.extend(unmapped);
|
||||
mapped
|
||||
}).collect()
|
||||
);
|
||||
let locations = maps.iter().fold(seeds, |seeds, mappings| {
|
||||
seeds
|
||||
.iter()
|
||||
.flat_map(|&(start, end)| {
|
||||
let mut mapped = Vec::new();
|
||||
let mut unmapped = vec![(start, end)];
|
||||
for &(dst, src, len) in mappings {
|
||||
let mut m = Vec::new();
|
||||
for (start, end) in unmapped {
|
||||
let a = (start, end.min(src));
|
||||
let b = (start.max(src), (src + len).min(end));
|
||||
let c = ((src + len).max(start), end);
|
||||
if a.0 < a.1 {
|
||||
m.push(a);
|
||||
}
|
||||
if b.0 < b.1 {
|
||||
mapped.push((b.0 - src + dst, b.1 - src + dst));
|
||||
}
|
||||
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()))
|
||||
}
|
||||
|
||||
@ -59,21 +73,31 @@ impl Solution for Day05 {
|
||||
}
|
||||
|
||||
impl Day05 {
|
||||
fn get_mappings(&self, input: &Vec<String>) -> Result<(Vec<usize>, Vec<Vec<(usize, usize, usize)>>), Box<dyn std::error::Error>> {
|
||||
let seeds: Vec<usize> = input[0].split_whitespace()
|
||||
.skip(1)
|
||||
.map(|s| s.parse().unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
fn get_mappings(
|
||||
&self,
|
||||
input: &Vec<String>,
|
||||
) -> Result<(Vec<usize>, Vec<Vec<(usize, usize, usize)>>), Box<dyn std::error::Error>> {
|
||||
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")
|
||||
.split("\n\n").map(|s|
|
||||
s.split('\n').skip(1).map(|l|
|
||||
l.split_whitespace()
|
||||
.map(|s| s.parse().unwrap())
|
||||
.collect_tuple()
|
||||
.unwrap()
|
||||
).collect::<Vec<_>>()
|
||||
).collect::<Vec<_>>();
|
||||
let maps: Vec<Vec<(usize, usize, usize)>> = input[2..input.len()]
|
||||
.join("\n")
|
||||
.split("\n\n")
|
||||
.map(|s| {
|
||||
s.split('\n')
|
||||
.skip(1)
|
||||
.map(|l| {
|
||||
l.split_whitespace()
|
||||
.map(|s| s.parse().unwrap())
|
||||
.collect_tuple()
|
||||
.unwrap()
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok((seeds, maps))
|
||||
}
|
||||
|
@ -6,14 +6,14 @@ impl Solution for Day06 {
|
||||
fn part1(
|
||||
&self,
|
||||
_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"))
|
||||
}
|
||||
|
||||
fn part2(
|
||||
&self,
|
||||
_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"))
|
||||
}
|
||||
|
||||
|
@ -9,34 +9,27 @@ use crate::utils::{self, get_input};
|
||||
use std::{error::Error, fmt::Display, time::SystemTime};
|
||||
|
||||
pub trait Solution {
|
||||
fn part1(&self, input: &mut Vec<String>) -> Result<Box<dyn Display>, Box<dyn Error>>;
|
||||
fn part2(&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 + Sync>, Box<dyn Error>>;
|
||||
fn get_day(&self) -> u8;
|
||||
|
||||
fn run(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("========== Day {} ==========", self.get_day());
|
||||
fn run(&self) -> Result<Run, Box<dyn std::error::Error>> {
|
||||
let start_time = SystemTime::now();
|
||||
println!(
|
||||
"Part1 Test: {}",
|
||||
self.part1(get_input(self.get_day(), utils::InputType::Test1)?.as_mut())?
|
||||
);
|
||||
println!(
|
||||
"Part1 Result: {}",
|
||||
self.part1(get_input(self.get_day(), utils::InputType::Actual)?.as_mut())?
|
||||
);
|
||||
|
||||
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(())
|
||||
let run = Run {
|
||||
part1: self.part1(get_input(self.get_day(), utils::InputType::Actual)?.as_mut())?,
|
||||
part2: self.part2(get_input(self.get_day(), utils::InputType::Actual)?.as_mut())?,
|
||||
day: self.get_day(),
|
||||
time: SystemTime::now().duration_since(start_time)?,
|
||||
};
|
||||
Ok(run)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
#[allow(unused)]
|
||||
pub enum InputType {
|
||||
Test1,
|
||||
Test2,
|
||||
|
Loading…
Reference in New Issue
Block a user