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 }