auto grab input & day 5
This commit is contained in:
parent
4f15848269
commit
b7a13cbc27
10 changed files with 171 additions and 50 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -1,9 +1,10 @@
|
||||||
# temporary files
|
# temporary files
|
||||||
/target
|
/target
|
||||||
|
/input
|
||||||
|
session.txt
|
||||||
|
|
||||||
# secrets
|
# secrets
|
||||||
.env
|
.env
|
||||||
|
|
||||||
# don't include inputs
|
# editors
|
||||||
/input
|
.vscode
|
||||||
session.txt
|
|
||||||
|
|
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -12,7 +12,7 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aoc-2022"
|
name = "aoc"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"eyes",
|
"eyes",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "aoc-2022"
|
name = "aoc"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
@ -8,6 +8,4 @@ regex = "1"
|
||||||
itertools = "0.10"
|
itertools = "0.10"
|
||||||
rayon = "1"
|
rayon = "1"
|
||||||
eyes = "1"
|
eyes = "1"
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
reqwest = { version = "0.11", features = ["blocking", "cookies"] }
|
reqwest = { version = "0.11", features = ["blocking", "cookies"] }
|
||||||
|
|
39
build.rs
39
build.rs
|
@ -1,39 +0,0 @@
|
||||||
use reqwest::{blocking::Client, cookie::Jar};
|
|
||||||
use std::{collections::HashMap, env, fs, path::PathBuf, sync::Arc};
|
|
||||||
|
|
||||||
const BASE_URL: &str = "https://adventofcode.com";
|
|
||||||
const YEAR: &str = "2022";
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
// get env and dotenv into hashmap
|
|
||||||
let file = fs::read_to_string(".env").unwrap_or(String::new());
|
|
||||||
let env = file
|
|
||||||
.lines()
|
|
||||||
.filter_map(|line| line.split_once('='))
|
|
||||||
.map(|(key, value)| (key.to_string(), value.to_string()))
|
|
||||||
.chain(env::vars())
|
|
||||||
.collect::<HashMap<_, _>>();
|
|
||||||
|
|
||||||
// create session cookie
|
|
||||||
let session = env
|
|
||||||
.get("SESSION")
|
|
||||||
.expect("SESSION environment variable not set, retrieve it from https://adventofcode.com");
|
|
||||||
let cookie = format!("session={session}");
|
|
||||||
|
|
||||||
// setup client
|
|
||||||
let jar = Arc::new(Jar::default());
|
|
||||||
jar.add_cookie_str(&cookie, &BASE_URL.parse().unwrap());
|
|
||||||
let client = Client::builder().cookie_provider(jar).build().unwrap();
|
|
||||||
|
|
||||||
// download until day fails
|
|
||||||
for day in 1..=25 {
|
|
||||||
let path = PathBuf::from(format!("input/day{day}.txt"));
|
|
||||||
if path.try_exists().is_err() {
|
|
||||||
let url = format!("{BASE_URL}/{YEAR}/day/{day}/input");
|
|
||||||
let Ok(res) = client.get(url).send() else {
|
|
||||||
break
|
|
||||||
};
|
|
||||||
fs::write(path, res.text().unwrap()).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let input = std::fs::read_to_string("input/day1.txt").unwrap();
|
let input = aoc::input!();
|
||||||
println!("part 1: {}", part1(&input));
|
println!("part 1: {}", part1(&input));
|
||||||
println!("part 1: {}", part2(&input));
|
println!("part 1: {}", part2(&input));
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
use eyes::parse;
|
use eyes::parse;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let input = std::fs::read_to_string("input/day2.txt").unwrap();
|
let input = aoc::input!();
|
||||||
println!("part 1: {}", part1(&input));
|
println!("part 1: {}", part1(&input));
|
||||||
println!("part 1: {}", part2(&input));
|
println!("part 1: {}", part2(&input));
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@ use itertools::Itertools;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let input = std::fs::read_to_string("input/day3.txt").unwrap();
|
let input = aoc::input!();
|
||||||
println!("part 1: {}", part1(&input));
|
println!("part 1: {}", part1(&input));
|
||||||
println!("part 1: {}", part2(&input));
|
println!("part 1: {}", part2(&input));
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
use eyes::parse;
|
use eyes::parse;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let input = std::fs::read_to_string("input/day4.txt").unwrap();
|
let input = aoc::input!();
|
||||||
println!("part 1: {}", part1(&input));
|
println!("part 1: {}", part1(&input));
|
||||||
println!("part 1: {}", part2(&input));
|
println!("part 1: {}", part2(&input));
|
||||||
}
|
}
|
109
src/bin/2022-5.rs
Normal file
109
src/bin/2022-5.rs
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
use eyes::parse;
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let input = aoc::input!();
|
||||||
|
println!("part 1: {}", part1(&input));
|
||||||
|
println!("part 1: {}", part2(&input));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1(input: &str) -> String {
|
||||||
|
// parsing challenge..... yay......
|
||||||
|
let (crates, instructions) = input.split_once("\n\n").unwrap();
|
||||||
|
let mut stacks = crates
|
||||||
|
.lines()
|
||||||
|
.rev()
|
||||||
|
.skip(1)
|
||||||
|
.map(|line| {
|
||||||
|
line.chars()
|
||||||
|
.chunks(4)
|
||||||
|
.into_iter()
|
||||||
|
.map(|mut cr| (cr.next() == Some('[')).then(|| cr.next().unwrap()))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.fold(vec![vec![]; 9], |mut stacks, crates| {
|
||||||
|
for (i, c) in crates.into_iter().enumerate() {
|
||||||
|
if let Some(c) = c {
|
||||||
|
stacks[i].push(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stacks
|
||||||
|
});
|
||||||
|
|
||||||
|
// perform instructions
|
||||||
|
instructions
|
||||||
|
.lines()
|
||||||
|
.map(|line| parse!(line, "move {} from {} to {}", usize, usize, usize))
|
||||||
|
.for_each(|(n, from, to)| {
|
||||||
|
(0..n).for_each(|_| {
|
||||||
|
if let Some(c) = stacks[from - 1].pop() {
|
||||||
|
stacks[to - 1].push(c)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// get message
|
||||||
|
stacks
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|mut stack| stack.pop())
|
||||||
|
.collect::<String>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2(input: &str) -> String {
|
||||||
|
let (crates, instructions) = input.split_once("\n\n").unwrap();
|
||||||
|
let mut stacks = crates
|
||||||
|
.lines()
|
||||||
|
.rev()
|
||||||
|
.skip(1)
|
||||||
|
.map(|line| {
|
||||||
|
line.chars()
|
||||||
|
.chunks(4)
|
||||||
|
.into_iter()
|
||||||
|
.map(|mut cr| (cr.next() == Some('[')).then(|| cr.next().unwrap()))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.fold(vec![vec![]; 9], |mut stacks, crates| {
|
||||||
|
for (i, c) in crates.into_iter().enumerate() {
|
||||||
|
if let Some(c) = c {
|
||||||
|
stacks[i].push(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stacks
|
||||||
|
});
|
||||||
|
|
||||||
|
// perform instructions
|
||||||
|
instructions
|
||||||
|
.lines()
|
||||||
|
.map(|line| parse!(line, "move {} from {} to {}", usize, usize, usize))
|
||||||
|
.for_each(|(n, from, to)| {
|
||||||
|
let len = stacks[from - 1].len();
|
||||||
|
let split = stacks[from - 1].split_off(len - n);
|
||||||
|
stacks[to - 1].extend(split);
|
||||||
|
});
|
||||||
|
|
||||||
|
// get message
|
||||||
|
stacks
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|mut stack| stack.pop())
|
||||||
|
.collect::<String>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn examples() {
|
||||||
|
let example = r#" [D]
|
||||||
|
[N] [C]
|
||||||
|
[Z] [M] [P]
|
||||||
|
1 2 3
|
||||||
|
|
||||||
|
move 1 from 2 to 1
|
||||||
|
move 3 from 1 to 3
|
||||||
|
move 2 from 2 to 1
|
||||||
|
move 1 from 1 to 2"#;
|
||||||
|
assert_eq!(part1(example), "CMZ".to_string());
|
||||||
|
assert_eq!(part2(example), "MCD".to_string());
|
||||||
|
}
|
||||||
|
}
|
52
src/lib.rs
52
src/lib.rs
|
@ -1 +1,53 @@
|
||||||
|
use reqwest::{blocking::Client, cookie::Jar};
|
||||||
|
use std::{env, error::Error, fs, path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
|
const BASE_URL: &str = "https://adventofcode.com";
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! input {
|
||||||
|
() => {{
|
||||||
|
let stem = std::path::Path::new(file!())
|
||||||
|
.file_stem()
|
||||||
|
.unwrap()
|
||||||
|
.to_string_lossy();
|
||||||
|
let (year, day) = stem.split_once('-').unwrap();
|
||||||
|
$crate::get_day(year, day).unwrap()
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_day(year: &str, day: &str) -> Result<String, Box<dyn Error>> {
|
||||||
|
let path = PathBuf::from(format!("input/{year}/day{day}.txt"));
|
||||||
|
fs::create_dir_all(path.parent().unwrap())?;
|
||||||
|
|
||||||
|
if let Ok(input) = fs::read_to_string(&path) {
|
||||||
|
Ok(input)
|
||||||
|
} else {
|
||||||
|
// get session token
|
||||||
|
let file = fs::read_to_string(".env").unwrap_or(String::new());
|
||||||
|
let session = file
|
||||||
|
.lines()
|
||||||
|
.filter_map(|line| line.split_once('='))
|
||||||
|
.map(|(key, value)| (key.to_string(), value.to_string()))
|
||||||
|
.chain(env::vars())
|
||||||
|
.find_map(|(k, v)| (k == "SESSION").then_some(v))
|
||||||
|
.ok_or(
|
||||||
|
"SESSION environment variable not set, retrieve it from https://adventofcode.com",
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// create session cookie
|
||||||
|
let cookie = format!("session={session}");
|
||||||
|
|
||||||
|
// setup client
|
||||||
|
let jar = Arc::new(Jar::default());
|
||||||
|
jar.add_cookie_str(&cookie, &BASE_URL.parse()?);
|
||||||
|
let client = Client::builder().cookie_provider(jar).build()?;
|
||||||
|
|
||||||
|
// download until day fails
|
||||||
|
let url = format!("{BASE_URL}/{year}/day/{day}/input");
|
||||||
|
let text = client.get(url).send()?.text()?;
|
||||||
|
fs::create_dir_all(path.parent().unwrap())?;
|
||||||
|
fs::write(path, &text)?;
|
||||||
|
|
||||||
|
Ok(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue