Compare commits
2 Commits
36ceda33db
...
f10e8a4c04
| Author | SHA1 | Date | |
|---|---|---|---|
| f10e8a4c04 | |||
| 57f4bc2732 |
14
src/bin/d13p1.rs
Normal file
14
src/bin/d13p1.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use aoc22::{day13, util};
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let pairs = day13::parse_pairs(&util::parse_input());
|
||||||
|
|
||||||
|
let mut sum = 0;
|
||||||
|
for (i, pair) in pairs.iter().enumerate() {
|
||||||
|
if pair.0 < pair.1 {
|
||||||
|
sum += i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Sum of indices of pairs in right order: {}", sum);
|
||||||
|
}
|
||||||
24
src/bin/d13p2.rs
Normal file
24
src/bin/d13p2.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use aoc22::{
|
||||||
|
day13::{self, Node},
|
||||||
|
util,
|
||||||
|
};
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let mut pairs = day13::parse_pairs(&util::parse_input());
|
||||||
|
let mut packets = Vec::new();
|
||||||
|
while let Some(pair) = pairs.pop() {
|
||||||
|
packets.push(pair.0);
|
||||||
|
packets.push(pair.1);
|
||||||
|
}
|
||||||
|
let div1 = Node::List(vec![Node::List(vec![Node::Num(2)])]);
|
||||||
|
let div2 = Node::List(vec![Node::List(vec![Node::Num(6)])]);
|
||||||
|
packets.push(div1.clone());
|
||||||
|
packets.push(div2.clone());
|
||||||
|
|
||||||
|
packets.sort();
|
||||||
|
let n1 = packets.iter().find_position(|p| **p == div1).unwrap().0 + 1;
|
||||||
|
let n2 = packets.iter().find_position(|p| **p == div2).unwrap().0 + 1;
|
||||||
|
|
||||||
|
println!("Decoder key: {}", n1 * n2);
|
||||||
|
}
|
||||||
120
src/day13.rs
Normal file
120
src/day13.rs
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
use itertools::{EitherOrBoth, Itertools};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Node {
|
||||||
|
List(Vec<Node>),
|
||||||
|
Num(usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for Node {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
match self {
|
||||||
|
Node::List(l1) => match other {
|
||||||
|
Node::Num(n2) => self.cmp(&Node::List(vec![Node::Num(*n2)])),
|
||||||
|
Node::List(l2) => {
|
||||||
|
for pair in l1.iter().zip_longest(l2.iter()) {
|
||||||
|
match pair {
|
||||||
|
EitherOrBoth::Both(n1, n2) => {
|
||||||
|
if n1 < n2 {
|
||||||
|
return Ordering::Less;
|
||||||
|
} else if n2 < n1 {
|
||||||
|
return Ordering::Greater;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EitherOrBoth::Left(_) => return Ordering::Greater,
|
||||||
|
EitherOrBoth::Right(_) => return Ordering::Less,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ordering::Equal
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Node::Num(n1) => match other {
|
||||||
|
Node::Num(n2) => n1.cmp(n2),
|
||||||
|
Node::List(_) => Node::List(vec![Node::Num(*n1)]).cmp(other),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Node {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Node {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.partial_cmp(other) == Some(Ordering::Equal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for Node {}
|
||||||
|
|
||||||
|
pub fn parse_pairs(input: &String) -> Vec<(Node, Node)> {
|
||||||
|
let mut result = Vec::new();
|
||||||
|
|
||||||
|
for mut p in &input.lines().chunks(3) {
|
||||||
|
let first = parse_list(p.next().unwrap()).0;
|
||||||
|
let second = parse_list(p.next().unwrap()).0;
|
||||||
|
assert!(p.next().unwrap_or("").is_empty());
|
||||||
|
|
||||||
|
result.push((first, second));
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ParseState {
|
||||||
|
Idle,
|
||||||
|
InNumber,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_list(line: &str) -> (Node, usize) {
|
||||||
|
assert_eq!(line.chars().next(), Some('['));
|
||||||
|
|
||||||
|
let mut state = ParseState::Idle;
|
||||||
|
let mut i = 1;
|
||||||
|
let mut result = Vec::new();
|
||||||
|
|
||||||
|
let mut num_start = 0;
|
||||||
|
while i < line.len() {
|
||||||
|
let c = line.chars().nth(i).unwrap();
|
||||||
|
match state {
|
||||||
|
ParseState::Idle => {
|
||||||
|
if c == '[' {
|
||||||
|
let (n, inc) = parse_list(&line[i..]);
|
||||||
|
result.push(n);
|
||||||
|
i += inc;
|
||||||
|
} else if c == ']' {
|
||||||
|
// End of list reached
|
||||||
|
break;
|
||||||
|
} else if c.is_numeric() {
|
||||||
|
num_start = i;
|
||||||
|
state = ParseState::InNumber;
|
||||||
|
} else if c != ',' {
|
||||||
|
panic!("Unknown char: {}", c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ParseState::InNumber => {
|
||||||
|
if c == ',' {
|
||||||
|
let slice = &line[num_start..i];
|
||||||
|
result.push(Node::Num(slice.parse().unwrap()));
|
||||||
|
state = ParseState::Idle;
|
||||||
|
} else if c == ']' {
|
||||||
|
// End of list reached
|
||||||
|
let slice = &line[num_start..i];
|
||||||
|
result.push(Node::Num(slice.parse().unwrap()));
|
||||||
|
|
||||||
|
break;
|
||||||
|
} else if !c.is_numeric() {
|
||||||
|
panic!("Unknown digit {}", c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(Node::List(result), i)
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ pub mod day1;
|
|||||||
pub mod day10;
|
pub mod day10;
|
||||||
pub mod day11;
|
pub mod day11;
|
||||||
pub mod day12;
|
pub mod day12;
|
||||||
|
pub mod day13;
|
||||||
pub mod day2;
|
pub mod day2;
|
||||||
pub mod day3;
|
pub mod day3;
|
||||||
pub mod day4;
|
pub mod day4;
|
||||||
|
|||||||
Reference in New Issue
Block a user