1
0
Files
AdventOfCode2025/src/solvers.rs
T
2026-02-10 10:41:56 +01:00

99 lines
2.5 KiB
Rust

use sanitise_file_name;
use std::fs::File;
use std::io;
use std::io::BufRead;
use std::path;
use std::path::Path;
pub mod cafeteria;
pub mod gift_shop;
pub mod laboratories;
pub mod lobby;
pub mod movie_theater;
pub mod playground;
pub mod printing_department;
pub mod secret_entrance;
pub mod trash_compactor;
pub trait Solver {
const PUZZLE_INDEX: u8;
const PUZZLE_NAME: &'static str;
fn puzzle_index(&self) -> u8 {
Self::PUZZLE_INDEX
}
fn puzzle_name(&self) -> &'static str {
Self::PUZZLE_NAME
}
fn process_data<R: BufRead>(&self, reader: R) -> (u64, u64);
}
// The "../../data" and "../../../data" paths are useful for running the binary from
// "target/release/" directory with "data/" directory in package root or parent directory.
pub const DATA_PATHS: &'static [&'static str] =
&["./data", "../data", "../../data", "../../../data"];
pub fn run<S: Solver>(solver: S) {
println!(
"--- Day {}: {} ---",
solver.puzzle_index(),
solver.puzzle_name()
);
match run_solver(solver, &DATA_PATHS) {
Ok(result) => print_result(result),
Err(error) => eprintln!("{}", error),
}
}
pub fn run_solver<S: Solver>(solver: S, paths: &[&str]) -> Result<(u64, u64), String> {
let reader = read_data_file(input_filename(solver.puzzle_name()), paths)?;
Ok(solver.process_data(reader))
}
fn input_filename(puzzle_name: &str) -> String {
sanitise_file_name::sanitise(puzzle_name)
.to_lowercase()
.replace(" ", "_")
+ ".txt"
}
fn print_result(result: (u64, u64)) {
println!("Part 1: {:?}\nPart 2: {:?}\n", result.0, result.1);
}
fn read_data_file<T>(filename: String, search_paths: &[T]) -> Result<io::BufReader<File>, String>
where
T: AsRef<Path>,
{
for path in search_paths {
if let Ok(reader) = read_file(path.as_ref().join(&filename)) {
return Ok(reader);
}
}
let message = search_paths
.iter()
.filter_map(|p| {
path::absolute(p.as_ref().join(&filename))
.ok()
.and_then(|p| Some(p.display().to_string()))
})
.collect::<Vec<_>>()
.join("\n");
Err(format!(
"Cannot open puzzle input file, searched these paths:\n{}",
message
))
}
// This code is taken from https://doc.rust-lang.org/stable/rust-by-example/std_misc/file/read_lines.html
fn read_file<T>(filename: T) -> io::Result<io::BufReader<File>>
where
T: AsRef<Path>,
{
let file = File::open(filename)?;
Ok(io::BufReader::new(file))
}