main.rs (4495B)
1 use std::cmp::Ordering;
2 use std::collections::VecDeque;
3
4 #[derive(PartialEq, Eq, Clone, Debug)]
5 enum Packet {
6 List(Vec<Packet>),
7 Number(i32),
8 }
9
10 #[derive(Clone, Debug)]
11 enum Chunk {
12 ListStart,
13 Number(i32),
14 Packet(Packet),
15 }
16
17 impl Packet {
18 fn from_str(s: &str) -> Option<Packet> {
19 let mut chunks = VecDeque::new();
20 let mut buf = String::new();
21 for ch in s.chars() {
22 match ch {
23 '[' => chunks.push_back(Chunk::ListStart),
24 ']' => {
25 if !buf.is_empty() {
26 chunks.push_back(Chunk::Number(buf.parse::<i32>().unwrap()));
27 buf.clear();
28 }
29 let mut new_list = Vec::new();
30 while let Some(c) = chunks.pop_back() {
31 match c {
32 Chunk::ListStart => {
33 chunks.push_back(Chunk::Packet(Packet::List(new_list)));
34 break;
35 }
36 Chunk::Number(x) => {
37 new_list.insert(0, Packet::Number(x));
38 }
39 Chunk::Packet(c) => {
40 new_list.insert(0, c);
41 }
42 }
43 }
44 }
45 ',' => {
46 if !buf.is_empty() {
47 chunks.push_back(Chunk::Number(buf.parse::<i32>().unwrap()));
48 buf.clear();
49 }
50 buf.clear();
51 }
52 ch => buf.push(ch),
53 }
54 }
55 if let Some(c) = chunks.into_iter().nth(0) {
56 match c {
57 Chunk::Packet(cc) => Some(cc),
58 _ => None,
59 }
60 } else {
61 None
62 }
63 }
64 }
65
66 impl Ord for Packet {
67 fn cmp(&self, other: &Self) -> Ordering {
68 match (self, other) {
69 (Self::Number(a), Self::Number(b)) => a.cmp(b),
70 (Self::Number(a), Self::List(_)) => Packet::List(vec![Packet::Number(*a)]).cmp(other),
71 (Self::List(_), Self::Number(b)) => self.cmp(&Packet::List(vec![Packet::Number(*b)])),
72 (Self::List(a), Self::List(b)) => {
73 let mut aa = a.iter();
74 let mut bb = b.iter();
75 loop {
76 match (aa.next(), bb.next()) {
77 (Some(aaa), Some(bbb)) => match aaa.cmp(bbb) {
78 Ordering::Less => break Ordering::Less,
79 Ordering::Equal => (),
80 Ordering::Greater => break Ordering::Greater,
81 },
82 (Some(_), None) => {
83 break Ordering::Greater;
84 }
85 (None, Some(_)) => {
86 break Ordering::Less;
87 }
88 (None, None) => {
89 break Ordering::Equal;
90 }
91 }
92 }
93 }
94 }
95 }
96 }
97
98 impl PartialOrd for Packet {
99 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
100 Some(self.cmp(other))
101 }
102 }
103
104 fn main() {
105 let input = std::fs::read_to_string("input.txt")
106 .unwrap()
107 .trim()
108 .split("\n\n")
109 .map(|p| {
110 p.split('\n')
111 .map(|s| Packet::from_str(s).unwrap())
112 .collect()
113 })
114 .collect::<Vec<Vec<Packet>>>();
115 // 6478
116 println!("Part 1: {}", part_1(&input));
117 // 21922
118 println!("Part 2: {}", part_2(&input));
119 }
120
121 fn part_1(input: &Vec<Vec<Packet>>) -> usize {
122 let mut tot = 0;
123 for (i, pp) in input.iter().enumerate() {
124 if let Ordering::Less = pp[0].cmp(&pp[1]) {
125 tot += i + 1;
126 }
127 }
128 tot
129 }
130
131 fn part_2(input: &Vec<Vec<Packet>>) -> usize {
132 let divider_1 = Packet::List(vec![Packet::Number(2)]);
133 let divider_2 = Packet::List(vec![Packet::Number(6)]);
134 let mut all_packet = {
135 let mut tmp = vec![divider_1.clone(), divider_2.clone()];
136 for pp in input {
137 tmp.append(&mut pp.clone());
138 }
139 tmp
140 };
141 all_packet.sort();
142 (all_packet.binary_search(÷r_1).unwrap() + 1)
143 * (all_packet.binary_search(÷r_2).unwrap() + 1)
144 }