Implement 2022 day 13

This commit is contained in:
2022-12-13 18:15:12 +01:00
parent 796c638300
commit 4b18a733c9
3 changed files with 618 additions and 4 deletions

View File

@@ -1,9 +1,151 @@
use std::cmp::Ordering;
use anyhow::Context;
use anyhow::Result;
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::character::complete::multispace1;
use nom::character::complete::newline;
use nom::combinator::map;
use nom::multi::many0;
use nom::multi::separated_list0;
use nom::sequence::delimited;
use nom::sequence::pair;
use nom::sequence::terminated;
use nom::IResult;
pub fn part1(_input: &[u8]) -> Result<String> {
anyhow::bail!("not implemented")
use crate::common::parse_input;
#[derive(Debug, PartialEq, Eq, Clone)]
enum Signal {
Number(u32),
List(Vec<Signal>),
}
pub fn part2(_input: &[u8]) -> Result<String> {
anyhow::bail!("not implemented")
impl Ord for Signal {
fn cmp(&self, other: &Self) -> Ordering {
fn list_cmp(a: &[Signal], b: &[Signal]) -> Ordering {
a.cmp(b)
}
match (self, other) {
(Signal::Number(first), Signal::Number(second)) => first.cmp(second),
(Signal::Number(first), Signal::List(second)) => {
list_cmp(&[Signal::Number(*first)], second)
}
(Signal::List(first), Signal::Number(second)) => {
list_cmp(first, &[Signal::Number(*second)])
}
(Signal::List(first), Signal::List(second)) => list_cmp(first, second),
}
}
}
impl PartialOrd for Signal {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl From<u32> for Signal {
fn from(val: u32) -> Self {
Signal::Number(val)
}
}
impl<T> From<Vec<T>> for Signal
where
Signal: From<T>,
{
fn from(vec: Vec<T>) -> Self {
Signal::List(vec.into_iter().map(Signal::from).collect())
}
}
fn parse_signal(input: &[u8]) -> IResult<&[u8], Signal> {
alt((
map(nom::character::complete::u32, Signal::Number),
map(
delimited(tag("["), separated_list0(tag(","), parse_signal), tag("]")),
Signal::List,
),
))(input)
}
fn parse_signal_pairs(input: &[u8]) -> IResult<&[u8], Vec<(Signal, Signal)>> {
separated_list0(
newline,
pair(
terminated(parse_signal, newline),
terminated(parse_signal, newline),
),
)(input)
}
pub fn part1(input: &[u8]) -> Result<String> {
let signals = parse_input(input, parse_signal_pairs)?;
let result: usize = signals
.into_iter()
.enumerate()
.filter_map(|(i, (first, second))| (first < second).then_some(i + 1))
.sum();
Ok(result.to_string())
}
fn parse_signals(input: &[u8]) -> IResult<&[u8], Vec<Signal>> {
many0(terminated(parse_signal, multispace1))(input)
}
pub fn part2(input: &[u8]) -> Result<String> {
let marker1 = Signal::from(vec![vec![2]]);
let marker2 = Signal::from(vec![vec![6]]);
let mut signals = parse_input(input, parse_signals)?;
signals.push(marker1.clone());
signals.push(marker2.clone());
signals.sort_unstable();
let pos1 = signals
.iter()
.position(|v| v == &marker1)
.context("Cannot find marker 1")?
+ 1;
let pos2 = pos1
+ signals[pos1..]
.iter()
.position(|v| v == &marker2)
.context("Cannot find marker 2")?
+ 1;
Ok((pos1 * pos2).to_string())
}
#[cfg(test)]
mod tests {
use super::*;
const SAMPLE: &[u8] = include_bytes!("samples/13.txt");
#[test]
fn test_parse_signal() {
assert_eq!(
parse_signal(b"[1,1,3,1,1]").unwrap(),
(&[][..], Signal::from(vec![1, 1, 3, 1, 1]))
);
}
#[test]
fn sample_part1() {
assert_eq!(part1(SAMPLE).unwrap(), "13");
}
#[test]
fn sample_part2() {
assert_eq!(part2(SAMPLE).unwrap(), "140");
}
}

23
2022/src/samples/13.txt Normal file
View File

@@ -0,0 +1,23 @@
[1,1,3,1,1]
[1,1,5,1,1]
[[1],[2,3,4]]
[[1],4]
[9]
[[8,7,6]]
[[4,4],4,4]
[[4,4],4,4,4]
[7,7,7,7]
[7,7,7]
[]
[3]
[[[]]]
[[]]
[1,[2,[3,[4,[5,6,7]]]],8,9]
[1,[2,[3,[4,[5,6,0]]]],8,9]