Use strings for output types in Rust

This is a compromise that gets us most of the way towards what we have with the heterogeneous list in Haskell, but without any complex abstractions.
This commit is contained in:
George Thomas 2025-12-16 17:38:53 +00:00
parent 415055dcc2
commit 437c2f290d
4 changed files with 12 additions and 11 deletions

View File

@ -3,7 +3,6 @@ mod puzzles;
use crate::puzzle::Puzzle; use crate::puzzle::Puzzle;
use puzzles::day1; use puzzles::day1;
use puzzles::day2; use puzzles::day2;
use std::fmt::Display;
use std::fs; use std::fs;
const PUZZLES: [&dyn SomePuzzle; 2] = [&day1::PUZZLE, &day2::PUZZLE]; const PUZZLES: [&dyn SomePuzzle; 2] = [&day1::PUZZLE, &day2::PUZZLE];
@ -39,12 +38,12 @@ pub trait SomePuzzle {
fn number(&self) -> u32; fn number(&self) -> u32;
fn run(&self, input: &str) -> Vec<String>; fn run(&self, input: &str) -> Vec<String>;
} }
impl<Input, Output: Display, const N: usize> SomePuzzle for Puzzle<Input, Output, { N }> { impl<Input, const N: usize> SomePuzzle for Puzzle<Input, { N }> {
fn number(&self) -> u32 { fn number(&self) -> u32 {
self.number self.number
} }
fn run(&self, s: &str) -> Vec<String> { fn run(&self, s: &str) -> Vec<String> {
let input = (self.parser)(s); let input = (self.parser)(s);
self.parts.map(|p| p(&input).to_string() + "\n").to_vec() self.parts.map(|p| p(&input) + "\n").to_vec()
} }
} }

View File

@ -1,5 +1,5 @@
pub struct Puzzle<Input, Output, const N: usize> { pub struct Puzzle<Input, const N: usize> {
pub number: u32, pub number: u32,
pub parser: fn(&str) -> Input, pub parser: fn(&str) -> Input,
pub parts: [fn(&Input) -> Output; N], pub parts: [fn(&Input) -> String; N],
} }

View File

@ -9,7 +9,7 @@ use nom::{
sequence::{pair, terminated}, sequence::{pair, terminated},
}; };
pub const PUZZLE: Puzzle<Vec<(Direction, i32)>, i32, 2> = Puzzle { pub const PUZZLE: Puzzle<Vec<(Direction, i32)>, 2> = Puzzle {
number: 1, number: 1,
parser: |input| { parser: |input| {
terminated( terminated(
@ -43,7 +43,7 @@ pub const PUZZLE: Puzzle<Vec<(Direction, i32)>, i32, 2> = Puzzle {
} }
p = p1; p = p1;
} }
r r.to_string()
}, },
|instructions| { |instructions| {
let mut p = 50; let mut p = 50;
@ -65,7 +65,7 @@ pub const PUZZLE: Puzzle<Vec<(Direction, i32)>, i32, 2> = Puzzle {
r += c1; r += c1;
p = p1; p = p1;
} }
r r.to_string()
}, },
], ],
}; };

View File

@ -8,7 +8,7 @@ use nom::{
sequence::{separated_pair, terminated}, sequence::{separated_pair, terminated},
}; };
pub const PUZZLE: Puzzle<Vec<(usize, usize)>, usize, 2> = Puzzle { pub const PUZZLE: Puzzle<Vec<(usize, usize)>, 2> = Puzzle {
number: 2, number: 2,
parser: |input| { parser: |input| {
terminated( terminated(
@ -32,7 +32,8 @@ pub const PUZZLE: Puzzle<Vec<(usize, usize)>, usize, 2> = Puzzle {
.flat_map(|(l, u)| { .flat_map(|(l, u)| {
(*l..(u + 1)).flat_map(|n| if is_repetition_2(n) { Some(n) } else { None }) (*l..(u + 1)).flat_map(|n| if is_repetition_2(n) { Some(n) } else { None })
}) })
.sum() .sum::<usize>()
.to_string()
}, },
|input| { |input| {
input input
@ -40,7 +41,8 @@ pub const PUZZLE: Puzzle<Vec<(usize, usize)>, usize, 2> = Puzzle {
.flat_map(|(l, u)| { .flat_map(|(l, u)| {
(*l..(u + 1)).flat_map(|n| if is_repetition_n(n) { Some(n) } else { None }) (*l..(u + 1)).flat_map(|n| if is_repetition_n(n) { Some(n) } else { None })
}) })
.sum() .sum::<usize>()
.to_string()
}, },
], ],
}; };