2 Commits

Author SHA1 Message Date
722f5205ff Stop manually impl'ing slice::from_ref 2023-07-01 18:00:35 +02:00
01300de076 Avoid sorting the entire list
Or materializing the list for that matter, since we only need to compare
each entry against both markers
2023-07-01 17:35:35 +02:00

View File

@@ -1,6 +1,6 @@
use core::slice;
use std::cmp::Ordering; use std::cmp::Ordering;
use anyhow::Context;
use anyhow::Result; use anyhow::Result;
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
@@ -8,15 +8,12 @@ use nom::character::complete::multispace1;
use nom::character::complete::newline; use nom::character::complete::newline;
use nom::combinator::iterator; use nom::combinator::iterator;
use nom::combinator::map; use nom::combinator::map;
use nom::multi::many0;
use nom::multi::separated_list0; use nom::multi::separated_list0;
use nom::sequence::delimited; use nom::sequence::delimited;
use nom::sequence::pair; use nom::sequence::pair;
use nom::sequence::terminated; use nom::sequence::terminated;
use nom::IResult; use nom::IResult;
use crate::common::parse_input;
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
enum Signal { enum Signal {
Number(u32), Number(u32),
@@ -31,11 +28,11 @@ impl Ord for Signal {
match (self, other) { match (self, other) {
(Signal::Number(first), Signal::Number(second)) => first.cmp(second), (Signal::Number(first), Signal::Number(second)) => first.cmp(second),
(Signal::Number(first), Signal::List(second)) => { (first @ Signal::Number(_), Signal::List(second)) => {
list_cmp(&[Signal::Number(*first)], second) list_cmp(slice::from_ref(first), second)
} }
(Signal::List(first), Signal::Number(second)) => { (Signal::List(first), second @ Signal::Number(_)) => {
list_cmp(first, &[Signal::Number(*second)]) list_cmp(first, slice::from_ref(second))
} }
(Signal::List(first), Signal::List(second)) => list_cmp(first, second), (Signal::List(first), Signal::List(second)) => list_cmp(first, second),
} }
@@ -91,33 +88,23 @@ pub fn part1(input: &[u8]) -> Result<String> {
Ok(result.to_string()) 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> { pub fn part2(input: &[u8]) -> Result<String> {
let marker1 = Signal::from(vec![vec![2]]); let marker1 = Signal::Number(2);
let marker2 = Signal::from(vec![vec![6]]); let marker2 = Signal::Number(6);
let mut signals = parse_input(input, parse_signals)?; let mut iterator = iterator(input, terminated(parse_signal, multispace1));
signals.push(marker1.clone()); let mut pos1 = 1;
signals.push(marker2.clone()); let mut pos2 = 2;
signals.sort_unstable(); for signal in &mut iterator {
if signal < marker1 {
let pos1 = signals pos1 += 1;
.iter() pos2 += 1;
.position(|v| v == &marker1) } else if signal < marker2 {
.context("Cannot find marker 1")? pos2 += 1;
+ 1; }
}
let pos2 = pos1
+ signals[pos1..]
.iter()
.position(|v| v == &marker2)
.context("Cannot find marker 2")?
+ 1;
Ok((pos1 * pos2).to_string()) Ok((pos1 * pos2).to_string())
} }