Compare commits
No commits in common. "be0bfd0545231b718db3a74a169035b8d47be95e" and "86e2ff6c62e4dbcf3ba16cced774870fb94bc0da" have entirely different histories.
be0bfd0545
...
86e2ff6c62
@ -342,8 +342,8 @@ displayTestResultsConsole terminalWidth testResult =
|
||||
<> displayLogs
|
||||
<> setColour Vivid Red
|
||||
<> indentAllLines indent case e of
|
||||
ExceptionFailure ex -> "Exception: " <> T.show ex
|
||||
AssertionFailure t -> "Assertion failed: " <> T.stripEnd t
|
||||
ExceptionFailure ex -> T.show ex
|
||||
AssertionFailure t -> T.stripEnd t
|
||||
GoldenMissing -> "Golden file missing"
|
||||
GoldenFailure{expected, actual} ->
|
||||
"Expected:\n" <> T.stripEnd expected <> "\nActual:\n" <> T.stripEnd actual
|
||||
@ -433,10 +433,8 @@ runTests opts r0 (TestTree name tc ts) =
|
||||
pure $ Left e
|
||||
Right (Left e) ->
|
||||
pure $ Left $ ExceptionFailure e
|
||||
Right (Right (r, dt)) -> do
|
||||
rs <- for ts $ runTests opts r
|
||||
let childTimes = sum $ map (either (const 0) fst . (.result)) rs
|
||||
pure $ Right (dt + childTimes, rs)
|
||||
Right (Right (r, dt)) ->
|
||||
Right . (dt,) <$> for ts (runTests opts r)
|
||||
where
|
||||
runTest = \case
|
||||
TestCase f -> timed (liftIO . evaluate . DeepSeq.force) $ f r0
|
||||
|
||||
20
rust/main.rs
20
rust/main.rs
@ -7,18 +7,16 @@ use puzzles::day3;
|
||||
use puzzles::day4;
|
||||
use puzzles::day5;
|
||||
use puzzles::day6;
|
||||
use puzzles::day7;
|
||||
use std::fs;
|
||||
use std::time::Instant;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
const PUZZLES: [&dyn SomePuzzle; 7] = [
|
||||
const PUZZLES: [&dyn SomePuzzle; 6] = [
|
||||
&day1::PUZZLE,
|
||||
&day2::PUZZLE,
|
||||
&day3::PUZZLE,
|
||||
&day4::PUZZLE,
|
||||
&day5::PUZZLE,
|
||||
&day6::PUZZLE,
|
||||
&day7::PUZZLE,
|
||||
];
|
||||
|
||||
fn main() {
|
||||
@ -29,7 +27,7 @@ fn main() {
|
||||
println!(" {}", puzzle.number());
|
||||
let input = fs::read_to_string(format!("../inputs/{}/{}", t, puzzle.number()))
|
||||
.expect("no input file");
|
||||
puzzle.with_parts(*is_real_data, &input, &|n, run| {
|
||||
puzzle.with_parts(&input, &|n, run| {
|
||||
let expected =
|
||||
fs::read_to_string(format!("../outputs/{}/{}/{}", t, puzzle.number(), n))
|
||||
.expect("no golden file");
|
||||
@ -41,7 +39,11 @@ fn main() {
|
||||
" {}: {}",
|
||||
n,
|
||||
if expected == output {
|
||||
format!("OK ({:?})", elapsed)
|
||||
let mut s = String::from("OK");
|
||||
if elapsed > Duration::from_millis(10) {
|
||||
s.push_str(&format!(" ({:?})", elapsed));
|
||||
}
|
||||
s
|
||||
} else {
|
||||
format!("expected {}, got {}", expected, output)
|
||||
}
|
||||
@ -53,14 +55,14 @@ fn main() {
|
||||
|
||||
pub trait SomePuzzle {
|
||||
fn number(&self) -> u32;
|
||||
fn with_parts(&self, is_real_data: bool, input: &str, f: &dyn Fn(usize, &dyn Fn() -> String));
|
||||
fn with_parts(&self, input: &str, f: &dyn Fn(usize, &dyn Fn() -> String));
|
||||
}
|
||||
impl<Input, const N: usize> SomePuzzle for Puzzle<Input, { N }> {
|
||||
fn number(&self) -> u32 {
|
||||
self.number
|
||||
}
|
||||
fn with_parts(&self, is_real_data: bool, s: &str, f: &dyn Fn(usize, &dyn Fn() -> String)) {
|
||||
let input = (self.parser)(is_real_data, s);
|
||||
fn with_parts(&self, s: &str, f: &dyn Fn(usize, &dyn Fn() -> String)) {
|
||||
let input = (self.parser)(s);
|
||||
for (i, p) in self.parts.iter().enumerate() {
|
||||
f(i + 1, &|| p(&input));
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
pub struct Puzzle<Input, const N: usize> {
|
||||
pub number: u32,
|
||||
pub parser: fn(bool, &str) -> Input,
|
||||
pub parser: fn(&str) -> Input,
|
||||
pub parts: [fn(&Input) -> String; N],
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ use nom::{
|
||||
|
||||
pub const PUZZLE: Puzzle<Vec<(Direction, i32)>, 2> = Puzzle {
|
||||
number: 1,
|
||||
parser: |_, input| {
|
||||
parser: |input| {
|
||||
terminated::<_, _, Error<&str>, _, _>(
|
||||
terminated(
|
||||
separated_list1(
|
||||
|
||||
@ -10,7 +10,7 @@ use nom::{
|
||||
|
||||
pub const PUZZLE: Puzzle<Vec<(usize, usize)>, 2> = Puzzle {
|
||||
number: 2,
|
||||
parser: |_, input| {
|
||||
parser: |input| {
|
||||
terminated::<_, _, Error<&str>, _, _>(
|
||||
terminated(
|
||||
separated_list1(char(','), separated_pair(usize, char('-'), usize)),
|
||||
|
||||
@ -10,7 +10,7 @@ use nom::{
|
||||
|
||||
pub const PUZZLE: Puzzle<Vec<Vec<u8>>, 2> = Puzzle {
|
||||
number: 3,
|
||||
parser: |_, input| {
|
||||
parser: |input| {
|
||||
terminated::<_, _, Error<&str>, _, _>(
|
||||
terminated(
|
||||
separated_list1(
|
||||
|
||||
@ -11,7 +11,7 @@ use nom::{
|
||||
|
||||
pub const PUZZLE: Puzzle<Vec<Vec<InTile>>, 2> = Puzzle {
|
||||
number: 4,
|
||||
parser: |_, input| {
|
||||
parser: |input| {
|
||||
terminated::<_, _, Error<&str>, _, _>(
|
||||
terminated(
|
||||
separated_list1(
|
||||
|
||||
@ -11,7 +11,7 @@ use nom::{
|
||||
|
||||
pub const PUZZLE: Puzzle<(Vec<Range>, Vec<usize>), 2> = Puzzle {
|
||||
number: 5,
|
||||
parser: |_, input| {
|
||||
parser: |input| {
|
||||
terminated::<_, _, Error<&str>, _, _>(
|
||||
separated_pair(
|
||||
separated_list1(
|
||||
|
||||
@ -13,7 +13,7 @@ use std::ops::{Add, Mul};
|
||||
|
||||
pub const PUZZLE: Puzzle<(Vec<Op>, Vec<Vec<Option<u8>>>), 2> = Puzzle {
|
||||
number: 6,
|
||||
parser: |_, input| {
|
||||
parser: |input| {
|
||||
terminated::<_, _, Error<&str>, _, _>(
|
||||
(
|
||||
terminated(
|
||||
|
||||
@ -1,89 +0,0 @@
|
||||
use crate::puzzle::Puzzle;
|
||||
use itertools::Itertools;
|
||||
use nom::{
|
||||
Parser,
|
||||
branch::alt,
|
||||
character::complete::{char, newline},
|
||||
combinator::{eof, value},
|
||||
error::Error,
|
||||
multi::{many1, separated_list1},
|
||||
sequence::terminated,
|
||||
};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
pub const PUZZLE: Puzzle<(usize, Vec<HashSet<usize>>), 2> = Puzzle {
|
||||
number: 7,
|
||||
parser: |_, input| {
|
||||
terminated::<_, _, Error<&str>, _, _>(
|
||||
terminated(
|
||||
(
|
||||
terminated(
|
||||
many1(alt((value(false, char('.')), value(true, char('S'))))),
|
||||
newline,
|
||||
)
|
||||
.map_opt(|v| v.into_iter().position(|b| b)),
|
||||
separated_list1(
|
||||
newline,
|
||||
many1(alt((value(false, char('.')), value(true, char('^'))))),
|
||||
)
|
||||
.map(|rows| {
|
||||
rows.into_iter()
|
||||
.map(|row| {
|
||||
row.into_iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, b)| if b { Some(i) } else { None })
|
||||
.collect()
|
||||
})
|
||||
.collect()
|
||||
}),
|
||||
),
|
||||
newline,
|
||||
),
|
||||
eof,
|
||||
)
|
||||
.parse(input)
|
||||
.unwrap()
|
||||
.1
|
||||
},
|
||||
parts: [
|
||||
|(start, splitter_rows)| {
|
||||
let mut beams = HashSet::from([*start]);
|
||||
let mut count = 0;
|
||||
for splitters in splitter_rows {
|
||||
beams = beams
|
||||
.iter()
|
||||
.flat_map(|x| {
|
||||
if splitters.contains(x) {
|
||||
count += 1;
|
||||
vec![x - 1, x + 1]
|
||||
} else {
|
||||
vec![*x]
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
count.to_string()
|
||||
},
|
||||
|(start, splitter_rows)| {
|
||||
let mut beams = HashMap::from([(*start, 1)]);
|
||||
for splitters in splitter_rows {
|
||||
beams = beams
|
||||
.into_iter()
|
||||
.flat_map(|(x, n)| {
|
||||
if splitters.contains(&x) {
|
||||
vec![x - 1, x + 1]
|
||||
} else {
|
||||
vec![x]
|
||||
}
|
||||
.into_iter()
|
||||
.map(move |x1| (x1, n))
|
||||
})
|
||||
.into_group_map()
|
||||
.into_iter()
|
||||
.map(|(k, vs)| (k, vs.into_iter().sum()))
|
||||
.collect();
|
||||
}
|
||||
beams.values().sum::<usize>().to_string()
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -4,4 +4,3 @@ pub(crate) mod day3;
|
||||
pub(crate) mod day4;
|
||||
pub(crate) mod day5;
|
||||
pub(crate) mod day6;
|
||||
pub(crate) mod day7;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user