1
0

Refactor Solver trait to streamline usage

This commit is contained in:
Stefan Müller
2025-12-08 14:38:02 +01:00
parent ad64b05db7
commit 496293b33b
5 changed files with 63 additions and 123 deletions
+25 -24
View File
@@ -8,52 +8,53 @@ pub mod printing_department;
pub mod trash_compactor;
pub trait Solver {
fn get_puzzle_index(&self) -> u8;
fn get_puzzle_name(&self) -> &str;
fn get_input_filename(&self) -> &str;
fn get_part1(&self) -> u64;
fn get_part2(&self) -> u64;
fn process_data(&mut self, lines: io::Lines<io::BufReader<File>>);
const PUZZLE_INDEX: u8;
const PUZZLE_NAME: &'static str;
// TODO: Replace constant input filename by a conversion from the puzzle name in the runner.
const INPUT_FILENAME: &'static str;
fn puzzle_index(&self) -> u8 { Self::PUZZLE_INDEX }
fn puzzle_name(&self) -> &'static str { Self::PUZZLE_NAME }
fn input_filename(&self) -> &'static str { Self::INPUT_FILENAME }
fn process_data<R: BufRead>(&self, reader: R) -> (u64, u64);
}
pub fn run(mut solver: Box<dyn Solver>) {
pub fn run<S: Solver>(solver: S) {
println!(
"--- Day {}: {} ---",
solver.get_puzzle_index(),
solver.get_puzzle_name()
solver.puzzle_index(),
solver.puzzle_name()
);
// TODO: Convert to constant and add "example" paths.
// The "../../data" and "../../../data" paths are useful for running the binary from
// "target/release/" directory with "data/" directory in package root or parent directory.
let paths = vec!["./data", "../data", "../../data", "../../../data"];
match read_data_file(solver.get_input_filename(), &paths) {
Ok(lines) => {
solver.process_data(lines);
print_result(solver);
match read_data_file(solver.input_filename(), &paths) {
Ok(reader) => {
let result = solver.process_data(reader);
print_result(result);
}
Err(error) => eprintln!("{}", error),
};
}
fn print_result(solver: Box<dyn Solver>) {
println!(
"Part 1: {:?}\nPart 2: {:?}\n",
solver.get_part1(),
solver.get_part2()
);
fn print_result(result: (u64, u64)) {
println!("Part 1: {:?}\nPart 2: {:?}\n", result.0, result.1);
}
fn read_data_file<T>(
filename: T,
search_paths: &Vec<T>,
) -> Result<io::Lines<io::BufReader<File>>, String>
) -> Result<io::BufReader<File>, String>
where
T: AsRef<Path>,
{
for path in search_paths {
if let Ok(lines) = read_lines(path.as_ref().join(&filename)) {
return Ok(lines);
if let Ok(reader) = read_file(path.as_ref().join(&filename)) {
return Ok(reader);
}
}
@@ -69,10 +70,10 @@ where
}
// This code is taken from https://doc.rust-lang.org/stable/rust-by-example/std_misc/file/read_lines.html
fn read_lines<T>(filename: T) -> io::Result<io::Lines<io::BufReader<File>>>
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).lines())
Ok(io::BufReader::new(file))
}