Add login checks and example solving
This commit is contained in:
parent
7bbd5ff22c
commit
161b341400
3 changed files with 67 additions and 57 deletions
|
@ -28,21 +28,18 @@ impl Day for Day5 {
|
||||||
.map(|(name, list)| {
|
.map(|(name, list)| {
|
||||||
(
|
(
|
||||||
name.split_once(' ').unwrap().0.split_once("-to-").unwrap(),
|
name.split_once(' ').unwrap().0.split_once("-to-").unwrap(),
|
||||||
list.into_iter().map(|line| {
|
list.into_iter()
|
||||||
let nums = line.split_whitespace()
|
.map(|line| {
|
||||||
.map(|n| n.parse::<usize>().unwrap())
|
let nums = line
|
||||||
.collect::<Vec<_>>();
|
.split_whitespace()
|
||||||
(nums[0], nums[1], nums[2])
|
.map(|n| n.parse::<usize>().unwrap())
|
||||||
}).collect::<Vec<_>>(),
|
.collect::<Vec<_>>();
|
||||||
|
(nums[0], nums[1], nums[2])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.map(|((from, to), mappings)| (
|
.map(|((from, to), mappings)| (from, (to, mappings)))
|
||||||
from,
|
|
||||||
(
|
|
||||||
to,
|
|
||||||
mappings
|
|
||||||
)
|
|
||||||
))
|
|
||||||
.collect::<HashMap<&str, (&str, Vec<(usize, usize, usize)>)>>();
|
.collect::<HashMap<&str, (&str, Vec<(usize, usize, usize)>)>>();
|
||||||
|
|
||||||
let mut locations = Vec::<usize>::new();
|
let mut locations = Vec::<usize>::new();
|
||||||
|
@ -90,29 +87,24 @@ impl Day for Day5 {
|
||||||
.split_whitespace()
|
.split_whitespace()
|
||||||
.map(|s| s.parse::<usize>().unwrap())
|
.map(|s| s.parse::<usize>().unwrap())
|
||||||
.collect::<Vec<usize>>();
|
.collect::<Vec<usize>>();
|
||||||
let seeds = seeds
|
let seeds = seeds.as_slice().chunks(2);
|
||||||
.as_slice()
|
|
||||||
.chunks(2);
|
|
||||||
|
|
||||||
let groups = groups
|
let groups = groups
|
||||||
.map(|(name, list)| {
|
.map(|(name, list)| {
|
||||||
(
|
(
|
||||||
name.split_once(' ').unwrap().0.split_once("-to-").unwrap(),
|
name.split_once(' ').unwrap().0.split_once("-to-").unwrap(),
|
||||||
list.into_iter().map(|line| {
|
list.into_iter()
|
||||||
let nums = line.split_whitespace()
|
.map(|line| {
|
||||||
.map(|n| n.parse::<usize>().unwrap())
|
let nums = line
|
||||||
.collect::<Vec<_>>();
|
.split_whitespace()
|
||||||
(nums[0], nums[1], nums[2])
|
.map(|n| n.parse::<usize>().unwrap())
|
||||||
}).collect::<Vec<_>>(),
|
.collect::<Vec<_>>();
|
||||||
|
(nums[0], nums[1], nums[2])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.map(|((from, to), mappings)| (
|
.map(|((from, to), mappings)| (from, (to, mappings)))
|
||||||
from,
|
|
||||||
(
|
|
||||||
to,
|
|
||||||
mappings
|
|
||||||
)
|
|
||||||
))
|
|
||||||
.collect::<HashMap<&str, (&str, Vec<(usize, usize, usize)>)>>();
|
.collect::<HashMap<&str, (&str, Vec<(usize, usize, usize)>)>>();
|
||||||
|
|
||||||
let mut location = 100000000usize;
|
let mut location = 100000000usize;
|
||||||
|
@ -122,13 +114,20 @@ impl Day for Day5 {
|
||||||
let (initial, range) = (chunk[0], chunk[1]);
|
let (initial, range) = (chunk[0], chunk[1]);
|
||||||
for (j, seed) in (initial..(initial + range)).enumerate() {
|
for (j, seed) in (initial..(initial + range)).enumerate() {
|
||||||
if j % 1000 == 0 {
|
if j % 1000 == 0 {
|
||||||
println!("Chunk {}/{}, Seed {}/{} ({:.2}%)", i, seedslen, j, range, j as f64 / range as f64 * 100.0);
|
println!(
|
||||||
|
"Chunk {}/{}, Seed {}/{} ({:.2}%)",
|
||||||
|
i,
|
||||||
|
seedslen,
|
||||||
|
j,
|
||||||
|
range,
|
||||||
|
j as f64 / range as f64 * 100.0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let (mut category, mut value) = ("seed", seed);
|
let (mut category, mut value) = ("seed", seed);
|
||||||
while category != "location" {
|
while category != "location" {
|
||||||
let (new_category, mappings) = groups.get(category).unwrap();
|
let (new_category, mappings) = groups.get(category).unwrap();
|
||||||
category = new_category;
|
category = new_category;
|
||||||
|
|
||||||
for (destination_start, source_start, length) in mappings {
|
for (destination_start, source_start, length) in mappings {
|
||||||
if (source_start..&(source_start + length)).contains(&&value) {
|
if (source_start..&(source_start + length)).contains(&&value) {
|
||||||
let delta = *source_start as isize - *destination_start as isize;
|
let delta = *source_start as isize - *destination_start as isize;
|
||||||
|
@ -137,8 +136,10 @@ impl Day for Day5 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if location > value { location = value }
|
if location > value {
|
||||||
|
location = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +147,6 @@ impl Day for Day5 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{day5::Day5, utils::Day};
|
use crate::{day5::Day5, utils::Day};
|
||||||
|
@ -186,7 +186,8 @@ temperature-to-humidity map:
|
||||||
|
|
||||||
humidity-to-location map:
|
humidity-to-location map:
|
||||||
60 56 37
|
60 56 37
|
||||||
56 93 4"#.to_string(),
|
56 93 4"#
|
||||||
|
.to_string(),
|
||||||
}
|
}
|
||||||
.solve(1));
|
.solve(1));
|
||||||
}
|
}
|
||||||
|
@ -226,8 +227,9 @@ temperature-to-humidity map:
|
||||||
|
|
||||||
humidity-to-location map:
|
humidity-to-location map:
|
||||||
60 56 37
|
60 56 37
|
||||||
56 93 4"#.to_string(),
|
56 93 4"#
|
||||||
|
.to_string(),
|
||||||
}
|
}
|
||||||
.solve(2));
|
.solve(2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use scraper::{Html, Selector};
|
use scraper::{Html, Selector};
|
||||||
|
|
||||||
pub async fn fetch_input(auth: String, day: u8) -> String {
|
pub async fn fetch_input(auth: String, day: u8) -> String {
|
||||||
reqwest::Client::new()
|
let input = reqwest::Client::new()
|
||||||
.get(format!("https://adventofcode.com/2023/day/{day}/input"))
|
.get(format!("https://adventofcode.com/2023/day/{day}/input"))
|
||||||
.header("Cookie", format!("session={auth}"))
|
.header("Cookie", format!("session={auth}"))
|
||||||
.send()
|
.send()
|
||||||
|
@ -11,7 +11,12 @@ pub async fn fetch_input(auth: String, day: u8) -> String {
|
||||||
.await
|
.await
|
||||||
.expect("Unable to parse string from input response")
|
.expect("Unable to parse string from input response")
|
||||||
.trim_end()
|
.trim_end()
|
||||||
.to_owned()
|
.to_owned();
|
||||||
|
if input != "Puzzle inputs differ by user. Please log in to get your puzzle input." {
|
||||||
|
input
|
||||||
|
} else {
|
||||||
|
panic!("Invalid auth")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn fetch_example(auth: String, day: u8, part: u8) -> (String, String) {
|
pub async fn fetch_example(auth: String, day: u8, part: u8) -> (String, String) {
|
||||||
|
@ -44,7 +49,7 @@ pub async fn fetch_example(auth: String, day: u8, part: u8) -> (String, String)
|
||||||
let solution = dom
|
let solution = dom
|
||||||
.select(&solution_selector)
|
.select(&solution_selector)
|
||||||
.last()
|
.last()
|
||||||
.unwrap()
|
.expect("Unable to find example solution for part, is auth correct?")
|
||||||
.inner_html()
|
.inner_html()
|
||||||
.trim_end()
|
.trim_end()
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
37
src/main.rs
37
src/main.rs
|
@ -35,6 +35,9 @@ enum Subcommands {
|
||||||
day: u8,
|
day: u8,
|
||||||
/// The part to solve for
|
/// The part to solve for
|
||||||
part: u8,
|
part: u8,
|
||||||
|
/// If used, then the example input will be solved and checked rather than the real one
|
||||||
|
#[arg(short, long)]
|
||||||
|
example: bool,
|
||||||
},
|
},
|
||||||
/// Runs solution N amount of times, averaging speed
|
/// Runs solution N amount of times, averaging speed
|
||||||
Benchmark {
|
Benchmark {
|
||||||
|
@ -67,32 +70,28 @@ async fn main() {
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
|
|
||||||
match cli.subcommand {
|
match cli.subcommand {
|
||||||
Subcommands::Solve { day, part } => {
|
Subcommands::Solve { day, part, example } => {
|
||||||
let response = client
|
let (input, solution) = match example {
|
||||||
.get(format!("https://adventofcode.com/2023/day/{day}/input"))
|
false => (fetcher::fetch_input(cli.auth, day).await, None),
|
||||||
.header("Cookie", format!("session={auth}", auth = cli.auth))
|
true => {
|
||||||
.send()
|
let example = fetcher::fetch_example(cli.auth, day, part).await;
|
||||||
.await
|
(example.0, Some(example.1))
|
||||||
.unwrap()
|
}
|
||||||
.text()
|
};
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.trim_end()
|
|
||||||
.to_owned();
|
|
||||||
|
|
||||||
let mut day: Box<dyn Day> = match day {
|
let mut day: Box<dyn Day> = match day {
|
||||||
1 => Box::new(Day1 { input: response }),
|
1 => Box::new(Day1 { input }),
|
||||||
2 => Box::new(Day2 {
|
2 => Box::new(Day2 {
|
||||||
input: response,
|
input,
|
||||||
games: vec![],
|
games: vec![],
|
||||||
}),
|
}),
|
||||||
3 => Box::new(Day3 { input: response }),
|
3 => Box::new(Day3 { input }),
|
||||||
4 => Box::new(Day4 {
|
4 => Box::new(Day4 {
|
||||||
input: response,
|
input,
|
||||||
acc: 0usize,
|
acc: 0usize,
|
||||||
cards: HashMap::new(),
|
cards: HashMap::new(),
|
||||||
}),
|
}),
|
||||||
5 => Box::new(Day5 { input: response }),
|
5 => Box::new(Day5 { input }),
|
||||||
_ => panic!("Invalid day #"),
|
_ => panic!("Invalid day #"),
|
||||||
};
|
};
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
|
@ -100,6 +99,10 @@ async fn main() {
|
||||||
let end = std::time::Instant::now();
|
let end = std::time::Instant::now();
|
||||||
println!("Solution: {result}");
|
println!("Solution: {result}");
|
||||||
|
|
||||||
|
if let Some(solution) = solution {
|
||||||
|
println!("Correct solution: {solution}")
|
||||||
|
}
|
||||||
|
|
||||||
let timing = (end - start).as_nanos();
|
let timing = (end - start).as_nanos();
|
||||||
let (timing, timing_units) = if timing >= 1000000000 {
|
let (timing, timing_units) = if timing >= 1000000000 {
|
||||||
(timing as f64 / 1000000000.0, "s")
|
(timing as f64 / 1000000000.0, "s")
|
||||||
|
|
Loading…
Reference in a new issue