146 lines
4.1 KiB
Rust
146 lines
4.1 KiB
Rust
use std::str::FromStr;
|
|
use crate::Day;
|
|
|
|
pub struct Day10(Vec<Vec<BracketType>>, Vec<(usize, Bracket)>);
|
|
|
|
impl Day for Day10 {
|
|
fn init(content: String) -> anyhow::Result<Self> {
|
|
let l = content.lines().map(|x| x.chars().map(|x| x.to_string().parse().unwrap()).collect::<Vec<BracketType>>()).collect::<Vec<_>>();
|
|
Ok(Self(l.clone(), gather_part1(l)))
|
|
}
|
|
|
|
fn part1(&self) -> anyhow::Result<String> {
|
|
Ok(format!("{}", self.1.iter().map(|&(_, b)| {
|
|
match b {
|
|
Bracket::Round => 3,
|
|
Bracket::Square => 57,
|
|
Bracket::Curly => 1197,
|
|
Bracket::Angle => 25137,
|
|
}
|
|
}).sum::<u32>()))
|
|
}
|
|
|
|
fn part2(&self) -> anyhow::Result<String> {
|
|
let mut wrongs = self.1.clone();
|
|
let mut zz = self.0.clone();
|
|
wrongs.sort_unstable();
|
|
wrongs.iter().rev().for_each(|&(x, _)| std::mem::drop(zz.remove(x)));
|
|
let mut scores = Vec::new();
|
|
for z in zz {
|
|
let mut stack = Vec::new();
|
|
for bracket in z {
|
|
match bracket {
|
|
BracketType::Open(x) => stack.push(x),
|
|
BracketType::Close(x) => {
|
|
if let Some(y) = stack.pop() {
|
|
assert_eq!(y, x);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stack.reverse();
|
|
let mut score = 0_u64;
|
|
for b in stack {
|
|
score *= 5;
|
|
score += match b {
|
|
Bracket::Round => 1,
|
|
Bracket::Square => 2,
|
|
Bracket::Curly => 3,
|
|
Bracket::Angle => 4,
|
|
}
|
|
}
|
|
scores.push(score);
|
|
}
|
|
scores.sort_unstable();
|
|
|
|
|
|
Ok(format!("{:?}", scores[scores.len() / 2]))
|
|
}
|
|
}
|
|
|
|
fn gather_part1(v: Vec<Vec<BracketType>>) -> Vec<(usize, Bracket)> {
|
|
let mut wrongs = Vec::new();
|
|
for (idx, brackets) in v.iter().enumerate() {
|
|
let mut stack = Vec::new();
|
|
for &bracket in brackets {
|
|
match bracket {
|
|
BracketType::Open(x) => stack.push(x),
|
|
BracketType::Close(x) => {
|
|
if let Some(y) = stack.pop() {
|
|
if x != y {
|
|
wrongs.push((idx, x));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
wrongs
|
|
}
|
|
|
|
impl FromStr for BracketType {
|
|
type Err = ();
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
match s {
|
|
"(" => Ok(BracketType::Open(Bracket::Round)),
|
|
"[" => Ok(BracketType::Open(Bracket::Square)),
|
|
"{" => Ok(BracketType::Open(Bracket::Curly)),
|
|
"<" => Ok(BracketType::Open(Bracket::Angle)),
|
|
")" => Ok(BracketType::Close(Bracket::Round)),
|
|
"]" => Ok(BracketType::Close(Bracket::Square)),
|
|
"}" => Ok(BracketType::Close(Bracket::Curly)),
|
|
">" => Ok(BracketType::Close(Bracket::Angle)),
|
|
_ => Err(()),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)]
|
|
pub enum BracketType {
|
|
Open(Bracket),
|
|
Close(Bracket),
|
|
}
|
|
|
|
|
|
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)]
|
|
pub enum Bracket {
|
|
Round,
|
|
Square,
|
|
Curly,
|
|
Angle,
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::{Day, day_tests};
|
|
use crate::day10::Day10;
|
|
|
|
const INPUT: &str = r"[({(<(())[]>[[{[]{<()<>>
|
|
[(()[<>])]({[<{<<[]>>(
|
|
{([(<{}[<>[]}>{[]{[(<()>
|
|
(((({<>}<{<{<>}{[]{[]{}
|
|
[[<[([]))<([[{}[[()]]]
|
|
[{[{({}]{}}([{[{{{}}([]
|
|
{<[[]]>}<{[{[{[]{()[[[]
|
|
[<(<(<(<{}))><([]([]()
|
|
<{([([[(<>()){}]>(<<{{
|
|
<{([{{}}[<[[[<>{}]]]>[]]";
|
|
|
|
#[test]
|
|
fn part1_test() -> anyhow::Result<()> {
|
|
let d = Day10::init(INPUT.to_string())?;
|
|
assert_eq!("26397", d.part1()?);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn part2_test() -> anyhow::Result<()> {
|
|
let d = Day10::init(INPUT.to_string())?;
|
|
assert_eq!("288957", d.part2()?);
|
|
Ok(())
|
|
}
|
|
|
|
day_tests!(Day10, "10", "392421", "2769449099");
|
|
} |