Let’s do this thing!
I’m going to try Rust this time, since it’s 1) awesome 2) fast and 3) crazy. :D
Let’s see how it goes!
If you’d like to see the full form of any particular solution, you can do so on GitHub (including previous years and possibly some I haven’t written up yet): jpverkamp/advent-of-code
Here’s a full list of all of the posts:
Posts in Advent of Code 2022:
- Advent of Code 2022
- AoC 2022 Day 1: Calorinator
- AoC 2022 Day 2: Roshamboinator
- AoC 2022 Day 3: Rucksackinator
- AoC 2022 Day 4: Overlapinator
- AoC 2022 Day 5: Stackinator
- AoC 2022 Day 6: Ring Buffinator
- AoC 2022 Day 7: Recursive Fileinator
- AoC 2022 Day 8: Treetopinator
- AoC 2022 Day 9: Ropeinator
- AoC 2022 Day 10: Interpretator
- AoC 2022 Day 11: Monkeyinator
- AoC 2022 Day 12: Climbiantor
- AoC 2022 Day 13: List Parsinator
- AoC 2022 Day 14: Sandinator
- AoC 2022 Day 15: Beaconator
- AoC 2022 Day 16: Pressurinator
- AoC 2022 Day 17: Tetrisinator
- AoC 2022 Day 18: Lavinator
- AoC 2022 Day 19: Blueprintinator
- AoC 2022 Day 20: Deencryptinator
- AoC 2022 Day 21: Yellinator
- AoC 2022 Day 22: Wonderator
- AoC 2022 Day 23: Elf Scattinator
- AoC 2022 Day 24: Blizzinator
- AoC 2022 Day 25: Snafuinator
So far, I have a few helper functions that all solutions can use:
Reading a file of input into a vector of lines
pub fn read_lines(filename: &Path) -> Vec<String> {
let file = File::open(filename).expect("no such file");
let buf = BufReader::new(file);
buf.lines()
.map(|l| l.expect("Could not parse line"))
.collect()
}
Running a function as ‘main’
type FnPart = fn(&Path) -> String;
pub fn aoc_main(part1: FnPart, part2: FnPart) {
let part = env::args()
.nth(1).expect("first arg should be part (1 or 2)")
.parse::<u32>().expect("part must be a non-negative integer");
if part != 1 && part != 2 {
}
let filename = env::args().nth(2).expect("second arg should be input filename");
let path = Path::new(&filename);
if !path.exists() {
panic!("{:?} does not exist", filename);
}
let now = Instant::now();
let result = match part {
1 => part1(path),
2 => part2(path),
_ => panic!("part must be 1 or 2")
};
let elapsed = now.elapsed();
println!("{}", result);
println!("took {:?}", elapsed);
}
This will allow me to have bin/day**.rs
with a main
function:
fn main() {
aoc_main(part1, part2);
}
I may macro that. We’ll see.
Running test cases
Given the day (or input filename), function, and expected answer, we can automatically write the body of tests:
pub fn aoc_test(day: &str, f: FnPart, expected: &str) {
let mut filename = String::from("data/");
filename.push_str(&day);
filename.push_str(".txt");
let actual = f(Path::new(filename.as_str()));
assert_eq!(expected, actual);
}
Likewise, the tests become:
#[cfg(test)]
mod tests {
use aoc::aoc_test;
use crate::{part1, part2};
#[test]
fn test1() { aoc_test("01", part1, "70369") }
#[test]
fn test2() { aoc_test("01", part2, "203002") }
}
Previous solutions
And here are my previous year’s solutions: