Day 13 part 1
Omg I had the answer ages ago but was counting them instead of adding indexes loooool kill me
This commit is contained in:
parent
ca848fe338
commit
1c4d83196a
1 changed files with 201 additions and 0 deletions
201
2022/rust/src/day13.rs
Normal file
201
2022/rust/src/day13.rs
Normal file
|
@ -0,0 +1,201 @@
|
|||
use std::cmp::Ordering;
|
||||
use std::str::FromStr;
|
||||
|
||||
mod common;
|
||||
|
||||
#[derive(Debug, Eq)]
|
||||
enum Packet {
|
||||
Num(i32),
|
||||
List(Box<Vec<Packet>>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ParsePacketError {
|
||||
EndOfList,
|
||||
EndOfString,
|
||||
}
|
||||
|
||||
impl FromStr for Packet {
|
||||
type Err = ParsePacketError;
|
||||
|
||||
fn from_str(orig: &str) -> Result<Self, Self::Err> {
|
||||
println!("orig: {}", orig);
|
||||
match orig.chars().next() {
|
||||
Some('[') => {
|
||||
let contents = &orig[1..orig.len() - 1];
|
||||
let mut chunks = vec![];
|
||||
let mut chunk_start = 0;
|
||||
// this is dumb. I should be able to recurse this crap but my brain must be fried
|
||||
let mut nest_level = 0;
|
||||
for (i, c) in contents.char_indices() {
|
||||
match c {
|
||||
'[' => nest_level += 1,
|
||||
']' => nest_level -= 1,
|
||||
',' => {
|
||||
if nest_level == 0 {
|
||||
chunks.push(&contents[chunk_start..i]);
|
||||
chunk_start = i + 1;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if chunk_start < contents.len() {
|
||||
chunks.push(&contents[chunk_start..]);
|
||||
}
|
||||
println!("{:?}", chunks);
|
||||
Ok(Self::List(Box::new(
|
||||
chunks
|
||||
.iter()
|
||||
.map(|s| s.parse::<Packet>().unwrap())
|
||||
.collect(),
|
||||
)))
|
||||
}
|
||||
Some(_) => Ok(Self::Num(orig.parse::<i32>().unwrap())),
|
||||
None => Err(ParsePacketError::EndOfString),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Packet {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
println!("comparing {:?} with {:?}", self, other);
|
||||
match (self, other) {
|
||||
(Self::Num(l), Self::Num(r)) => l.cmp(r),
|
||||
(Self::List(l), Self::List(r)) => {
|
||||
for (l, r) in std::iter::zip(l.iter(), r.iter()) {
|
||||
match l.cmp(r) {
|
||||
Ordering::Equal => continue,
|
||||
v => {
|
||||
println!("done: {:?}", v);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
l.len().cmp(&r.len())
|
||||
}
|
||||
(Self::Num(l), r) => Self::List(Box::new(vec![Self::Num(*l)])).cmp(r),
|
||||
(l, Self::Num(r)) => l.cmp(&Self::List(Box::new(vec![Self::Num(*r)]))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Packet {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Packet {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Self::Num(l), Self::Num(r)) => l == r,
|
||||
(Self::List(l), Self::List(r)) => {
|
||||
l.len() == r.len() && l.iter().zip(r.iter()).all(|(l, r)| l == r)
|
||||
}
|
||||
(Self::Num(_), Self::List(_)) => false,
|
||||
(Self::List(_), Self::Num(_)) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PacketPair {
|
||||
left: Packet,
|
||||
right: Packet,
|
||||
}
|
||||
|
||||
type Input = Vec<PacketPair>;
|
||||
type Answer = usize;
|
||||
|
||||
fn processed_input(input: &str) -> Input {
|
||||
input
|
||||
.split("\n\n")
|
||||
.map(|c| {
|
||||
let mut l = c.lines();
|
||||
let result = PacketPair {
|
||||
left: l.next().unwrap().parse::<Packet>().unwrap(),
|
||||
right: l.next().unwrap().parse::<Packet>().unwrap(),
|
||||
};
|
||||
println!("{:?}", result);
|
||||
return result;
|
||||
})
|
||||
.collect::<Vec<PacketPair>>()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> Answer {
|
||||
let mut sum = 0;
|
||||
let mut i = 1;
|
||||
for pair in input {
|
||||
if pair.left < pair.right {
|
||||
sum += i
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
sum
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> Answer {
|
||||
0
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input_text = common::day_input(13);
|
||||
eprintln!("{}\n\nAbove is your input file.\n\n", input_text);
|
||||
let input = processed_input(&input_text);
|
||||
common::show_answers(&part1(&input), &part2(&input))
|
||||
// common::show_both_answers(&both_parts(&input))
|
||||
}
|
||||
|
||||
// fn both_parts(input: &Input) -> (Answer, Answer) {
|
||||
// (0, 0)
|
||||
// }
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const TEST_INPUT: &str = "[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]";
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let mut v = vec![Packet::Num(1), Packet::Num(0)];
|
||||
v.sort();
|
||||
assert_eq!(v, vec![Packet::Num(0), Packet::Num(1)]);
|
||||
assert!("[1,1,3,1]".parse::<Packet>().unwrap() < "[1,1,5,1]".parse::<Packet>().unwrap());
|
||||
assert_eq!(
|
||||
"[[8,7,6]]".parse::<Packet>().unwrap(),
|
||||
Packet::List(Box::new(vec![Packet::List(Box::new(vec![
|
||||
Packet::Num(8),
|
||||
Packet::Num(7),
|
||||
Packet::Num(6)
|
||||
]))]))
|
||||
);
|
||||
let input = processed_input(TEST_INPUT);
|
||||
assert_eq!(part1(&input), 13);
|
||||
assert_eq!(part2(&input), 0);
|
||||
// assert_eq!(both_parts(&input), (0, 0));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue