Add login checks and example solving

This commit is contained in:
Tyler Beckman 2023-12-05 00:03:50 -07:00
parent 7bbd5ff22c
commit 161b341400
Signed by: Ty
GPG key ID: 2813440C772555A4
3 changed files with 67 additions and 57 deletions

View file

@ -28,21 +28,18 @@ impl Day for Day5 {
.map(|(name, list)| {
(
name.split_once(' ').unwrap().0.split_once("-to-").unwrap(),
list.into_iter().map(|line| {
let nums = line.split_whitespace()
.map(|n| n.parse::<usize>().unwrap())
.collect::<Vec<_>>();
(nums[0], nums[1], nums[2])
}).collect::<Vec<_>>(),
list.into_iter()
.map(|line| {
let nums = line
.split_whitespace()
.map(|n| n.parse::<usize>().unwrap())
.collect::<Vec<_>>();
(nums[0], nums[1], nums[2])
})
.collect::<Vec<_>>(),
)
})
.map(|((from, to), mappings)| (
from,
(
to,
mappings
)
))
.map(|((from, to), mappings)| (from, (to, mappings)))
.collect::<HashMap<&str, (&str, Vec<(usize, usize, usize)>)>>();
let mut locations = Vec::<usize>::new();
@ -90,29 +87,24 @@ impl Day for Day5 {
.split_whitespace()
.map(|s| s.parse::<usize>().unwrap())
.collect::<Vec<usize>>();
let seeds = seeds
.as_slice()
.chunks(2);
let seeds = seeds.as_slice().chunks(2);
let groups = groups
.map(|(name, list)| {
(
name.split_once(' ').unwrap().0.split_once("-to-").unwrap(),
list.into_iter().map(|line| {
let nums = line.split_whitespace()
.map(|n| n.parse::<usize>().unwrap())
.collect::<Vec<_>>();
(nums[0], nums[1], nums[2])
}).collect::<Vec<_>>(),
list.into_iter()
.map(|line| {
let nums = line
.split_whitespace()
.map(|n| n.parse::<usize>().unwrap())
.collect::<Vec<_>>();
(nums[0], nums[1], nums[2])
})
.collect::<Vec<_>>(),
)
})
.map(|((from, to), mappings)| (
from,
(
to,
mappings
)
))
.map(|((from, to), mappings)| (from, (to, mappings)))
.collect::<HashMap<&str, (&str, Vec<(usize, usize, usize)>)>>();
let mut location = 100000000usize;
@ -122,13 +114,20 @@ impl Day for Day5 {
let (initial, range) = (chunk[0], chunk[1]);
for (j, seed) in (initial..(initial + range)).enumerate() {
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);
while category != "location" {
let (new_category, mappings) = groups.get(category).unwrap();
category = new_category;
for (destination_start, source_start, length) in mappings {
if (source_start..&(source_start + length)).contains(&&value) {
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)]
mod tests {
use crate::{day5::Day5, utils::Day};
@ -186,7 +186,8 @@ temperature-to-humidity map:
humidity-to-location map:
60 56 37
56 93 4"#.to_string(),
56 93 4"#
.to_string(),
}
.solve(1));
}
@ -226,8 +227,9 @@ temperature-to-humidity map:
humidity-to-location map:
60 56 37
56 93 4"#.to_string(),
56 93 4"#
.to_string(),
}
.solve(2));
}
}
}

View file

@ -1,7 +1,7 @@
use scraper::{Html, Selector};
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"))
.header("Cookie", format!("session={auth}"))
.send()
@ -11,7 +11,12 @@ pub async fn fetch_input(auth: String, day: u8) -> String {
.await
.expect("Unable to parse string from input response")
.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) {
@ -44,7 +49,7 @@ pub async fn fetch_example(auth: String, day: u8, part: u8) -> (String, String)
let solution = dom
.select(&solution_selector)
.last()
.unwrap()
.expect("Unable to find example solution for part, is auth correct?")
.inner_html()
.trim_end()
.to_string();

View file

@ -35,6 +35,9 @@ enum Subcommands {
day: u8,
/// The part to solve for
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
Benchmark {
@ -67,32 +70,28 @@ async fn main() {
let client = reqwest::Client::new();
match cli.subcommand {
Subcommands::Solve { day, part } => {
let response = client
.get(format!("https://adventofcode.com/2023/day/{day}/input"))
.header("Cookie", format!("session={auth}", auth = cli.auth))
.send()
.await
.unwrap()
.text()
.await
.unwrap()
.trim_end()
.to_owned();
Subcommands::Solve { day, part, example } => {
let (input, solution) = match example {
false => (fetcher::fetch_input(cli.auth, day).await, None),
true => {
let example = fetcher::fetch_example(cli.auth, day, part).await;
(example.0, Some(example.1))
}
};
let mut day: Box<dyn Day> = match day {
1 => Box::new(Day1 { input: response }),
1 => Box::new(Day1 { input }),
2 => Box::new(Day2 {
input: response,
input,
games: vec![],
}),
3 => Box::new(Day3 { input: response }),
3 => Box::new(Day3 { input }),
4 => Box::new(Day4 {
input: response,
input,
acc: 0usize,
cards: HashMap::new(),
}),
5 => Box::new(Day5 { input: response }),
5 => Box::new(Day5 { input }),
_ => panic!("Invalid day #"),
};
let start = std::time::Instant::now();
@ -100,6 +99,10 @@ async fn main() {
let end = std::time::Instant::now();
println!("Solution: {result}");
if let Some(solution) = solution {
println!("Correct solution: {solution}")
}
let timing = (end - start).as_nanos();
let (timing, timing_units) = if timing >= 1000000000 {
(timing as f64 / 1000000000.0, "s")