Refactor into cli and lib packages
This commit is contained in:
parent
4b1b27e2c6
commit
a622539277
18 changed files with 95 additions and 72 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -21,7 +21,6 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
name = "advent"
|
name = "advent"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-irrational",
|
"num-irrational",
|
||||||
"num-rational",
|
"num-rational",
|
||||||
|
@ -31,6 +30,15 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "advent-cli"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"advent",
|
||||||
|
"clap",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.8.6"
|
version = "0.8.6"
|
||||||
|
|
19
Cargo.toml
19
Cargo.toml
|
@ -1,16 +1,3 @@
|
||||||
[package]
|
[workspace]
|
||||||
name = "advent"
|
members = ["cli", "lib"]
|
||||||
version = "0.1.0"
|
resolver = "2"
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
clap = { version = "4.4.10", features = ["derive"] }
|
|
||||||
num-bigint = "0.4.4"
|
|
||||||
num-irrational = { version = "0.3.0", features = ["num-bigint"] }
|
|
||||||
num-rational = { version = "0.4.1", features = ["num-bigint"] }
|
|
||||||
regex = "1.10.2"
|
|
||||||
reqwest = "0.11.22"
|
|
||||||
scraper = "0.18.1"
|
|
||||||
tokio = { version = "1.34.0", features = ["macros", "rt-multi-thread"] }
|
|
9
cli/Cargo.toml
Normal file
9
cli/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "advent-cli"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
clap = { version = "4.4.10", features = ["derive"] }
|
||||||
|
tokio = { version = "1.34.0", features = ["macros", "rt-multi-thread"] }
|
||||||
|
advent = { path = "../lib" }
|
|
@ -4,25 +4,11 @@ use std::{
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use clap::{Parser, Subcommand, ValueEnum};
|
use advent::{
|
||||||
|
|
||||||
use crate::{
|
|
||||||
day1::Day1, day10::Day10, day2::Day2, day3::Day3, day4::Day4, day5::Day5, day6::Day6,
|
day1::Day1, day10::Day10, day2::Day2, day3::Day3, day4::Day4, day5::Day5, day6::Day6,
|
||||||
day7::Day7, day8::Day8, day9::Day9, utils::Day,
|
day7::Day7, day8::Day8, day9::Day9, fetcher, utils::Day,
|
||||||
};
|
};
|
||||||
|
use clap::{Parser, Subcommand, ValueEnum};
|
||||||
pub mod day1;
|
|
||||||
pub mod day10;
|
|
||||||
pub mod day2;
|
|
||||||
pub mod day3;
|
|
||||||
pub mod day4;
|
|
||||||
pub mod day5;
|
|
||||||
pub mod day6;
|
|
||||||
pub mod day7;
|
|
||||||
pub mod day8;
|
|
||||||
pub mod day9;
|
|
||||||
pub mod fetcher;
|
|
||||||
pub mod utils;
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
|
@ -86,7 +72,6 @@ enum Subcommands {
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
let client = reqwest::Client::new();
|
|
||||||
let auth = cli
|
let auth = cli
|
||||||
.auth
|
.auth
|
||||||
.unwrap_or(std::env::var("AOC_SESSION").ok().expect("no auth provided"));
|
.unwrap_or(std::env::var("AOC_SESSION").ok().expect("no auth provided"));
|
||||||
|
@ -132,7 +117,10 @@ async fn main() {
|
||||||
}),
|
}),
|
||||||
8 => Box::new(Day8 { input }),
|
8 => Box::new(Day8 { input }),
|
||||||
9 => Box::new(Day9 { input }),
|
9 => Box::new(Day9 { input }),
|
||||||
10 => Box::new(Day10 { input, parsed: vec![] }),
|
10 => Box::new(Day10 {
|
||||||
|
input,
|
||||||
|
parsed: vec![],
|
||||||
|
}),
|
||||||
_ => panic!("Invalid day #"),
|
_ => panic!("Invalid day #"),
|
||||||
};
|
};
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
|
@ -198,7 +186,10 @@ async fn main() {
|
||||||
}),
|
}),
|
||||||
8 => Box::new(Day8 { input }),
|
8 => Box::new(Day8 { input }),
|
||||||
9 => Box::new(Day9 { input }),
|
9 => Box::new(Day9 { input }),
|
||||||
10 => Box::new(Day10 { input, parsed: vec![] }),
|
10 => Box::new(Day10 {
|
||||||
|
input,
|
||||||
|
parsed: vec![],
|
||||||
|
}),
|
||||||
_ => panic!("Invalid day #"),
|
_ => panic!("Invalid day #"),
|
||||||
};
|
};
|
||||||
let mut timings = Vec::<Duration>::new();
|
let mut timings = Vec::<Duration>::new();
|
||||||
|
@ -240,19 +231,7 @@ async fn main() {
|
||||||
println!("\nAverage timing: {avg}{avg_units} ± {deviation}{deviation_units}");
|
println!("\nAverage timing: {avg}{avg_units} ± {deviation}{deviation_units}");
|
||||||
}
|
}
|
||||||
Subcommands::Input { day } => {
|
Subcommands::Input { day } => {
|
||||||
let response = client
|
println!("{}", fetcher::fetch_input(auth, day).await);
|
||||||
.get(format!("https://adventofcode.com/2023/day/{day}/input"))
|
|
||||||
.header("Cookie", format!("session={auth}"))
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.text()
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.trim_end()
|
|
||||||
.to_owned();
|
|
||||||
|
|
||||||
println!("{response}");
|
|
||||||
}
|
}
|
||||||
Subcommands::Example { day, part } => {
|
Subcommands::Example { day, part } => {
|
||||||
let (input, solution) = fetcher::fetch_example(auth, day, part).await;
|
let (input, solution) = fetcher::fetch_example(auth, day, part).await;
|
13
lib/Cargo.toml
Normal file
13
lib/Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
[package]
|
||||||
|
name = "advent"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
num-bigint = "0.4.4"
|
||||||
|
num-irrational = { version = "0.3.0", features = ["num-bigint"] }
|
||||||
|
num-rational = { version = "0.4.1", features = ["num-bigint"] }
|
||||||
|
regex = "1.10.2"
|
||||||
|
scraper = "0.18.1"
|
||||||
|
tokio = { version = "1.34.0", features = ["macros", "rt-multi-thread"] }
|
||||||
|
reqwest = "0.11.22"
|
|
@ -3,19 +3,33 @@ use crate::utils::Day;
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Day10 {
|
pub struct Day10 {
|
||||||
pub input: String,
|
pub input: String,
|
||||||
pub parsed: Vec<Vec<char>>
|
pub parsed: Vec<Vec<char>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Day10 {
|
impl Day10 {
|
||||||
/// Yes I copied this from wikipedia
|
/// Yes I copied this from wikipedia
|
||||||
/// https://en.wikipedia.org/wiki/Flood_fill#Stack-based_recursive_implementation_(four-way)
|
/// https://en.wikipedia.org/wiki/Flood_fill#Stack-based_recursive_implementation_(four-way)
|
||||||
pub fn flood_fill(&mut self, start: (usize, usize)) {
|
pub fn flood_fill(&mut self, start: (usize, usize)) {
|
||||||
if !(self.parsed[start.0][start.1] == '.' || self.parsed[start.0][start.1] == 'x') { return } // If node is not Inside return.
|
if !(self.parsed[start.0][start.1] == '.' || self.parsed[start.0][start.1] == 'x') {
|
||||||
if self.parsed[start.0][start.1] == '.' { self.parsed[start.0][start.1] = '+' } else { self.parsed[start.0][start.1] = '=' } // Set the node
|
return;
|
||||||
if start.0 != self.parsed.len() - 1 { self.flood_fill((start.0 + 1, start.1)) } // Perform Flood-fill one step to the south of node.
|
} // If node is not Inside return.
|
||||||
if start.0 != 0 { self.flood_fill((start.0 - 1, start.1)) } // Perform Flood-fill one step to the north of node
|
if self.parsed[start.0][start.1] == '.' {
|
||||||
if start.1 != 0 { self.flood_fill((start.0, start.1 - 1)) } // Perform Flood-fill one step to the west of node
|
self.parsed[start.0][start.1] = '+'
|
||||||
if start.1 != self.parsed[0].len() - 1 { self.flood_fill((start.0, start.1 + 1)) } // Perform Flood-fill one step to the east of node
|
} else {
|
||||||
|
self.parsed[start.0][start.1] = '='
|
||||||
|
} // Set the node
|
||||||
|
if start.0 != self.parsed.len() - 1 {
|
||||||
|
self.flood_fill((start.0 + 1, start.1))
|
||||||
|
} // Perform Flood-fill one step to the south of node.
|
||||||
|
if start.0 != 0 {
|
||||||
|
self.flood_fill((start.0 - 1, start.1))
|
||||||
|
} // Perform Flood-fill one step to the north of node
|
||||||
|
if start.1 != 0 {
|
||||||
|
self.flood_fill((start.0, start.1 - 1))
|
||||||
|
} // Perform Flood-fill one step to the west of node
|
||||||
|
if start.1 != self.parsed[0].len() - 1 {
|
||||||
|
self.flood_fill((start.0, start.1 + 1))
|
||||||
|
} // Perform Flood-fill one step to the east of node
|
||||||
return; // Return.
|
return; // Return.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +138,8 @@ impl Day for Day10 {
|
||||||
self.parsed = self.input.lines().map(|l| l.chars().collect()).collect();
|
self.parsed = self.input.lines().map(|l| l.chars().collect()).collect();
|
||||||
let line_len = self.parsed[0].len();
|
let line_len = self.parsed[0].len();
|
||||||
let height = self.parsed.len();
|
let height = self.parsed.len();
|
||||||
let mut pos = self.parsed
|
let mut pos = self
|
||||||
|
.parsed
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find_map(|(i, line)| line.iter().position(|&char| char == 'S').map(|v| (i, v)))
|
.find_map(|(i, line)| line.iter().position(|&char| char == 'S').map(|v| (i, v)))
|
||||||
|
@ -232,7 +247,11 @@ impl Day for Day10 {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let dots_before = self.parsed.iter().map(|line| line.iter().filter(|&&c| c == '.').count()).sum::<usize>();
|
let dots_before = self
|
||||||
|
.parsed
|
||||||
|
.iter()
|
||||||
|
.map(|line| line.iter().filter(|&&c| c == '.').count())
|
||||||
|
.sum::<usize>();
|
||||||
|
|
||||||
let s_tile = match start_connections {
|
let s_tile = match start_connections {
|
||||||
[1, 1] => '|',
|
[1, 1] => '|',
|
||||||
|
@ -258,7 +277,8 @@ impl Day for Day10 {
|
||||||
'x'
|
'x'
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}).collect();
|
})
|
||||||
|
.collect();
|
||||||
// Extend vertically
|
// Extend vertically
|
||||||
let new = line
|
let new = line
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -274,7 +294,7 @@ impl Day for Day10 {
|
||||||
self.parsed.push(new);
|
self.parsed.push(new);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.flood_fill((0,0));
|
self.flood_fill((0, 0));
|
||||||
|
|
||||||
// Dbg print lines
|
// Dbg print lines
|
||||||
// println!(
|
// println!(
|
||||||
|
@ -286,7 +306,11 @@ impl Day for Day10 {
|
||||||
// .join("\n")
|
// .join("\n")
|
||||||
// );
|
// );
|
||||||
|
|
||||||
let inner = dots_before - std::mem::take(&mut self.parsed).into_iter().map(|line| line.into_iter().filter(|&c| c == '+').count()).sum::<usize>();
|
let inner = dots_before
|
||||||
|
- std::mem::take(&mut self.parsed)
|
||||||
|
.into_iter()
|
||||||
|
.map(|line| line.into_iter().filter(|&c| c == '+').count())
|
||||||
|
.sum::<usize>();
|
||||||
|
|
||||||
inner.to_string()
|
inner.to_string()
|
||||||
}
|
}
|
|
@ -90,13 +90,3 @@ pub async fn fetch_example(auth: String, day: u8, part: u8) -> (String, Option<S
|
||||||
|
|
||||||
(input, solution)
|
(input, solution)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::fetcher;
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn fetches_large_data() {
|
|
||||||
fetcher::fetch_large(6, 1).await;
|
|
||||||
}
|
|
||||||
}
|
|
13
lib/src/lib.rs
Normal file
13
lib/src/lib.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
pub mod fetcher;
|
||||||
|
pub mod utils;
|
||||||
|
|
||||||
|
pub mod day1;
|
||||||
|
pub mod day10;
|
||||||
|
pub mod day2;
|
||||||
|
pub mod day3;
|
||||||
|
pub mod day4;
|
||||||
|
pub mod day5;
|
||||||
|
pub mod day6;
|
||||||
|
pub mod day7;
|
||||||
|
pub mod day8;
|
||||||
|
pub mod day9;
|
Loading…
Reference in a new issue