mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-27 22:00:31 +01:00
Compare commits
3 Commits
e887a8ad0d
...
1cd5579bf6
| Author | SHA1 | Date | |
|---|---|---|---|
| 1cd5579bf6 | |||
| 7c7c69255d | |||
| 391bba24c5 |
@@ -1,6 +1,7 @@
|
|||||||
//! Common helper utilities to all days
|
//! Common helper utilities to all days
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use nom::combinator::map;
|
||||||
use nom::error::ErrorKind;
|
use nom::error::ErrorKind;
|
||||||
use nom::error::ParseError;
|
use nom::error::ParseError;
|
||||||
use nom::Finish;
|
use nom::Finish;
|
||||||
@@ -93,6 +94,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add an index to repeated successful invocations of the embedded parser.
|
||||||
|
pub fn enumerate<I, O, E>(f: impl Parser<I, O, E>) -> impl FnMut(I) -> IResult<I, (usize, O), E> {
|
||||||
|
let mut index = 0usize;
|
||||||
|
|
||||||
|
map(f, move |v| {
|
||||||
|
let res = (index, v);
|
||||||
|
index += 1;
|
||||||
|
res
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the minimum and maximum of two unordered variables
|
/// Return the minimum and maximum of two unordered variables
|
||||||
pub fn minmax<T>(a: T, b: T) -> (T, T)
|
pub fn minmax<T>(a: T, b: T) -> (T, T)
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -16,17 +16,16 @@ use nom::sequence::terminated;
|
|||||||
use nom::sequence::tuple;
|
use nom::sequence::tuple;
|
||||||
use nom::IResult;
|
use nom::IResult;
|
||||||
|
|
||||||
|
use crate::common::enumerate;
|
||||||
use crate::common::parse_input;
|
use crate::common::parse_input;
|
||||||
|
|
||||||
type Move = (usize, usize, usize);
|
type Move = (usize, usize, usize);
|
||||||
type OwnedStacks = Vec<Vec<u8>>;
|
type OwnedStacks = Vec<Vec<u8>>;
|
||||||
|
|
||||||
fn parse_row<'a>(input: &'a [u8], stacks: &mut OwnedStacks) -> IResult<&'a [u8], ()> {
|
fn parse_row<'a>(input: &'a [u8], stacks: &mut OwnedStacks) -> IResult<&'a [u8], ()> {
|
||||||
let mut index = 0usize;
|
|
||||||
|
|
||||||
// Forgive me for this crime
|
// Forgive me for this crime
|
||||||
fold_many1(
|
fold_many1(
|
||||||
terminated(
|
enumerate(terminated(
|
||||||
alt((
|
alt((
|
||||||
// Parse a delimited value into a Some(content)
|
// Parse a delimited value into a Some(content)
|
||||||
map(delimited(tag("["), take(1usize), tag("]")), |v: &[u8]| {
|
map(delimited(tag("["), take(1usize), tag("]")), |v: &[u8]| {
|
||||||
@@ -36,9 +35,9 @@ fn parse_row<'a>(input: &'a [u8], stacks: &mut OwnedStacks) -> IResult<&'a [u8],
|
|||||||
map(tag(" "), |_| None),
|
map(tag(" "), |_| None),
|
||||||
)),
|
)),
|
||||||
opt(tag(" ")),
|
opt(tag(" ")),
|
||||||
),
|
)),
|
||||||
|| (),
|
|| (),
|
||||||
move |_, c| {
|
move |_, (index, c)| {
|
||||||
if let Some(b) = c {
|
if let Some(b) = c {
|
||||||
if stacks.len() <= index {
|
if stacks.len() <= index {
|
||||||
stacks.resize_with(index + 1, Vec::new);
|
stacks.resize_with(index + 1, Vec::new);
|
||||||
@@ -46,8 +45,6 @@ fn parse_row<'a>(input: &'a [u8], stacks: &mut OwnedStacks) -> IResult<&'a [u8],
|
|||||||
|
|
||||||
stacks[index].push(b)
|
stacks[index].push(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
index += 1;
|
|
||||||
},
|
},
|
||||||
)(input)
|
)(input)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,27 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
fn find_first(input: &[u8], unique: usize) -> Result<usize> {
|
fn find_first(input: &[u8], unique: usize) -> Result<usize> {
|
||||||
#[inline]
|
let mut seen = [false; 256];
|
||||||
const fn index(c: u8) -> usize {
|
|
||||||
(c - b'a') as usize
|
let mut tail_it = input.iter();
|
||||||
}
|
|
||||||
let mut seen = [false; 26];
|
|
||||||
|
|
||||||
let mut first = 0;
|
let mut first = 0;
|
||||||
|
|
||||||
// Loop invariant: input[first..last] contains only unique characters
|
// Loop invariant: input[first..last] contains only unique characters
|
||||||
for (last, &c) in input.iter().enumerate() {
|
for (last, &c) in input.iter().enumerate() {
|
||||||
if seen[index(c)] {
|
if seen[c as usize] {
|
||||||
while input[first] != c {
|
first += (&mut tail_it)
|
||||||
seen[index(input[first])] = false;
|
.take_while(|&&b| b != c)
|
||||||
first += 1;
|
.map(|&b| seen[b as usize] = false)
|
||||||
}
|
.count()
|
||||||
first += 1;
|
+ 1; // +1 because take_while doesn't return the first element that didn't satisfy the condition, while we do need to count it
|
||||||
} else {
|
} else {
|
||||||
// New unique character found: input[first..=last] contains unique characters
|
// New unique character found: input[first..=last] contains unique characters
|
||||||
if last - first + 1 == unique {
|
if last - first + 1 == unique {
|
||||||
return Ok(first + unique);
|
return Ok(last + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
seen[index(c)] = true;
|
seen[c as usize] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user