2023-02-15 1
2023-02-15 2
2023-02-15 3 😅
👋I'm Luciano ( 🍕🍝 ) Senior Architect @ fourTheorem nodejsdp.link 📔Co-Author of Node.js Design Patterns 👉 Let's connect! (blog) (twitter) (twitch) (github) loige.co @loige loige lmammino Grab the slides 4
Always re-imagining We are a pioneering technology consultancy focused on AWS and serverless | | Accelerated Serverless AI as a Service Platform Modernisation loige ✉Reach out to us at 😇We are always looking for talent: hello@fourTheorem.com fth.link/careers 5
loige podcast awsbites.com How do you write Lambda Functions in Rust? 6
Why am I learning Rust 🦀 Full-stack Web Developer turning Cloud Architect loige Experience with dynamic scripting languages (JavaScript, Python, Php) Looked into Go for performance-sensitive applications Rust seemed like the natural next step ... and it's fun! 7
How it is going loige error[E0382]: borrow of moved value: `v` --> src/main.rs:6:19 | 4 | let v = vec![2, 3, 5, 7, 11, 13, 17]; | - move occurs because `v` has type `Vec<i32>`, whic 5 | hold_my_vec(v); | - value moved here 6 | let element = v.get(3); | ^^^^^^^^ value borrowed here after move | 1 2 3 4 5 6 7 8 9 10 #[stable(feature = "future_poll_fn", since = "1.64.0")] impl<T, F> Future for PollFn<F> where F: FnMut(&mut Context<'_>) -> Poll<T>, { type Output = T; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> P // SAFETY: We are not moving out of the pinned field (unsafe { &mut self.get_unchecked_mut().f })(cx) } } 1 2 3 4 5 6 7 8 9 10 11 12 How it started 8
How it started -> How it is going loige 2019: Ported some JS code to Rust (resulted in ) jwtinfo 2020-2022: Live streamed solving Advent of Code in Rust + some other small side-projects and coding challenges Nothing "production ready" as of today 🤷 Excited about Serverless Rust on AWS 9
Yeah, but it's not really about tech... loige 10
It's about people loige 11
It's about people loige @gbinside 12
It's about people loige 13
🔥Hot take If you are struggling to learn Rust (or anything else, really)... Find a learning buddy! loige 14
Advent of Code . com loige github.com/lmammino/rust-advent 15
loige 16
loige 17
loige Valve NV has flow rate=5; tunnels lead to valves ZV, CG, YB, HX, OY Valve NU has flow rate=6; tunnels lead to valves DA, MA, OA, DK Valve VU has flow rate=0; tunnels lead to valves PS, FX Valve JW has flow rate=0; tunnels lead to valves AA, MD Valve RI has flow rate=0; tunnels lead to valves OY, DG Valve DG has flow rate=9; tunnels lead to valves TG, RI, DF, EV, KW Valve PH has flow rate=7; tunnels lead to valves KW, OW, LT, LZ Valve KZ has flow rate=12; tunnels lead to valves ET, QV, CK, MS Valve IX has flow rate=0; tunnels lead to valves TS, DO Valve MS has flow rate=0; tunnels lead to valves LZ, KZ Valve IL has flow rate=0; tunnels lead to valves DO, ET Valve EJ has flow rate=20; tunnels lead to valves AV, JY Valve DK has flow rate=0; tunnels lead to valves NU, CG Valve YB has flow rate=0; tunnels lead to valves NV, PS Valve OA has flow rate=0; tunnels lead to valves YA, NU Valve DA has flow rate=0; tunnels lead to valves NU, RG Valve KO has flow rate=0; tunnels lead to valves AA, TG Valve RG has flow rate=4; tunnels lead to valves DF, DA, ZV, MD, LB Valve MA has flow rate=0; tunnels lead to valves AA, NU Valve OW has flow rate=0; tunnels lead to valves DO, PH Valve KW has flow rate=0; tunnels lead to valves DG, PH Valve DO has flow rate=14; tunnels lead to valves IX, IL, CZ, OW Valve DF has flow rate=0; tunnels lead to valves RG, DG Valve TG has flow rate=0; tunnels lead to valves DG, KO Valve LB has flow rate=0; tunnels lead to valves RG, FX Valve HX has flow rate=0; tunnels lead to valves AA, NV Valve GB has flow rate=0; tunnels lead to valves AV, XK Valve CG has flow rate=0; tunnels lead to valves DK, NV Valve LT has flow rate=0; tunnels lead to valves AO, PH Valve FX has flow rate=23; tunnels lead to valves LB, HY, VU Valve ET has flow rate=0; tunnels lead to valves IL, KZ Valve CK has flow rate=0; tunnels lead to valves UX, KZ Valve LZ has flow rate=0; tunnels lead to valves PH, MS Valve YA has flow rate=17; tunnels lead to valves JY, OA Valve TS has flow rate=0; tunnels lead to valves NO, IX Valve NO has flow rate=8; tunnel leads to valve TS Valve XK has flow rate=24; tunnel leads to valve GB 1. Read & understand the puzzle 2. Parse the input 3. Write some code 4. Find solution 5. Submit your solution (unlocks part 2) 6. Repeat from point 1 for part 2 18
Iterator combinators loige 19
1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 y2022 - Day 1: Calorie Counting loige sum sum sum sum sum max 6000 4000 11000 24000 20 10000 24000
fn classic(input: &str) -> u64 { let mut max = 0; let batches = input.split("nn"); for batch in batches { let lines = batch.lines(); let mut total = 0; for line in lines { let value = line.parse::<u64>().unwrap(); total += value; } if total > max { max = total; } } max } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 let mut max = 0; max fn classic(input: &str) -> u64 { 1 2 let batches = input.split("nn"); 3 for batch in batches { 4 let lines = batch.lines(); 5 let mut total = 0; 6 for line in lines { 7 let value = line.parse::<u64>().unwrap(); 8 total += value; 9 } 10 if total > max { 11 max = total; 12 } 13 } 14 15 } 16 let batches = input.split("nn"); fn classic(input: &str) -> u64 { 1 let mut max = 0; 2 3 for batch in batches { 4 let lines = batch.lines(); 5 let mut total = 0; 6 for line in lines { 7 let value = line.parse::<u64>().unwrap(); 8 total += value; 9 } 10 if total > max { 11 max = total; 12 } 13 } 14 max 15 } 16 for batch in batches { } fn classic(input: &str) -> u64 { 1 let mut max = 0; 2 let batches = input.split("nn"); 3 4 let lines = batch.lines(); 5 let mut total = 0; 6 for line in lines { 7 let value = line.parse::<u64>().unwrap(); 8 total += value; 9 } 10 if total > max { 11 max = total; 12 } 13 14 max 15 } 16 let lines = batch.lines(); let mut total = 0; fn classic(input: &str) -> u64 { 1 let mut max = 0; 2 let batches = input.split("nn"); 3 for batch in batches { 4 5 6 for line in lines { 7 let value = line.parse::<u64>().unwrap(); 8 total += value; 9 } 10 if total > max { 11 max = total; 12 } 13 } 14 max 15 } 16 for line in lines { } fn classic(input: &str) -> u64 { 1 let mut max = 0; 2 let batches = input.split("nn"); 3 for batch in batches { 4 let lines = batch.lines(); 5 let mut total = 0; 6 7 let value = line.parse::<u64>().unwrap(); 8 total += value; 9 10 if total > max { 11 max = total; 12 } 13 } 14 max 15 } 16 let value = line.parse::<u64>().unwrap(); fn classic(input: &str) -> u64 { 1 let mut max = 0; 2 let batches = input.split("nn"); 3 for batch in batches { 4 let lines = batch.lines(); 5 let mut total = 0; 6 for line in lines { 7 8 total += value; 9 } 10 if total > max { 11 max = total; 12 } 13 } 14 max 15 } 16 total += value; fn classic(input: &str) -> u64 { 1 let mut max = 0; 2 let batches = input.split("nn"); 3 for batch in batches { 4 let lines = batch.lines(); 5 let mut total = 0; 6 for line in lines { 7 let value = line.parse::<u64>().unwrap(); 8 9 } 10 if total > max { 11 max = total; 12 } 13 } 14 max 15 } 16 if total > max { max = total; } fn classic(input: &str) -> u64 { 1 let mut max = 0; 2 let batches = input.split("nn"); 3 for batch in batches { 4 let lines = batch.lines(); 5 let mut total = 0; 6 for line in lines { 7 let value = line.parse::<u64>().unwrap(); 8 total += value; 9 } 10 11 12 13 } 14 max 15 } 16 fn classic(input: &str) -> u64 { let mut max = 0; let batches = input.split("nn"); for batch in batches { let lines = batch.lines(); let mut total = 0; for line in lines { let value = line.parse::<u64>().unwrap(); total += value; } if total > max { max = total; } } max } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Classic noob approach loige 21
fn combinators(input: &str) -> u64 { input .split("nn") .map(|batch| { batch .lines() .map(|line| line.parse::<u64>().unwrap()) .sum::<u64>() }) .max() .unwrap() } 1 2 3 4 5 6 7 8 9 10 11 12 input .split("nn") fn combinators(input: &str) -> u64 { 1 2 3 .map(|batch| { 4 batch 5 .lines() 6 .map(|line| line.parse::<u64>().unwrap()) 7 .sum::<u64>() 8 }) 9 .max() 10 .unwrap() 11 } 12 .map(|batch| { }) fn combinators(input: &str) -> u64 { 1 input 2 .split("nn") 3 4 batch 5 .lines() 6 .map(|line| line.parse::<u64>().unwrap()) 7 .sum::<u64>() 8 9 .max() 10 .unwrap() 11 } 12 batch .lines() .map(|line| line.parse::<u64>().unwrap()) .sum::<u64>() fn combinators(input: &str) -> u64 { 1 input 2 .split("nn") 3 .map(|batch| { 4 5 6 7 8 }) 9 .max() 10 .unwrap() 11 } 12 .max() .unwrap() fn combinators(input: &str) -> u64 { 1 input 2 .split("nn") 3 .map(|batch| { 4 batch 5 .lines() 6 .map(|line| line.parse::<u64>().unwrap()) 7 .sum::<u64>() 8 }) 9 10 11 } 12 fn combinators(input: &str) -> u64 { input .split("nn") .map(|batch| { batch .lines() .map(|line| line.parse::<u64>().unwrap()) .sum::<u64>() }) .max() .unwrap() } 1 2 3 4 5 6 7 8 9 10 11 12 Combinators approach loige 22
Nice, but the classic noob version must be much faster, right? 🤔 loige 23
⚡NOT REALLY! loige 24
Yeah, but I am sure that iterator combinators are not always flexible enough, right? 🤔 loige 25
1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 y2022 Day 1: Calorie Counting (part 2) loige sum sum sum sum sum top 3 6000 4000 11000 24000 26 10000 24000 11000 10000 sum 45000
fn combinators(input: &str) -> u64 { input .split("nn") .map(|batch| { batch .lines() .map(|line| line.parse::<u64>().unwrap()) .sum::<u64>() }) .sort_descending() .take(3) .sum() } 1 2 3 4 5 6 7 8 9 10 11 12 13 .sort_descending() fn combinators(input: &str) -> u64 { 1 input 2 .split("nn") 3 .map(|batch| { 4 batch 5 .lines() 6 .map(|line| line.parse::<u64>().unwrap()) 7 .sum::<u64>() 8 }) 9 10 .take(3) 11 .sum() 12 } 13 .take(3) fn combinators(input: &str) -> u64 { 1 input 2 .split("nn") 3 .map(|batch| { 4 batch 5 .lines() 6 .map(|line| line.parse::<u64>().unwrap()) 7 .sum::<u64>() 8 }) 9 .sort_descending() 10 11 .sum() 12 } 13 .sum() fn combinators(input: &str) -> u64 { 1 input 2 .split("nn") 3 .map(|batch| { 4 batch 5 .lines() 6 .map(|line| line.parse::<u64>().unwrap()) 7 .sum::<u64>() 8 }) 9 .sort_descending() 10 .take(3) 11 12 } 13 fn combinators(input: &str) -> u64 { input .split("nn") .map(|batch| { batch .lines() .map(|line| line.parse::<u64>().unwrap()) .sum::<u64>() }) .sort_descending() .take(3) .sum() } 1 2 3 4 5 6 7 8 9 10 11 12 13 loige 27
.sort_descending() fn combinators(input: &str) -> u64 { 1 input 2 .split("nn") 3 .map(|batch| { 4 batch 5 .lines() 6 .map(|line| line.parse::<u64>().unwrap()) 7 .sum::<u64>() 8 }) 9 10 .take(3) 11 .sum() 12 } 13 loige 🤷 28
But iterator combinators can be "extended" 🤫 loige $ cargo add itertools 29
use itertools::Itertools; fn combinators(input: &str) -> u64 { input .split("nn") .map(|batch| { batch .lines() .map(|line| line.parse::<u64>().unwrap()) .sum::<u64>() }) .sorted() .rev() .take(3) .sum() } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 use itertools::Itertools; 1 2 fn combinators(input: &str) -> u64 { 3 input 4 .split("nn") 5 .map(|batch| { 6 batch 7 .lines() 8 .map(|line| line.parse::<u64>().unwrap()) 9 .sum::<u64>() 10 }) 11 .sorted() 12 .rev() 13 .take(3) 14 .sum() 15 } 16 .sorted() .rev() use itertools::Itertools; 1 2 fn combinators(input: &str) -> u64 { 3 input 4 .split("nn") 5 .map(|batch| { 6 batch 7 .lines() 8 .map(|line| line.parse::<u64>().unwrap()) 9 .sum::<u64>() 10 }) 11 12 13 .take(3) 14 .sum() 15 } 16 use itertools::Itertools; fn combinators(input: &str) -> u64 { input .split("nn") .map(|batch| { batch .lines() .map(|line| line.parse::<u64>().unwrap()) .sum::<u64>() }) .sorted() .rev() .take(3) .sum() } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 loige 30
.sorted() use itertools::Itertools; 1 2 fn combinators(input: &str) -> u64 { 3 input 4 .split("nn") 5 .map(|batch| { 6 batch 7 .lines() 8 .map(|line| line.parse::<u64>().unwrap()) 9 .sum::<u64>() 10 }) 11 12 .rev() 13 .take(3) 14 .sum() 15 } 16 loige 🤩 added by itertools 31
But... Do we really want to sort? 😕 loige 32
💡IDEA: Consume the iterator and, as you go, keep the current top 3 in a vec... loige 33
💡IDEA: Consume the iterator and, as you go, keep the current top 3 in a vec... loige 100 22 44 1 120 top3 = [] 34
loige 100 22 44 1 120 top3 = [] 👉 💡IDEA: Consume the iterator and, as you go, keep the current top 3 in a vec... 35
loige 100 22 44 1 120 top3 = [100] 👉 💡IDEA: Consume the iterator and, as you go, keep the current top 3 in a vec... 36
loige 100 22 44 1 120 top3 = [100] 👉 💡IDEA: Consume the iterator and, as you go, keep the current top 3 in a vec... 37
loige 100 22 44 1 120 top3 = [100,22] 👉 💡IDEA: Consume the iterator and, as you go, keep the current top 3 in a vec... 38
loige 100 22 44 1 120 top3 = [100,22] 👉 💡IDEA: Consume the iterator and, as you go, keep the current top 3 in a vec... 39
loige 100 22 44 1 120 top3 = [100,44,22] 👉 💡IDEA: Consume the iterator and, as you go, keep the current top 3 in a vec... 40
loige 100 22 44 1 120 top3 = [100,44,22] 👉 💡IDEA: Consume the iterator and, as you go, keep the current top 3 in a vec... 41
loige 100 22 44 1 120 top3 = [100,44,22] 👉 💡IDEA: Consume the iterator and, as you go, keep the current top 3 in a vec... 42
loige 100 22 44 1 120 top3 = [120,100,44] 👉 💡IDEA: Consume the iterator and, as you go, keep the current top 3 in a vec... 43
loige 100 22 44 1 120 top3 = [120,100,44] This is O(n*m) vs sorting O(n*logn) ⚡ * indulge me and let's ignore we could have used radix sort here... ** O(n) for very small m, top100 would be expensive! 💡IDEA: Consume the iterator and, as you go, keep the current top 3 in a vec... 44
trait TopN { fn top_n(self, n: usize) -> Vec<u64>; } 1 2 3 loige That's what we want for now, but can it be more "generic"? 🧐 45
trait TopN<T> { fn top_n(self, n: usize) -> Vec<T>; } 1 2 3 loige Makes the trait "generic" over any type T T is used as part of the return type of the function 46
That's a cool trait indeed... but I am sure we cannot implement it for "all" iterators, right?! 🤷 loige 47
Of course, we can! 💪 loige It's called a "blanket implementation". 48
impl<T, U: Iterator<Item = T>> TopN<T> for U { fn top_n(self, n: usize) -> Vec<T> { } } 1 2 // TODO: 3 unimplemented!(); 4 5 6 loige All types U that implements the Iterator trait producing Items of type T We implement TopN<T> for all types U (iterators producing T)! 49
impl<T, U: Iterator<Item = T>> TopN<T> for U { fn top_n(self, n: usize) -> Vec<T> { let mut top = Vec::with_capacity(n); for value in self { for i in 0..n { if let Some(top_value) = top.get(i) { if value > *top_value { top[i..].rotate_right(1); top[i] = value; break; } } else { top.push(value); break; } } } top } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 let mut top = Vec::with_capacity(n); impl<T, U: Iterator<Item = T>> TopN<T> for U { 1 fn top_n(self, n: usize) -> Vec<T> { 2 3 for value in self { 4 for i in 0..n { 5 if let Some(top_value) = top.get(i) { 6 if value > *top_value { 7 top[i..].rotate_right(1); 8 top[i] = value; 9 break; 10 } 11 } else { 12 top.push(value); 13 break; 14 } 15 } 16 } 17 top 18 } 19 } 20 if value > *top_value { impl<T, U: Iterator<Item = T>> TopN<T> for U { 1 fn top_n(self, n: usize) -> Vec<T> { 2 let mut top = Vec::with_capacity(n); 3 for value in self { 4 for i in 0..n { 5 if let Some(top_value) = top.get(i) { 6 7 top[i..].rotate_right(1); 8 top[i] = value; 9 break; 10 } 11 } else { 12 top.push(value); 13 break; 14 } 15 } 16 } 17 top 18 } 19 } 20 loige 50
if value > *top_value { impl<T, U: Iterator<Item = T>> TopN<T> for U { 1 fn top_n(self, n: usize) -> Vec<T> { 2 let mut top = Vec::with_capacity(n); 3 for value in self { 4 for i in 0..n { 5 if let Some(top_value) = top.get(i) { 6 7 top[i..].rotate_right(1); 8 top[i] = value; 9 break; 10 } 11 } else { 12 top.push(value); 13 break; 14 } 15 } 16 } 17 top 18 } 19 } 20 loige 51
impl<T: PartialOrd, U: Iterator<Item = T>> TopN<T> for U { 1 fn top_n(self, n: usize) -> Vec<T> { 2 let mut top = Vec::with_capacity(n); 3 for value in self { 4 for i in 0..n { 5 if let Some(top_value) = top.get(i) { 6 if value > *top_value { 7 top[i..].rotate_right(1); 8 top[i] = value; 9 break; 10 } 11 } else { 12 top.push(value); 13 break; 14 } 15 } 16 } 17 top 18 } 19 } 20 loige Restricting T only to types that can be compared! 👍 52
fn combinators_no_sort(input: &str) -> u64 { input .split("nn") .map(|batch| { batch .lines() .map(|line| line.parse::<u64>().unwrap()) .sum::<u64>() }) .top_n(3) .iter() .sum() } 1 2 3 4 5 6 7 8 9 10 11 12 13 .top_n(3) .iter() .sum() fn combinators_no_sort(input: &str) -> u64 { 1 input 2 .split("nn") 3 .map(|batch| { 4 batch 5 .lines() 6 .map(|line| line.parse::<u64>().unwrap()) 7 .sum::<u64>() 8 }) 9 10 11 12 } 13 loige 53
.top_n(3) fn combinators_no_sort(input: &str) -> u64 { 1 input 2 .split("nn") 3 .map(|batch| { 4 batch 5 .lines() 6 .map(|line| line.parse::<u64>().unwrap()) 7 .sum::<u64>() 8 }) 9 10 .iter() 11 .sum() 12 } 13 loige 😍 OMG, we added this! 54
OK, but you used a Vec there... I heard rustaceans don't like unnecessary allocations, right?! 🤷 loige 55
trait Top<T> { fn top(self, n: usize) -> Vec<T>; } impl<T: PartialOrd, U: Iterator<Item = T>> Top<T> for U { fn top(self, n: usize) -> Vec<T> { let mut top = Vec::with_capacity(n); // ... top } } 1 2 3 4 5 6 7 8 9 10 11 loige We want to replace these with an array... 56
trait Top<T> { fn top(self, n: usize) -> [T;n]; } impl<T: PartialOrd, U: Iterator<Item = T>> Top<T> for U { fn top(self, n: usize) -> [T;n] { let mut top = [T;n]; // ... top } } 1 2 3 4 5 6 7 8 9 10 11 fn top(self, n: usize) -> [T;n]; trait Top<T> { 1 2 } 3 4 impl<T: PartialOrd, U: Iterator<Item = T>> Top<T> for U { 5 fn top(self, n: usize) -> [T;n] { 6 let mut top = [T;n]; 7 // ... 8 top 9 } 10 } 11 loige 57
fn top<const N: usize>(self) -> [T; N]; trait Top<T> { 1 2 } 3 4 impl<T: PartialOrd, U: Iterator<Item = T>> Top<T> for U { 5 fn top<const N: usize>(self) -> [T; N] { 6 let mut top = [T;N]; 7 // ... 8 top 9 } 10 } 11 loige const generics syntax 58
let mut top = [T;N]; trait Top<T> { 1 fn top<const N: usize>(self) -> [T; N]; 2 } 3 4 impl<T: PartialOrd, U: Iterator<Item = T>> Top<T> for U { 5 fn top<const N: usize>(self) -> [T; N] { 6 7 // ... 8 top 9 } 10 } 11 loige 59
let mut top = [Default::default(); N]; trait Top<T> { 1 fn top<const N: usize>(self) -> [T; N]; 2 } 3 4 impl<T: PartialOrd, U: Iterator<Item = T>> Top<T> for U { 5 fn top<const N: usize>(self) -> [T; N] { 6 7 // ... 8 top 9 } 10 } 11 loige 60
impl<T: Default + Copy + PartialOrd, U: Iterator<Item = T>> Top<T> for let mut top = [Default::default(); N]; trait Top<T> { 1 fn top<const N: usize>(self) -> [T; N]; 2 } 3 4 5 fn top<const N: usize>(self) -> [T; N] { 6 7 // ... 8 top 9 } 10 } 11 loige 61
impl<T: Default + Copy + PartialOrd, U: Iterator<Item = T>> Top<T> for let mut top = [Default::default(); N]; trait Top<T> { 1 fn top<const N: usize>(self) -> [T; N]; 2 } 3 4 5 fn top<const N: usize>(self) -> [T; N] { 6 7 // ... 8 top 9 } 10 } 11 loige Do we really need this? 62
impl<T: Default + PartialOrd, U: Iterator<Item = T>> Top<T> for U { let mut top = core::array::from_fn(|_| Default::default()); trait Top<T> { 1 fn top<const N: usize>(self) -> [T; N]; 2 } 3 4 5 fn top<const N: usize>(self) -> [T; N] { 6 7 // ... 8 top 9 } 10 } 11 loige Allows us to avoid Copy 63
impl<T: Default + PartialOrd, U: Iterator<Item = T>> Top<T> for U { let mut top = core::array::from_fn(|_| Default::default()); trait Top<T> { 1 fn top<const N: usize>(self) -> [T; N]; 2 } 3 4 5 fn top<const N: usize>(self) -> [T; N] { 6 7 // ... 8 top 9 } 10 } 11 loige Note: This works for now, but it's not a perfect solution 😥 (e.g. what if there are fewer than N items?) 64
fn combinators_no_sort_const(input: &str) -> u64 { input .split("nn") .map(|batch| { batch .lines() .map(|line| line.parse::<u64>().unwrap()) .sum::<u64>() }) .top::<3>() .iter() .sum() } 1 2 3 4 5 6 7 8 9 10 11 12 13 .top::<3>() fn combinators_no_sort_const(input: &str) -> u64 { 1 input 2 .split("nn") 3 .map(|batch| { 4 batch 5 .lines() 6 .map(|line| line.parse::<u64>().unwrap()) 7 .sum::<u64>() 8 }) 9 10 .iter() 11 .sum() 12 } 13 loige 65
.top::<3>() fn combinators_no_sort_const(input: &str) -> u64 { 1 input 2 .split("nn") 3 .map(|batch| { 4 batch 5 .lines() 6 .map(|line| line.parse::<u64>().unwrap()) 7 .sum::<u64>() 8 }) 9 10 .iter() 11 .sum() 12 } 13 loige Slightly different syntax 🐟 Phew... we did it! 😮💨 66
Which one do you think is faster? 🧐 loige Itertools no_sort_vec no_sort_array 1. 2. 3. 67
Which one do you think is faster? 🧐 loige Itertools no_sort_vec no_sort_array 1. 2. 3. 37.517 µs 33.284 µs 32.957 µs BTW, is awesome! cargo bench ⭐ 68
But let's talk more about const generics, what else can you do with them? loige 69
struct Point<const D: usize>([i32; D]); fn make_2d_point(x: i32, y: i32) -> Point<2> { Point([x, y]) } fn make_3d_point(x: i32, y: i32, z: i32) -> Point<3> { Point([x, y, z]) } fn make_4d_point(x: i32, y: i32, z: i32, w: i32) -> Point<4> { Point([x, y, z, w]) } 1 2 3 4 5 6 7 8 9 10 11 12 13 struct Point<const D: usize>([i32; D]); 1 2 fn make_2d_point(x: i32, y: i32) -> Point<2> { 3 Point([x, y]) 4 } 5 6 fn make_3d_point(x: i32, y: i32, z: i32) -> Point<3> { 7 Point([x, y, z]) 8 } 9 10 fn make_4d_point(x: i32, y: i32, z: i32, w: i32) -> Point<4> { 11 Point([x, y, z, w]) 12 } 13 struct Point<const D: usize>([i32; D]); fn make_2d_point(x: i32, y: i32) -> Point<2> { Point([x, y]) } 1 2 3 4 5 6 fn make_3d_point(x: i32, y: i32, z: i32) -> Point<3> { 7 Point([x, y, z]) 8 } 9 10 fn make_4d_point(x: i32, y: i32, z: i32, w: i32) -> Point<4> { 11 Point([x, y, z, w]) 12 } 13 struct Point<const D: usize>([i32; D]); fn make_3d_point(x: i32, y: i32, z: i32) -> Point<3> { Point([x, y, z]) } 1 2 fn make_2d_point(x: i32, y: i32) -> Point<2> { 3 Point([x, y]) 4 } 5 6 7 8 9 10 fn make_4d_point(x: i32, y: i32, z: i32, w: i32) -> Point<4> { 11 Point([x, y, z, w]) 12 } 13 struct Point<const D: usize>([i32; D]); fn make_4d_point(x: i32, y: i32, z: i32, w: i32) -> Point<4> { Point([x, y, z, w]) } 1 2 fn make_2d_point(x: i32, y: i32) -> Point<2> { 3 Point([x, y]) 4 } 5 6 fn make_3d_point(x: i32, y: i32, z: i32) -> Point<3> { 7 Point([x, y, z]) 8 } 9 10 11 12 13 struct Point<const D: usize>([i32; D]); fn make_2d_point(x: i32, y: i32) -> Point<2> { Point([x, y]) } fn make_3d_point(x: i32, y: i32, z: i32) -> Point<3> { Point([x, y, z]) } fn make_4d_point(x: i32, y: i32, z: i32, w: i32) -> Point<4> { Point([x, y, z, w]) } 1 2 3 4 5 6 7 8 9 10 11 12 13 y2020 - Day 17: Conway Cubes loige 70
let p5d = Point([1, 2, 3, 4, 5]); fn some_func() { 1 // ... 2 3 // ... 4 } 5 y2020 - Day 17: Conway Cubes loige No need to specify the type, Rust will infer Point<5> based on the length of the passed array! 71
v...>>.vv> .vv>>.vv.. >>.>v>...v >>v>>.>.v. v>v.vv.v.. >.>>..v... .vv..>.>v. v.v..>>v.v ....v..v.> y2021 - Day 25: Sea Cucumber loige Sometimes you have to handle grids of variable sizes. README example (10x9) 72
.v.v.v>...>vv>v>>>.v>..v>.v.>.>v>.v.v.>>v...>.>....>.>vv>>>.....>>...v.>>v..>..vvv.>v...vv...>..>....>.>.>.>vvv....>..vv>v....>v...>>....v. >.v>..v.>>vv.>>v...v.>.>..v.>.>.>vvv..>>>.>...>v>.>>v....>>>>...>v.v>.v>....>>>v.>>>....vv.....vvv.v.v..>.>..v>>.>.v>.>v>.vvvv.v..v>>..>>vv .vv>>...v>..v..v>v.>vvv.v.v>>.....v>>.......>...v>.v>.v.vv.v.>v>v.v......>>......>.v...v........v.v........>.v.vv.>>.v.>>.>.>...v....v>>>.. .>.>v.>vv.v...v.>>v>.>v..vv>..v.v.>...v....>vvvvvv>>>v..vv.v.v>>.>>.>>v>v>>..>.v...v.v.>v..>...v.>.>>.v...v>..v...vv.>v.....vvv.v>.v>..>>v. ..>.....v.>>..>>.v>v.>.>>.>..vv.v>>.>..>.>..v>>...>.>>.vv>>>..>>>>.v.>....>>.>..v>>vv>.>>v>vvvv>vv..v.v.>.v>..v>.vvv>>.v.......>>.>...>>.>. v...>..>..v>.vv.>>.>...>>....v.......v>...v.vvvvv>..v...>.v.>.>>v>v.>....v>...>...v.>.vv>......vv>.v>vv>>....v>.v>.>..>v.v..>>>.>>>..v..>vv v>v>.v>..v..v.>..>...>v.>..>.>vvvv...v.v>v....>.>v.vvvv....>...v.v..vvvvvv..v.v..v>v....>v....>v.>>.v>.>v..>...v.vv...>v>>..>.>.....v.v..v. .......v.....v>v.vv.>.v>.>>.>v.....>>..v.v.v>v>.....v...>v.vv>>.vv>>>>.>>.v.>v>..v.v..>v.vv....>>.vv.>v...>>v....v.v.>.vvvv.v....>v>>>>v.>. v>.v>..v...vv.>vv.v...v.v>.>........>.vv>>..........v...>vv....>.>v>v..>..>>>v.>>..v.>.>...v.v.>..v>>>..>v.....v.>>>>...v>>v...vv>..>>.v.>> .v>>>>>>v.>.>...>.>>.>.>>v>.........v..>.v>>>v>.....>...>>.>.v..>.vvv.>..v.v..>.>..>v>v.>v......>>...>>v.vv.....>.>...>.....>v.v..>>v.vvvv. v......>.......>>..>.v.>..v..>>v..>>......v>v.vvv.>...>>>...v..v>vv.....v.v>v>>v..v.v..v.......v.>v>.v.v..>.>..>v.v>>>v..v.>.>.>>v.>..v.v>. >.v..>>....>.v.>...>>>..>.v..v>v..>>>.v..v....vv>vv.v.v..v...>>..>......>>..v.....v.v>>.v....v>>....>..>v.vv.>.>..v...v>>.>.>v.v.vv>.v..v.> ..v...>...v..v.v...>...>.v..>...v...vv>..v....v>>>v.v..v.v>v..>v..v..v>>vv.v>..v..v...>.......>..>.>v>v..>...>v.....v..>v>v...v>..>.>...vvv .vv>.>.v...>>...v.>.>v.v.>>v..v.>v.>>vv.v>.>..>....v.>v>vv>..v>v>v.>>v>v.>...v>vvv..>>.v.>v.>vv.>..v>...>.v..>.>>>v>>...v>.>>v..v....v>v..v ..>.>>>...>........>.vvv>>.>v..v.>v..v..>v.>>.>.v..>.v...v>>.>v..vv...v.v>.vvv...vv>vv>v>.>vv>.>v.vv..v.v...v.>>..v...v>...v..vv..v..>.>>>> ..>.>.>v.v.>.....>vv.vvv>.>..v>>>v.>vv.>.v.>.....v>>.....>v..vvv....v.>.v>.v.vv>v.>vv.v..>v>>...v>v....v>>v>....v..>vvvv>..>v>.v..v.....>.. .vv>.....v>.>>>.>>v>>>v>>>v>.v>>.>v..>>v.vvv...>vv.v.v.v.....>>vv..v.>>>>v.>....v>v.>..>..vv>>>....vv.vvvvv>v....v...>.>.vv...v...>vv...>.. >...v.vv.vv.vvv..>v.>.......v...v.>v.>..>.v>..v...>v..>..>v.v..>.v>.>>.v>.>v...v>>.>v.v.v.v>.>..v.>vv.v>>>.>vv.vvv.>vv>>v>..v>>.vvv>v..v.v> >v.>...>v.vv..vv>..v.v..>..v.>v>>>..vv...>.>.v.v...>>.>v.vv..>.v.>>.>.>.v>..>.>..v>..v>>.v.v.v>.>...v.v.vv.>>>.v>...v.v>..>>..v.v>vv>vv>>vv vv.vv>....>..>...>>..v.v..v..v....v.>.vvv>>.v.v>.>.vv.>v......>vv>>.>>.....>>....>..v.v..v.v...>>v.>>>v.....v.>......v>v>v>>.v.vv...>.v.... .>v>....vv.v>>...>>....>>>.>.v>...vv.v.>vv>.....v>v.v....v..v.>v>.....>...>v>>....v.vv.v>>.>..v>.v.v...v..>..>>v.v>....v.>....v>......>v... ..vvvv>.>.>.v.>.vv....>>>v..>..v..v>vvv.>v.>>.>v.>.vv>vv.>......v...vv>v..v.v.vv>v.v..vvv>v..>>...>..>.>....>>v>....v.>vvv>>..>>>..v..v.>.. >.....>>..v>.vv.v>..>..v.>vv>>vv>.v>v..vv......>....>.....>.>v.vv.vvv.v..>.vv..>>...>vvvv>..>..>.>>.>v.vv>...>>vvvv.>.v.v...>...>v>..>v.... .v.>v..>vv.>v...>vv.v..vv>.>>.......>v>.vv..v.vv>v..>.>vv.v>>>.>>v>.>...v...vv.>>>v...>>..v>v>v.v.v>..>.v....>.v.v.>vvv.v.vv.>.v..vv.>>v>>. ....v...vvv>>>.>>.>v>...>.>v.v.>.vv>...v...>>v.v.>.v>..>...vvv....v..vv>vv>>>..>.>.>v....>..v.vv.v..v...>>>v..v.>.....v>>v>vvvv.>.>.v.>vv.. .>.>v..v>.v.v.v>v.>.vv...vv.>.>v>....v>>v..>....>>>.v>v.v>>..>.>vv..>.>..>.>>.........>>>>..>...vvv>.>.v.>v.v>...v.>vv..>.>v.>>vv.>>>v>.vvv >..>>..>.>>>vvv.>....>>v.>..v>v>v....vv.>.>>>v..v..v>.v....v>>...>>v...vvvv>>>>.>.....v>v.v.v..>v.v..>.v.>v>>....>>>v>.v>v.>.v...>>>.>vv.>> ...>>..>..>.>v.v..vv>.>.>vv.v>>.>....>.v>..>.v>>.....v.v.v.v..>...>>v.>.v.v.>>.>v....>..v..v>>..>>.>.v..>>..>vv..vv>v.v.v..v.vv.vv>....vv.. .v.v>..>.>.v..v>>....v>....>v>>>....>......v..v.......>vvvv.vvv.v..>.>..>.>>v.v..>...>>vv>.v..v.v..>vv>..>>.>v.>.v...vvv>>..>.vv..v.>v.v>v> v>.>.>.v>>v.>>v>.>.vv>.>>...>..>>>.v....>>>v>.v>v.>.v.>..>vvv>.v.>>....>v....v.vvv>..>.>.vv>>..>>v...vv.>.>>.v..v>.v.>.v..>.v>.v....v...>.> >vvv>.v>..>>..>.vv>>>...>>v.>v..>v....v>vv.>..>.v.>....vv....v....>....vv.v...vv>>>.>..>>>.v....>>vv.vv>vv>>.v...>>>v.v...v.vv..v>.vv..>v>. v.>...>>..>>v>..v.vvvv..>>.v>.v.>.vvvvv>v..v.v>....v..>>.>>..v.>.v>..v.>.v.vv>.>.>v.v....>v.vvv>>>.v>>.vvv..v..>.>...>.>..>.>...v..>>v..... .>v.>>v>..vv.>.vv.>>...v.v....>>>v....vvv>.v.>v.>v.vv.>.....>..>>.vv.v.v.>..v.>...>>.>.....>>.>........v>...>.>>>.>v.>.v.>>.....vvvv.v.>v>. >..v..>.>>>..>vv..v..>.v.v....v>...v>....>>...>v.>v...v..v...>.v>.>.>.vv...v....>>....vv.v>>....v.v.v....>v.....>.v.v...v>..>>..>..>>..>>v> .>vvv.v>.>vvv>>vv>v>v..>...>vv.>..v>.....>.vv....>>...>>.>>>v..vv.>>.....>>.v..v.v>>.vv>..v.vvv...>>.>..v.v>.v......v...>.>..>..>v....vv>.v .>v>...>...v..v>.v..v>v.v.>>.>vvv...v.>..............vv..vvvv>.>....>.>>..v.vv.>>.>.vv>...>>v.>.>.v..v>..v..>v...>.>..v.......>.>v.....>... ..v.>v>vv....v>>.v>vv....>.v>.>v.vvv>vv>>vv>..v>.vvv>.v.>v.>....v.>..v>v........v.>>>v..>>.>v>v...>>vv.>.v.>>.>..>..>vvv>.v.>vvvv.v>v.>v..> .vv>>v......>...v>.vv>..v>>.v>v>>v>...>.>>.>.>...v...>>>>>vv>.>v....>v..v>>.>.vv>..v>>v>.v..v.v..v>......>.vv>....>v>..v>>.>.>>.v>v>v>>>v.. >v.v>.>...vv.>..>.v.>>.vv....>.....>v.v..v.>..>...>.v>v.......vv.v>.>vvv...>..>.>....>v...>..v...>v.......vv..>....v...>v.....>>v.>vv>.v.v> v>..vv>.vv.v...vv...>......>v..>>.v>vv.v>>v..>v>..vvvv..>.>>.v..vv>.v>.>......>......>vv.v..vv>>..>..v..>v..>..>...>...>.>.........v.vv>v.v .v>.>.......>.v.>.v..>>.>.v>...>..vv......v.v...>..v>>v..v..v...>>vv..v.v...v.v...v>vv>..v.>>>v.v.v>v..>vv>..v..>>>>...>.>..>.>>>.>>vv>>..v .>..vvv.v>.v..>..v>>..v>v>>.>.>..v.>vv>.v.>>v>v.vv.....v.>v.>>>>vv>>>..>>...vv>v..vvvv>>>..v.v.>...v.....>>...>>..>.>.>v..>..>...>..v.v>..> vv..v>.v....v..v>.......>vv..>vv>...vv...v>>vvv>v...v.>v.v>v.>.v.v.>.>.>....v.>>>..>.v.......vv..v.vv>.v...v...>....vvvv>....>.v..v.>v..v.. >.vvv.>v....vv>>v.>..>.vv.>v>.v.>..>>v......vv>>>vv.v..vv.v.vvvvv>>.>>.>>v...v..v.>..>...>v>.v.v>vv>>.v.vv>>..v.>>>...>>.>v.v.>>..vv>..>.v. ..v.v>..>v>..>.......>>.>>>v..v.>....>.v..v>...>v>v.>.v.>.v...>....vv..>..v.>......v...>vvv>..v..v....v>...v.>.v......v>vv..>.vv...vvv.>vv. vv......vvvv.>>.>v>.>.v>.vv>v>.vv>....v....v.v.>vv>vv.>>.>.v>v...v.....v.>..>....v.>..>..v.....v.v>>v>.v.>..v>..vv.v.>>...>.vv>....>v.v>>.. v>.>>.>.....vv.>v>>.v>..>v.>..>>.v..v.>.>.>>.vv>..v..vv.>>v..>.>........v....v>>v.v.>v..>.>v......>..>.>.v.>...v>..>v>..v.>v>v..>vv>..v.>>> v..v..>...>.v..>>...>.>v..>v.v.vv.v..>..v..>.v.>>v.>..v.>..v>..>.>vvv..v.>.>>.v.v..v>.>v.>..>v..v>>v>>......vv.>.>.v.>>v......>v...>v...>>. .>..>...>...v.....>.....vv.v.>v.>.>..v....v>>...>.>.v..>>>...>v.v..>...>vv>..>v>.v.>>.vvv>>v>v.......v.vv...>>>..v...v.>v..v.>..>vv>..>.v>. ....>vv.>..>.>>.v..>.v.>..v..>..v.>>.>v..vv.v>>>v.....>>...>v>......>.>v>.v.>.vv>.vv>.v.>>..v>..>vv.v..v...>vvvv>>..>..v......v>..v.v.v>.>. ....vv>....v....>...v>..v>.>.>.>v..>.v>.......v>..v.vvv.v.>..v.>v>.>vv.v.>vv>.>>v.v..v.v...>vvv.......>v>v.v..>.v>.v>vvvv.>.>>>.>..vv.>v..> ..>.vvv>.>vvv>>>vv.>..>v.v.vvv>..vv.....>v>>..vv>.....>...>.v>.v>>.>.>vv..v...v..>.>>..>>.>.vv>v>>>vv....v>.>>..>..vv>.>>..>v>.v.v.v..>...v .>.v>............v>v.v......vvv>.vvv>v.v.>vv..>>....v.>.vv.vv..>..>>>>v.....>.>.>..v.>.>..>.vv.v.v......>>.>>>.>>.v..>v>v...v...v>...vv>.>. >>.v....v..>..v>>v....>...v.v....v.>..>.v>v.>v>.>>v.....>.v.>>.>>>..>.v.v.>>vv>>.>..>>v...>.>.v.vvv>>vv.vv>.v.>.>.>vv.v..>v>.>.vv>>>v..v>.v >v..v.v.>..>>>>..>>v.v>.v>..>>....v.....>..>.>v>...>>.v>....vvv>....>v.>.v.>.>v>.>v>>.>v>v..>.....v>.vv..v>>...>>v....>v..v>....>...vvv.v>. .>.v.....>..>.>vvv.>v.>vv.>..v..v.v.>vv>.>..>.>>>.....>v......>v.>....v..>.>..v>v.>..>.>v..>.v.>v>v>...v.v.>.v.>vvv>vv..>.v..v>..vv..>..v>. .v>.v>v>.v..v>.v..v.>............>v.>..>..>>.v..v>v>vv>>.>v.>>.v..v...v....>.v..>vv.>.....>.>>.vvv..>>..vv>>v>.....>>.v>...v.vvv>>..>..v.v> v...>..>...v.>>.v...>..v>v...>vv.v..>vv>..vv>>.v..vv.v>v.>>..v>v.v..>.......v...v.v>...>v.v......v.vv>...v.>..>vv>v.v....v.v.vv.vv.vvvv.>v. .>.v>>....>....vv..>vv>.>..vv.>>...>....>vv.vv...>.vv>v...>>..v...>..v....>v.vvv...v>>.>>>>>v>..v>>vv>vv.>vv..v...v.vv..v>v.>.v.v>..v..v.>v .>.v.v...v.....>..v>..v>.vv.v>...vv.....>v..>..>..>v.>.v...>.vv.....>.>.v.v>v....>..>>.vv.>vvvv..>>>.v...v...>v.vv>>.v..>v..>..>>.>..v>v..> >..vv>>v..>.v>>>v>>.v..vv>....v.>vvvv.>...vv...>.v..>v.>v>.>v>v>>v.>.>...>>>.....v.v....v>...>..>.>v.>.vv.....>.>>vv.....>......>.v..>v>.>. v.......>>.>..v>.v.>.>v..>>.>.>vv..>v.v...>.v>..v....v..v..>.>>...v..v>.vv.>v>>.>....>vv>.v.v.>..vvv.v.>.v>.v>v..>.>>.>.>..>.>...vvvvv.v>.. >..v.v>.>>v.>>...v.>v.....>.v.>.v>v.>v>.vvv>.>>..>v..v.v.>...>v....>v.v.v>>...>.vv>.>v.vv....v>..v>>v.>.>..v>v..>v>..>.>>.v>.>..>..>..v.... .>vv.>.v>>>.>.>.v>v.>..vv>..>>>.>>...v.....>v.v..>.>.>>.v.>.>v>.>v.v..vvvv>.....v.v..vv....v.>...>.vv.>>v.....>.>vv>...v....>v..>v..vv.>>>v v..>>>v.>..v>.v.v.>.>..>..>>..vv.vv.>.v.v..>v>v.>>>.>.>>.>>.vvv..>...>>..>.>..vvv>.>..v.>.>.v>v>.>v..>.>.v>....v..>..v.>v.>>.v.v..v>v..>v.. ....>v...>....>.v>>vv.....vv>..vv.v....vvv>>...vv.v.v.>......v.v>>v..>.v>..v>v.v..>....>....v.vvvv>v..v>v>v>v.>>v....v.>vv>>v>vv>>>.>..>.v> ...>>>.v.v.....v>vv>>v>.>..v.v>v>....v>>vv..vv>v>..vv...>.>v>.>v..v...>.>vv..v.>.v..v...>...v>...v.vv>vv>..v....>.v....v.v>..>.....v..v..v. .>vv.v..v>..vv....>.>>>>..>>>>..v....>.>v.vv.v.>>.>vvv..vv..>vv.>>v>>v.v..>.....>>v>..v..>>v>vvvv...>.>v>..v..>v>...>>.>vvv.v.>vv.>..v>>... >>.>...>v.>vv>v>.>.....>.vv.>.vv>.>>.>.>...........v>.>..>>.>.>>..v.v>>v.vv>v>.>v.>..v>vv>.>>.v>>.>.v>v.v..>v.v>.v>v>>.v.>v.>>vv...vv.vv... >vv>>.>...>v.>v>...>v>.v.>...vv....vv>v>.>..>.v.v.vv.v.>v......>..>.vv..v>.>>.>v>...v.vv..v...>vv.v.v...>>.>.>.v..v..>.vvvvv>>>>v>vv.v.v... >v>>>.v>..vvvv..vv>...>.>.v>>>..v.v>>.v..v>.v.....>v>>.v..>..>.....>v....>.>..>......>v>.>.v.>..v..vvv>>v.v..v>..v.v.>>>>>>>vvvv.vv.>vv..v> ..v..vv>v>v...v...>.vvvv.v.....v..>.>..>....v.....v>.>>..v.v.vv..>....vv>vv>v>>.>>v>>.>.vv.>..>>v.v>...v>.v...vv.>v....v.>>...>v.>.vv.>.vv. .v>v..>vvv.vv>v>>>..v..>v>.vvvv.>.>.vvv>.>..vv.>v...>...>v..>..>......v...>.v..v>>.>v...>>>>.....>>>..>vv.>>>v.>v..v>>vv.>....>..>>vv.>.>.. v.>...>vvv>...>.>.v>.v..v..v>.v.>.v>.v...vvv..>.>>v>...>.>>v>>.v.>v...>>.v.v..vv..vv.>.>v.>.v.>>>.>.vv...v.v>.v.>>>>>>..vvvv..>....>..>.v.. >v..>v....v.v....>vv.>.>.>v>.>v>v.v>>>.>v...>>>.v..v.v.v>v......>vv.v..>......>v>.v>>.vv>>>...vvv.v..>.>.........v.vv>.>vv.vv>v.v.>.>vv..v. >.v>.v.v>v..vv.v>v>.>>....vv..>.vvv>v..>>>>vv.v>....>.vv.>...>>>...>v>.>...v..v>v...>..v...>.v..v>.v...v.....>vv........>....v>v..v.>..>v.. >...>v......v>.>v...>.v...>>v.v>..>v...v.v..v>.>.v>.>...>vv.v>vvv.>..>..>...v...>>..>.>v.>vv.v..>>.v.v.v..>.v>..v.>..v...>>v.>v>v.v.v.>..>. ..v>.>>v>>..>..vv>>..>.>>vv..>..vv....v.>v>.....>v>..v.v>.v..>...vv..v.>>vvv...v>v>.>.v.>>>.v>...v>.>v.v>v>..>...>....>>>v..v..>>...>.v.... ....>...vv.>...vvv>v..>vvv>>..>>>>......>>>.v..v>vv>v>.>....>.....v.v..v.v.....v.v..v.v..v>.>v>v>.>.v.>v>....vv.v..>.vv..>..vv>.>v.>....... vv.>.>...>vvv.>v.>v>.>.>.v..v>..>.>>.v>.v>.v.v..v>v...v..>>.>>.>.>....v.>..>>vv>....>..>>...>>v.>.v>>..>>...vv.v.v.>>..v.v...v.v>..v.v..vv. .>v.v..v.v.>.v.....>.v...>.vv>.>....vv.v.v..v>.v>v>>>.v..vv.>vv.v....vv..vv.>>>v>.v.......>.vv.v..>v>v...v...>..>vv....>.>.>.>>v...v..v>>.v ...>v.>>.vv...>v.v.v>...v.>vv..v.v...>>>>..>.....>.>v.v.v>.v.v>.>>.>...vv..v....v>.v.vv..>.v>...>>..v.v.v.v>.v.v>v.>..v.>v..>>..>vv.......v >....v..>..vv.>.v>..>.>.>.>>v..vv.>vv...>>v.>.vv.v.>.v..>vvv>.v...vvvv>vv.>>>.>>..v.>v>>>..>>.>.v>>>v>>>..v>>.>.v.>...v.....v..>..>>.>v>..v >..vvvv>>..v>v>......>...v>...>>>...>.v>.>.v>.>>....vv..v>>>vv..>>>v.v>.>.v..>.v>..v>....vv>.>.v.....>v>.>.>.v>v.>.>v>v....v.>...>.v....... .v...v.....>>v.>vv.>v.>>.>.v>>.v...>>.v..v.vv>>.v...>>>v.>v>>..>>...vv.v>v.>..>v>.>v>>..>>.v...>..>.>..vv.....>>.>.vv>v>>.>..vv>.v.>v.>.v>v .vv>...v.>.vv.>>...v..>.vv...>.v.....>>..v..>v.>.>...v>..>v.v>.v.>v....>..>..>..>.>.>.>.>..>.>.>.>..v..v>>v.>.v>>.....v..>.v.....v>..v....v .....v>v..vvvv...v>..>.v.vv.>.>.......v.>..v..vvv.....vvv..>...>.v.>v.>v..>....v>.>>...v>...v>..v>v....v...v.v.>.>v>...v.vv.>...v.>>v>v>..> >v...>...>..>.v.>>>>.>v.vv>vv>.>.>.......v>>v.>vv...>>.>..v..v>vv..>.>..>v..>v>>>.v>>v.>.>..>...>>..v..v>>v.>vv>>.vvv>..v.>vvv..>..v>vv..vv ..vv.>v...>>........v.....>>..>>..>........>>vv.>.>.....vvv.vvvv>>.>..v.>v>...v.v..vv...v.v..v..>>v...v.>>>>...vvv>>>v>...>vv>v>.vvv..>v..> ..>.........vv.>....v>>.>>vv....>>vv....>..>.>...v..vv.v>..>v>.>v>>.>>>...vv>.......v..v>v>.>.>vvv.>...>.v.>>v>.v>>....v..v........vv.>>.vv ..v.>>v.v..>..>>.v..>.v>>>...>..vv>v.>...>...v.vv>.>.v>..>v.vv.......v...vv>.>vvv.>...>>.v.vv...>..vv..v>...v...>>>....>.>v.>.v...v......vv >vvv>.vv..>>.>....v..v>>>>v.>.>v....v.v...>>>..v.>..>v..>.vvv..v>.v>.v......>.v.v>>v.v.>.v...>.v.>vv.v>v..>..>>>.>v>>.vvv>>vv>.>v.>..vv.vvv >>>..>v.v>.vv.v>v>vv...v........v>.>.....v>v..v.>>>.>v..vv..>....vv.v>..v....>>>>vv...>v..v>.v.vv.>..>vv.vv...>>..>>.....vv..v>>..>....vvvv v>......vv>>.vv..v>v.v>>..v...>.v.>...>>..vv.>...vvvv.>v.>...>v.vvvvv..>>.....>v.>....>....>.>.>v..>.v.vvvvv..v..>vv.v>.v.v...>v.>..v>..>.. .v>>>>..vvv>v.vv>.v>vv..vv.v.vv.>>v>.>..>.v>v....>....v>>>.>.v.vvv.>>...v..>v>...v.v>>v>>v.v...v.v...vvv>>v.>.>...>v..>....>>.>..>.vvv>.v>. >>.v...>.v>...v>v..v.vv.v..v.v.>...v>v.>.>>.v.>.v>>>.>>.>..>....v..v>>>.v>>.>..>>.>.vv.>>.vv.>>>v>.>>.>.v....v>....>..vvvv....v....v.v.v>vv >..v>vv>.>v.>.....v.>vvv>..>.>.vv>>>..>.....>..>v>.v...>v..>...v...vv..v>>>v.>>..vv>>..>.>>>v.>..>v...v.v..>.>..>.>>..>.v.v>....>...v...v.. >.>.v...v..vv.>>>vv.vvv..>...vv.vv>...v.v>>>>.>.>>v.>..vv...>v>>v>..>..>vv..vv>>.v>>...>.>v...>..>.>>>.......>.>>.>.>....v.v.............>v ...v>.vv..vv...>v>..>>.v..vv.>.v..v..>..>>.>vvvv.vvv.>>vv>v>.>>v>..>...v>...v...v>>.>..>.>.>v>.v..>>......>v...>v>v.>>.....v>..>.>>>>v.v.>> .v..vv>....>>...v>.v.v.>.>>....>..v>>.v>v..>......>v...v.>.v......v..>v..>....v.vvv.v..>vv..v.>..v..>>>....>>>>v.>.....v>>.>..v..v>v.v..>.. v>......v..v..v>.....>v>>.>v>v>.>>v>v>v>>...>.....v>.v>...v...v.....>>...v...>.vv..vv..>.>>...>v.>.vv>..v.v>..vv..vvvv.>v..>....v>.>..vv.>> >.>..v>v..>.vv>>.v>>>>>v>....v.v.>vv..>>...v>v>v.vv>.>>>..>.>v.>>v......>>.>v..v>.vv...vv.v.vv>.>....>.>v...>.v..>.>..vv>..>.vvv.>>>v.v.... >.>.vvv.v>.>vvv...v.>..>.v.>.......>.>....v..>..>...>v..>v....v..>v.v>v.v.>..v.vvvv>>v>.>>.>>>...>..>v>..>v.>v.v..v>>vv.>..v.v>vv...vv>..v. .v>v.v..>...v>v>.>vvv.>.v.....v.>.>>..v>v>.v.>.>....>.v..v.>v.v>.>.v.vv..v>>v>vv....>>....>vv>v>v>>.v..>.vv..>>>......>>>>..v>v>v>.>>..v..v ..>v.vv..>>v>v.v.......vvvv>vv.v>.v...v>v>>.v>.>.v>..vv...>v.>...v.>v>..v>.vv>....>>..v.>.>vv.vvv.>....v...v>.>..vvv>.>>vvvv>>v....>..>>.>. .v.v.>vv>.>...v...vv.....v...v>>.>v.>vv>.>>....>>...v.vvv..>>..v.>vvvvv>..v.>....>v.>.......v.>.v.v.>..>>v>vv>>vv.>v.>v>>..>.v>.vv..v..vv.> ...vv.v...vv....>..>..v.>>v>v.>.v...>...v>...v>>v...>v.>>.v...v>>v...>..>v..v>..v..>.v>.>.>..v...vv>v.>.vv>>>..>>>vv.>..vvv..v.>.>..vvv>.v. .>>.v.>.>..v>..>v>..v>.v.v>>.vvv..vv.>v.>>.>.v.vv.v.vv>.>.vv>.>..v>>.>.v.>v..>>v...v..v>>.>.v>.>.>v..v.v.>>>vv.v.>...v..>v.....>vv..v>.>>>> .>.....>v>>>>....v..>>>vv...v.>>>v..v>vv>>.>.v.>.>v>.v>v..>..v.v...v..v.>.>>...v.>>v.v>vv.v..>.v>.>>vv...v.v...>>....v.>..vv..vv....v>..... ..v>.>v..v>...v>.>..>...vv>v>vv.>...vv>>..v>.v.>....>....v..>v>.>...v>>vvv....v.v..v>.vv.v.vv.v..>v>>..>...>v>>....v.>>..v.>v.>v.>>v.v.v.v. .>.v>>>v>.v.vvv...v>....vvvvv>>v.vv>>>>>....>.....>>...vv.>vvv..>.v..vvv.vv>vv>..vv>>vvv...>.>.>.>...vv>.>v.v.v..v>v..v.>.v>>.>vv.>...v.v.> .>....>>vv.>>>>.>v.>.v..>.>>.vvv>..v..v>..>>.v>.>>>.v.v>>vvv>v...vv.vv..>....>.v..v.>.v>..v....v..vv>v>.>..>..>>>.>>>.v.vvv.v..v......vv.vv .v.v>>>v.>v.>....>..>.>v.......v>>........vv.v>>>...vvv.>>.>.v.>v.v.>...>v.v.....v.v.>vv>.>>v>>..v>>>..v.v..v......>.v>.>.>>v.v.v.vvv>vv.>. .>..>....>>.....>.>...v.v....>v>>>v.>.v>.>vv..>v>v>v.>>>>>>v.>>>>>.>.>>.v>......v.v.v.v...>.v..v...>..>>>>>.>.>..>.vv..v>.>..v>.v.v....v.>. ..v>>>>.>>>>....v>v..>>vv.>>..>..v>..vvv>.>..v.>...v>>..>.>>>..vvv.v..>.>.vv>...>vvvv>vv>>>vv..>...>v.>vv....>v.v>..>vv....>v>..v>.v.>v>>v> .>>.>>>v.>.v>.>.v>.v.>......v...>.v.>..>.vv.>v..v>.v>.v..v...>.vv.v>>.>v.v..>v.>...>>...v.>>v.>>..>v...v.>...v>.>.v..v.>.>....v.>>>>v.>v.>. >vvv..v.v>>..>..v.>vv.vv>..>vv.v.>...>v..v>>....>>...>>.>>....>...>v>..>>>..>...v.>v.v>.....>..v...>vvv.vv.>>.>v>v.v>v..v>...v..>>.>..v...> >>.>>...>.>>>..v>>..>v..vv>>>>.v.>>v..vv..>.>..vv.....v.v.v.>..>>>....v.v.>v>>vv....>.....v>v..v>..vv...>..>>v..vv...v.....>vv..v>.>..>.>.. ..vv>.v>.....v..>.vv>>...>v...>.v.v>>>........>vvvvv>>.>...>.v.v..v....>.>v>>.v.vv.v..v.vv.>.>v>.>v.>..vv...>>..>.....v...>>>v..v..>.v>>v>. .vvvv>.>...>>.v..>...vvv>vvv..vv>.>v>.....vv.v..v...v.....>>>v.v>v>>.>v..>>>..>.>v..vv...>vv>.v.>.v..v.>>.....>v.>v>>.vv..v..>..>.>.v....v. >v>>v...>..>.>>..v..vvv>...>>....>.>>....vv>...>......>..>>v...vv..>>>>>.>v.>.>.vv>>.>>vv....>.v>>..v>>...>v..>...vv..>.>..vvv...>.....>.v. >..v>.>..vv...v.>>>.v>>.>....v.vv.>..>...>..v..>v.>vv.>..v..>.v.>...vv...v>>..>>vvv...>.>v.>.vv.>v..vv.>>vv.>>..>vv>.v.....>>...v..v.vvv.>> v.v..vvv>...>v......v....>..>>>.....v>v>>>..v.v..vv.>.>>>>.>.v.>....v.>.>v>vv>vv>v..>.>.v.v>.....>..v>>v...v.....v...v.v.vv>>........v.>.v> .v>>...>>v>.>...v.>>>....>v>>v.>.v.>>v.v>.>>...>.v.v...vv>v....v>v..>>.>v>.>..>vv.v>>.>..v>>v...>v>>>..v..>v>vv.vv>............>v..>vv.v.vv >.....>vv.>...v>vvvv>vvv..vvv>.v.>...>v..vv>vv.>>>.v..v>v.>..vv.v.>>v....v...v.....>.v.>.>..>.v>..>v..>>>>>>>v..vv>.v.v>v.v>..>....>>>v>.vv v.>.v>v.v>...>>>..v>..>>.>..v.v....>.>....v.>..>>>.>v.>.>.>vv..>.>...v.>.....>vv>.>..vv.vvv.>>.vv.>.....vvvv>..v.>.>>v..v..>.>>.>...v>>v..> v..v>v>..vvv>...v..>.>>...v.v..v..>v..>>.>>.v..>>v...v.vv..v..>...v...v....>v.v.v.v.>.v>vvv.v.v>...>v>.>..>v.v>v>v..v..>>>>...>v.....v.>..v v>v..v..>..v>.....>>>.v..>v>v..>..>v>...v..>....v...v>>vv.....v.vv...v>....v>..v>>.v.>.>>..>v>..>>>vv.>>>...>...v>vv>v>...>..v.v..>.....>>. vv..>>v..>>>.>...v..v.>v>..v.>>>>>v..v>v>..>v>>>v.....v..>.>.>>vv.v....v.....>v......>.>vv..vv>.vv..vv...vv.v...>.v..>.>.v>v...v>..vv...>vv .>...vv>>>.v.....v....>.v......vvvv>.>..>vv>v..vv..>v>>.>v.v>.v>v.vvvvv.v>v......v.>v>vv..>v..>vv.v.v.vvv..>.>.>>v.v.......>vv..v.vv>.>.v.. ....v...v.>.v>>>v.>.....>>v>..v>.v.>.v.>..>v.>vv>>vv.>........v..>v>.v>>v>>v.>....>.>...>.>.v.......v....v>vvv..v>..>..v>....v...>.v.>.v... ..vvv.v>.>...>>.vvv>...v...>..>..>...v>v>..>>.vv....>.v.v.>.v>vv.>>v..v>.v.v..v.>.>>.v.....>.v...v>.....v....v.v.v.>>....v.v>>>.......>vv.v ...v>v>..v.v.v...>v>.vvv.vv..>..v.>v.>vv.>.>>..v....>.v.....>.v>..>..v>>vv..vv.>....v>>.v>...>.>vv....v>>.>>v>....>.v.v>v>>>>...>....>.>..v .>>..v.>v..>>>v.v.v>>...>>v...v>....>.v>>...v.>.v.>...v>>vv.vvv>v....v>.v.>v......v.v.>>.>v...v...>vv.v.....>...>.>..vv.v..>..>.v>..>.v>.vv >..>.>.>>.v.v.>.v.vvv....>.v>v.v..v.v...>...vv..>>.>..>>>...v>.>.v..v.>>.......v.....>.v>vv.>.v..vv>>>>>>v...vvv..vvv>>>.v.>.v..v.v>v>v>..> v..>.v.vv>>vvvvv.....v>>v...vv....v>.>>v.v.>.>>v.vv....vv..v.>>.v.v.>v>....>....v.v>>>.>v.v.>v>v.v.v..>.>v>v......v.v>...>v.vvv...v>...vv.. >>vv.....v...v......>v.v..v>..v.v>..>>>.>>..>v>.v>>>.>v..>>>>v.>..vvvv.v>...v..vv.>.>v....>v.>>.....v>v....v..>.>.v>v.>.>.>v.v..>v......... y2021 - Day 25: Sea Cucumber loige Sometimes you have to handle grids of variable sizes. Actual input (139x137) 73
struct Grid<const W: usize, const H: usize> { cells: [[Option<Cell>; W]; H], } 1 2 3 y2021 - Day 25: Sea Cucumber loige You can use const generics to define a matrix with configurable dimensions 74
struct Grid<const W: usize, const H: usize> { cells: [[Option<Cell>; W]; H], } pub fn test_readme(input: &str) -> usize { let mut grid1: Grid<10, 9> = input.parse().unwrap(); // ... } pub fn part1(input: &str) -> usize { let mut grid1: Grid<139, 137> = input.parse().unwrap(); // ... } 1 2 3 4 5 6 7 8 9 10 11 12 13 pub fn test_readme(input: &str) -> usize { let mut grid1: Grid<10, 9> = input.parse().unwrap(); // ... struct Grid<const W: usize, const H: usize> { 1 cells: [[Option<Cell>; W]; H], 2 } 3 4 5 6 7 } 8 9 pub fn part1(input: &str) -> usize { 10 let mut grid1: Grid<139, 137> = input.parse().unwrap(); 11 // ... 12 } 13 pub fn part1(input: &str) -> usize { let mut grid1: Grid<139, 137> = input.parse().unwrap(); // ... } struct Grid<const W: usize, const H: usize> { 1 cells: [[Option<Cell>; W]; H], 2 } 3 4 pub fn test_readme(input: &str) -> usize { 5 let mut grid1: Grid<10, 9> = input.parse().unwrap(); 6 // ... 7 } 8 9 10 11 12 13 struct Grid<const W: usize, const H: usize> { cells: [[Option<Cell>; W]; H], } pub fn test_readme(input: &str) -> usize { let mut grid1: Grid<10, 9> = input.parse().unwrap(); // ... } pub fn part1(input: &str) -> usize { let mut grid1: Grid<139, 137> = input.parse().unwrap(); // ... } 1 2 3 4 5 6 7 8 9 10 11 12 13 y2021 - Day 25: Sea Cucumber loige 75
Parsing (Ergo, extracting data from text) loige 76
mask = 000000000000000000000000000000X1001X mem[42] = 100 mask = 00000000000000000000000000000000X0XX mem[26] = 1 ... y2020 - Day 14: Docking Data loige enum Instr { Mask(String), Mem(u64, u64), } 77
use std::str::FromStr; impl FromStr for Instr { type Err = String; fn from_str(s: &str) -> Result<Self, Self::Err> { if s.starts_with("mask") { Ok(Instr::Mask(s[7..].to_string())) } else if s.starts_with("mem") { let addr_value = &mut s[4..].split("] = "); let addr: u64 = addr_value.next().unwrap().parse().unwrap(); let value: u64 = addr_value.next().unwrap().parse().unwrap(); Ok(Instr::Mem(addr, value)) } else { Err(format!("Invalid line found: {s}")) } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 use std::str::FromStr; impl FromStr for Instr { } 1 2 3 type Err = String; 4 5 fn from_str(s: &str) -> Result<Self, Self::Err> { 6 if s.starts_with("mask") { 7 Ok(Instr::Mask(s[7..].to_string())) 8 } else if s.starts_with("mem") { 9 let addr_value = &mut s[4..].split("] = "); 10 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 11 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 12 Ok(Instr::Mem(addr, value)) 13 } else { 14 Err(format!("Invalid line found: {s}")) 15 } 16 } 17 18 use std::str::FromStr; impl FromStr for Instr { type Err = String; fn from_str(s: &str) -> Result<Self, Self::Err> { } } 1 2 3 4 5 6 if s.starts_with("mask") { 7 Ok(Instr::Mask(s[7..].to_string())) 8 } else if s.starts_with("mem") { 9 let addr_value = &mut s[4..].split("] = "); 10 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 11 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 12 Ok(Instr::Mem(addr, value)) 13 } else { 14 Err(format!("Invalid line found: {s}")) 15 } 16 17 18 if s.starts_with("mask") { Ok(Instr::Mask(s[7..].to_string())) use std::str::FromStr; 1 2 impl FromStr for Instr { 3 type Err = String; 4 5 fn from_str(s: &str) -> Result<Self, Self::Err> { 6 7 8 } else if s.starts_with("mem") { 9 let addr_value = &mut s[4..].split("] = "); 10 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 11 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 12 Ok(Instr::Mem(addr, value)) 13 } else { 14 Err(format!("Invalid line found: {s}")) 15 } 16 } 17 } 18 } else if s.starts_with("mem") { Ok(Instr::Mem(addr, value)) use std::str::FromStr; 1 2 impl FromStr for Instr { 3 type Err = String; 4 5 fn from_str(s: &str) -> Result<Self, Self::Err> { 6 if s.starts_with("mask") { 7 Ok(Instr::Mask(s[7..].to_string())) 8 9 let addr_value = &mut s[4..].split("] = "); 10 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 11 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 12 13 } else { 14 Err(format!("Invalid line found: {s}")) 15 } 16 } 17 } 18 } else { Err(format!("Invalid line found: {s}")) } use std::str::FromStr; 1 2 impl FromStr for Instr { 3 type Err = String; 4 5 fn from_str(s: &str) -> Result<Self, Self::Err> { 6 if s.starts_with("mask") { 7 Ok(Instr::Mask(s[7..].to_string())) 8 } else if s.starts_with("mem") { 9 let addr_value = &mut s[4..].split("] = "); 10 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 11 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 12 Ok(Instr::Mem(addr, value)) 13 14 15 16 } 17 } 18 use std::str::FromStr; impl FromStr for Instr { type Err = String; fn from_str(s: &str) -> Result<Self, Self::Err> { if s.starts_with("mask") { Ok(Instr::Mask(s[7..].to_string())) } else if s.starts_with("mem") { let addr_value = &mut s[4..].split("] = "); let addr: u64 = addr_value.next().unwrap().parse().unwrap(); let value: u64 = addr_value.next().unwrap().parse().unwrap(); Ok(Instr::Mem(addr, value)) } else { Err(format!("Invalid line found: {s}")) } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 loige 78
let mask: Instr = "mask = 00000000000000X1001X".parse().unwrap(); assert_eq!(mask, Instr::Mask("00000000000000X1001X".to_string())); let mem: Instr = "mem[42] = 100".parse().unwrap(); assert_eq!(mem, Instr::Mem(42, 100)); 1 2 3 4 5 let mask: Instr = "mask = 00000000000000X1001X".parse().unwrap(); assert_eq!(mask, Instr::Mask("00000000000000X1001X".to_string())); 1 2 3 let mem: Instr = "mem[42] = 100".parse().unwrap(); 4 assert_eq!(mem, Instr::Mem(42, 100)); 5 let mem: Instr = "mem[42] = 100".parse().unwrap(); assert_eq!(mem, Instr::Mem(42, 100)); let mask: Instr = "mask = 00000000000000X1001X".parse().unwrap(); 1 assert_eq!(mask, Instr::Mask("00000000000000X1001X".to_string())); 2 3 4 5 let mask: Instr = "mask = 00000000000000X1001X".parse().unwrap(); assert_eq!(mask, Instr::Mask("00000000000000X1001X".to_string())); let mem: Instr = "mem[42] = 100".parse().unwrap(); assert_eq!(mem, Instr::Mem(42, 100)); 1 2 3 4 5 loige 79
let mask: Instr = "mask = 00000000000000X1001X".parse().unwrap(); let mem: Instr = "mem[42] = 100".parse().unwrap(); 1 assert_eq!(mask, Instr::Mask("00000000000000X1001X".to_string())); 2 3 4 assert_eq!(mem, Instr::Mem(42, 100)); 5 loige Implementing the FromStr trait, will make the parse() method available! 80
oops, I did it again: unnecessary allocations! 🤷 loige Why don't you just take a slice from the input rather than allocating a String? 81
enum Instr<'a> { Mask(&'a str), Mem(u64, u64), } impl<'a> FromStr for Instr<'a> { type Err = String; fn from_str(s: &'a str) -> Result<Self, Self::Err> { if s.starts_with("mask") { Ok(Instr::Mask(&s[7..])) } else if s.starts_with("mem") { let addr_value = &mut s[4..].split("] = "); let addr: u64 = addr_value.next().unwrap().parse().unwrap(); let value: u64 = addr_value.next().unwrap().parse().unwrap(); Ok(Instr::Mem(addr, value)) } else { Err(format!("Invalid line found: {s}")) } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 enum Instr<'a> { Mask(&'a str), } 1 2 Mem(u64, u64), 3 4 5 6 impl<'a> FromStr for Instr<'a> { 7 type Err = String; 8 9 fn from_str(s: &'a str) -> Result<Self, Self::Err> { 10 if s.starts_with("mask") { 11 Ok(Instr::Mask(&s[7..])) 12 } else if s.starts_with("mem") { 13 let addr_value = &mut s[4..].split("] = "); 14 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 15 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 16 Ok(Instr::Mem(addr, value)) 17 } else { 18 Err(format!("Invalid line found: {s}")) 19 } 20 } 21 } 22 impl<'a> FromStr for Instr<'a> { enum Instr<'a> { 1 Mask(&'a str), 2 Mem(u64, u64), 3 } 4 5 6 7 type Err = String; 8 9 fn from_str(s: &'a str) -> Result<Self, Self::Err> { 10 if s.starts_with("mask") { 11 Ok(Instr::Mask(&s[7..])) 12 } else if s.starts_with("mem") { 13 let addr_value = &mut s[4..].split("] = "); 14 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 15 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 16 Ok(Instr::Mem(addr, value)) 17 } else { 18 Err(format!("Invalid line found: {s}")) 19 } 20 } 21 } 22 fn from_str(s: &'a str) -> Result<Self, Self::Err> { enum Instr<'a> { 1 Mask(&'a str), 2 Mem(u64, u64), 3 } 4 5 6 impl<'a> FromStr for Instr<'a> { 7 type Err = String; 8 9 10 if s.starts_with("mask") { 11 Ok(Instr::Mask(&s[7..])) 12 } else if s.starts_with("mem") { 13 let addr_value = &mut s[4..].split("] = "); 14 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 15 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 16 Ok(Instr::Mem(addr, value)) 17 } else { 18 Err(format!("Invalid line found: {s}")) 19 } 20 } 21 } 22 loige 82
fn from_str(s: &'a str) -> Result<Self, Self::Err> { enum Instr<'a> { 1 Mask(&'a str), 2 Mem(u64, u64), 3 } 4 5 6 impl<'a> FromStr for Instr<'a> { 7 type Err = String; 8 9 10 if s.starts_with("mask") { 11 Ok(Instr::Mask(&s[7..])) 12 } else if s.starts_with("mem") { 13 let addr_value = &mut s[4..].split("] = "); 14 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 15 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 16 Ok(Instr::Mem(addr, value)) 17 } else { 18 Err(format!("Invalid line found: {s}")) 19 } 20 } 21 } 22 loige users.rust-lang.org/t/fromstr-and-lifetimes/12198 83
enum Instr<'a> { Mask(&'a str), Mem(u64, u64), } impl<'a> From<&'a str> for Instr<'a> { fn from(s: &'a str) -> Self { if s.starts_with("mask") { Instr::Mask(&s[7..]) } else if s.starts_with("mem") { let addr_value = &mut s[4..].split("] = "); let addr: u64 = addr_value.next().unwrap().parse().unwrap(); let value: u64 = addr_value.next().unwrap().parse().unwrap(); Instr::Mem(addr, value) } else { panic!("Invalid line found: {s}") } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 impl<'a> From<&'a str> for Instr<'a> { } enum Instr<'a> { 1 Mask(&'a str), 2 Mem(u64, u64), 3 } 4 5 6 7 fn from(s: &'a str) -> Self { 8 if s.starts_with("mask") { 9 Instr::Mask(&s[7..]) 10 } else if s.starts_with("mem") { 11 let addr_value = &mut s[4..].split("] = "); 12 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 13 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 14 Instr::Mem(addr, value) 15 } else { 16 panic!("Invalid line found: {s}") 17 } 18 } 19 20 fn from(s: &'a str) -> Self { } enum Instr<'a> { 1 Mask(&'a str), 2 Mem(u64, u64), 3 } 4 5 6 impl<'a> From<&'a str> for Instr<'a> { 7 8 if s.starts_with("mask") { 9 Instr::Mask(&s[7..]) 10 } else if s.starts_with("mem") { 11 let addr_value = &mut s[4..].split("] = "); 12 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 13 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 14 Instr::Mem(addr, value) 15 } else { 16 panic!("Invalid line found: {s}") 17 } 18 19 } 20 panic!("Invalid line found: {s}") enum Instr<'a> { 1 Mask(&'a str), 2 Mem(u64, u64), 3 } 4 5 6 impl<'a> From<&'a str> for Instr<'a> { 7 fn from(s: &'a str) -> Self { 8 if s.starts_with("mask") { 9 Instr::Mask(&s[7..]) 10 } else if s.starts_with("mem") { 11 let addr_value = &mut s[4..].split("] = "); 12 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 13 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 14 Instr::Mem(addr, value) 15 } else { 16 17 } 18 } 19 } 20 loige 84
panic!("Invalid line found: {s}") enum Instr<'a> { 1 Mask(&'a str), 2 Mem(u64, u64), 3 } 4 5 6 impl<'a> From<&'a str> for Instr<'a> { 7 fn from(s: &'a str) -> Self { 8 if s.starts_with("mask") { 9 Instr::Mask(&s[7..]) 10 } else if s.starts_with("mem") { 11 let addr_value = &mut s[4..].split("] = "); 12 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 13 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 14 Instr::Mem(addr, value) 15 } else { 16 17 } 18 } 19 } 20 loige This panic gives me anxiety 😰 85
use std::convert::{TryFrom, TryInto}; enum Instr<'a> { Mask(&'a str), Mem(u64, u64), } impl<'a> TryFrom<&'a str> for Instr<'a> { type Error = String; fn try_from(s: &'a str) -> Result<Self, Self::Error> { if s.starts_with("mask") { Ok(Instr::Mask(&s[7..])) } else if s.starts_with("mem") { let addr_value = &mut s[4..].split("] = "); let addr: u64 = addr_value.next().unwrap().parse().unwrap(); let value: u64 = addr_value.next().unwrap().parse().unwrap(); Ok(Instr::Mem(addr, value)) } else { Err(format!("Invalid line found: {s}")) } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 use std::convert::{TryFrom, TryInto}; 1 2 enum Instr<'a> { 3 Mask(&'a str), 4 Mem(u64, u64), 5 } 6 7 impl<'a> TryFrom<&'a str> for Instr<'a> { 8 type Error = String; 9 10 fn try_from(s: &'a str) -> Result<Self, Self::Error> { 11 if s.starts_with("mask") { 12 Ok(Instr::Mask(&s[7..])) 13 } else if s.starts_with("mem") { 14 let addr_value = &mut s[4..].split("] = "); 15 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 16 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 17 Ok(Instr::Mem(addr, value)) 18 } else { 19 Err(format!("Invalid line found: {s}")) 20 } 21 } 22 } 23 impl<'a> TryFrom<&'a str> for Instr<'a> { } use std::convert::{TryFrom, TryInto}; 1 2 enum Instr<'a> { 3 Mask(&'a str), 4 Mem(u64, u64), 5 } 6 7 8 type Error = String; 9 10 fn try_from(s: &'a str) -> Result<Self, Self::Error> { 11 if s.starts_with("mask") { 12 Ok(Instr::Mask(&s[7..])) 13 } else if s.starts_with("mem") { 14 let addr_value = &mut s[4..].split("] = "); 15 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 16 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 17 Ok(Instr::Mem(addr, value)) 18 } else { 19 Err(format!("Invalid line found: {s}")) 20 } 21 } 22 23 type Error = String; use std::convert::{TryFrom, TryInto}; 1 2 enum Instr<'a> { 3 Mask(&'a str), 4 Mem(u64, u64), 5 } 6 7 impl<'a> TryFrom<&'a str> for Instr<'a> { 8 9 10 fn try_from(s: &'a str) -> Result<Self, Self::Error> { 11 if s.starts_with("mask") { 12 Ok(Instr::Mask(&s[7..])) 13 } else if s.starts_with("mem") { 14 let addr_value = &mut s[4..].split("] = "); 15 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 16 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 17 Ok(Instr::Mem(addr, value)) 18 } else { 19 Err(format!("Invalid line found: {s}")) 20 } 21 } 22 } 23 fn try_from(s: &'a str) -> Result<Self, Self::Error> { } use std::convert::{TryFrom, TryInto}; 1 2 enum Instr<'a> { 3 Mask(&'a str), 4 Mem(u64, u64), 5 } 6 7 impl<'a> TryFrom<&'a str> for Instr<'a> { 8 type Error = String; 9 10 11 if s.starts_with("mask") { 12 Ok(Instr::Mask(&s[7..])) 13 } else if s.starts_with("mem") { 14 let addr_value = &mut s[4..].split("] = "); 15 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 16 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 17 Ok(Instr::Mem(addr, value)) 18 } else { 19 Err(format!("Invalid line found: {s}")) 20 } 21 22 } 23 Ok(Instr::Mask(&s[7..])) Ok(Instr::Mem(addr, value)) Err(format!("Invalid line found: {s}")) use std::convert::{TryFrom, TryInto}; 1 2 enum Instr<'a> { 3 Mask(&'a str), 4 Mem(u64, u64), 5 } 6 7 impl<'a> TryFrom<&'a str> for Instr<'a> { 8 type Error = String; 9 10 fn try_from(s: &'a str) -> Result<Self, Self::Error> { 11 if s.starts_with("mask") { 12 13 } else if s.starts_with("mem") { 14 let addr_value = &mut s[4..].split("] = "); 15 let addr: u64 = addr_value.next().unwrap().parse().unwrap(); 16 let value: u64 = addr_value.next().unwrap().parse().unwrap(); 17 18 } else { 19 20 } 21 } 22 } 23 use std::convert::{TryFrom, TryInto}; enum Instr<'a> { Mask(&'a str), Mem(u64, u64), } impl<'a> TryFrom<&'a str> for Instr<'a> { type Error = String; fn try_from(s: &'a str) -> Result<Self, Self::Error> { if s.starts_with("mask") { Ok(Instr::Mask(&s[7..])) } else if s.starts_with("mem") { let addr_value = &mut s[4..].split("] = "); let addr: u64 = addr_value.next().unwrap().parse().unwrap(); let value: u64 = addr_value.next().unwrap().parse().unwrap(); Ok(Instr::Mem(addr, value)) } else { Err(format!("Invalid line found: {s}")) } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 loige 86
let mask: Instr = "mask = 00000000000000X1001X".try_into().unwrap(); let mem: Instr = "mem[42] = 100".try_into().unwrap(); 1 assert_eq!(mask, Instr::Mask("00000000000000X1001X")); 2 3 4 assert_eq!(mem, Instr::Mem(42, 100)); 5 loige Implementing the TryFrom trait, will make the try_into() method available! 87
Sensor at x=2, y=18: closest beacon is at x=-2, y=15 Sensor at x=9, y=16: closest beacon is at x=10, y=16 Sensor at x=13, y=2: closest beacon is at x=15, y=3 Sensor at x=12, y=14: closest beacon is at x=10, y=16 ... y2022 - Day 15: Beacon Exclusion Zone loige struct Pos { x: i64, y: i64, } let sensor = Pos { x: 13, y: 2, } let beacon = Pos { x: 15, y: 3, } 88
loige89
loige 😱 90
loige 91
loige 92
use regex::Regex; fn parse_line_regex(line: &str) -> (Pos, Pos) { let re = Regex::new( r"Sensor at x=(?P<x1>[-]?d+), y=(?P<y1>[-]?d+): closest beacon ) .unwrap(); let captures = re.captures(line).unwrap(); let sensor = Pos { x: captures["x1"].parse().unwrap(), y: captures["y1"].parse().unwrap(), }; let beacon = Pos { x: captures["x2"].parse().unwrap(), y: captures["y2"].parse().unwrap(), }; (sensor, beacon) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 use regex::Regex; 1 2 fn parse_line_regex(line: &str) -> (Pos, Pos) { 3 let re = Regex::new( 4 r"Sensor at x=(?P<x1>[-]?d+), y=(?P<y1>[-]?d+): closest beacon 5 ) 6 .unwrap(); 7 8 let captures = re.captures(line).unwrap(); 9 let sensor = Pos { 10 x: captures["x1"].parse().unwrap(), 11 y: captures["y1"].parse().unwrap(), 12 }; 13 let beacon = Pos { 14 x: captures["x2"].parse().unwrap(), 15 y: captures["y2"].parse().unwrap(), 16 }; 17 (sensor, beacon) 18 } 19 fn parse_line_regex(line: &str) -> (Pos, Pos) { } use regex::Regex; 1 2 3 let re = Regex::new( 4 r"Sensor at x=(?P<x1>[-]?d+), y=(?P<y1>[-]?d+): closest beacon 5 ) 6 .unwrap(); 7 8 let captures = re.captures(line).unwrap(); 9 let sensor = Pos { 10 x: captures["x1"].parse().unwrap(), 11 y: captures["y1"].parse().unwrap(), 12 }; 13 let beacon = Pos { 14 x: captures["x2"].parse().unwrap(), 15 y: captures["y2"].parse().unwrap(), 16 }; 17 (sensor, beacon) 18 19 let re = Regex::new( r"Sensor at x=(?P<x1>[-]?d+), y=(?P<y1>[-]?d+): closest beacon ) .unwrap(); use regex::Regex; 1 2 fn parse_line_regex(line: &str) -> (Pos, Pos) { 3 4 5 6 7 8 let captures = re.captures(line).unwrap(); 9 let sensor = Pos { 10 x: captures["x1"].parse().unwrap(), 11 y: captures["y1"].parse().unwrap(), 12 }; 13 let beacon = Pos { 14 x: captures["x2"].parse().unwrap(), 15 y: captures["y2"].parse().unwrap(), 16 }; 17 (sensor, beacon) 18 } 19 let captures = re.captures(line).unwrap(); use regex::Regex; 1 2 fn parse_line_regex(line: &str) -> (Pos, Pos) { 3 let re = Regex::new( 4 r"Sensor at x=(?P<x1>[-]?d+), y=(?P<y1>[-]?d+): closest beacon 5 ) 6 .unwrap(); 7 8 9 let sensor = Pos { 10 x: captures["x1"].parse().unwrap(), 11 y: captures["y1"].parse().unwrap(), 12 }; 13 let beacon = Pos { 14 x: captures["x2"].parse().unwrap(), 15 y: captures["y2"].parse().unwrap(), 16 }; 17 (sensor, beacon) 18 } 19 let sensor = Pos { x: captures["x1"].parse().unwrap(), y: captures["y1"].parse().unwrap(), }; let beacon = Pos { x: captures["x2"].parse().unwrap(), y: captures["y2"].parse().unwrap(), }; use regex::Regex; 1 2 fn parse_line_regex(line: &str) -> (Pos, Pos) { 3 let re = Regex::new( 4 r"Sensor at x=(?P<x1>[-]?d+), y=(?P<y1>[-]?d+): closest beacon 5 ) 6 .unwrap(); 7 8 let captures = re.captures(line).unwrap(); 9 10 11 12 13 14 15 16 17 (sensor, beacon) 18 } 19 (sensor, beacon) use regex::Regex; 1 2 fn parse_line_regex(line: &str) -> (Pos, Pos) { 3 let re = Regex::new( 4 r"Sensor at x=(?P<x1>[-]?d+), y=(?P<y1>[-]?d+): closest beacon 5 ) 6 .unwrap(); 7 8 let captures = re.captures(line).unwrap(); 9 let sensor = Pos { 10 x: captures["x1"].parse().unwrap(), 11 y: captures["y1"].parse().unwrap(), 12 }; 13 let beacon = Pos { 14 x: captures["x2"].parse().unwrap(), 15 y: captures["y2"].parse().unwrap(), 16 }; 17 18 } 19 use regex::Regex; fn parse_line_regex(line: &str) -> (Pos, Pos) { let re = Regex::new( r"Sensor at x=(?P<x1>[-]?d+), y=(?P<y1>[-]?d+): closest beacon ) .unwrap(); let captures = re.captures(line).unwrap(); let sensor = Pos { x: captures["x1"].parse().unwrap(), y: captures["y1"].parse().unwrap(), }; let beacon = Pos { x: captures["x2"].parse().unwrap(), y: captures["y2"].parse().unwrap(), }; (sensor, beacon) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 loige 93
pub fn parse_regex(input: &str) -> impl Iterator<Item = (Pos, Pos)> + '_ input.lines().map(parse_line_regex) } use regex::Regex; 1 2 fn parse_line_regex(line: &str) -> (Pos, Pos) { 3 let re = Regex::new( 4 r"Sensor at x=(?P<x1>[-]?d+), y=(?P<y1>[-]?d+): closest beacon 5 ) 6 .unwrap(); 7 8 // ... 9 (sensor, beacon) 10 } 11 12 13 14 15 loige Aren't we re-istantiating the Regex over and over? 🤷 94
How can we initialize the regex globally? loige $ cargo add lazy_static 95
#[macro_use] extern crate lazy_static; use regex::Regex; lazy_static! { static ref LINE_REGEX: Regex = Regex::new(r"Sensor at x=(?P<x1>[-]?d .unwrap(); } fn parse_line_regex(line: &str) -> (Pos, Pos) { let captures = LINE_REGEX.captures(line).unwrap(); // ... (sensor, beacon) } pub fn parse_regex(input: &str) -> impl Iterator<Item = (Pos, Pos)> + '_ input.lines().map(parse_line_regex) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #[macro_use] extern crate lazy_static; 1 2 use regex::Regex; 3 4 lazy_static! { 5 static ref LINE_REGEX: Regex = Regex::new(r"Sensor at x=(?P<x1>[-]?d 6 .unwrap(); 7 } 8 9 fn parse_line_regex(line: &str) -> (Pos, Pos) { 10 let captures = LINE_REGEX.captures(line).unwrap(); 11 12 // ... 13 (sensor, beacon) 14 } 15 16 pub fn parse_regex(input: &str) -> impl Iterator<Item = (Pos, Pos)> + '_ 17 input.lines().map(parse_line_regex) 18 } 19 lazy_static! { static ref LINE_REGEX: Regex = Regex::new(r"Sensor at x=(?P<x1>[-]?d .unwrap(); } #[macro_use] 1 extern crate lazy_static; 2 use regex::Regex; 3 4 5 6 7 8 9 fn parse_line_regex(line: &str) -> (Pos, Pos) { 10 let captures = LINE_REGEX.captures(line).unwrap(); 11 12 // ... 13 (sensor, beacon) 14 } 15 16 pub fn parse_regex(input: &str) -> impl Iterator<Item = (Pos, Pos)> + '_ 17 input.lines().map(parse_line_regex) 18 } 19 let captures = LINE_REGEX.captures(line).unwrap(); #[macro_use] 1 extern crate lazy_static; 2 use regex::Regex; 3 4 lazy_static! { 5 static ref LINE_REGEX: Regex = Regex::new(r"Sensor at x=(?P<x1>[-]?d 6 .unwrap(); 7 } 8 9 fn parse_line_regex(line: &str) -> (Pos, Pos) { 10 11 12 // ... 13 (sensor, beacon) 14 } 15 16 pub fn parse_regex(input: &str) -> impl Iterator<Item = (Pos, Pos)> + '_ 17 input.lines().map(parse_line_regex) 18 } 19 #[macro_use] extern crate lazy_static; use regex::Regex; lazy_static! { static ref LINE_REGEX: Regex = Regex::new(r"Sensor at x=(?P<x1>[-]?d .unwrap(); } fn parse_line_regex(line: &str) -> (Pos, Pos) { let captures = LINE_REGEX.captures(line).unwrap(); // ... (sensor, beacon) } pub fn parse_regex(input: &str) -> impl Iterator<Item = (Pos, Pos)> + '_ input.lines().map(parse_line_regex) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 loige 96
🤷BTW, should I tell you that when you solve a problem with a Regex... BLAH BLAH BLAH?! loige 97
Ok, let's do proper parsing with nom! 💪 loige $ cargo add nom 98
fn parse_i64(input: &str) -> IResult<&str, i64> { let (input, sign) = opt(tag("-"))(input)?; let (input, value) = digit1(input)?; let mut value = value.parse::<i64>().unwrap(); if sign.is_some() { value *= -1; } Ok((input, value)) } 1 2 3 4 5 6 7 8 9 fn parse_i64(input: &str) -> IResult<&str, i64> { } 1 let (input, sign) = opt(tag("-"))(input)?; 2 let (input, value) = digit1(input)?; 3 let mut value = value.parse::<i64>().unwrap(); 4 if sign.is_some() { 5 value *= -1; 6 } 7 Ok((input, value)) 8 9 let (input, sign) = opt(tag("-"))(input)?; fn parse_i64(input: &str) -> IResult<&str, i64> { 1 2 let (input, value) = digit1(input)?; 3 let mut value = value.parse::<i64>().unwrap(); 4 if sign.is_some() { 5 value *= -1; 6 } 7 Ok((input, value)) 8 } 9 let (input, value) = digit1(input)?; fn parse_i64(input: &str) -> IResult<&str, i64> { 1 let (input, sign) = opt(tag("-"))(input)?; 2 3 let mut value = value.parse::<i64>().unwrap(); 4 if sign.is_some() { 5 value *= -1; 6 } 7 Ok((input, value)) 8 } 9 let mut value = value.parse::<i64>().unwrap(); if sign.is_some() { value *= -1; } fn parse_i64(input: &str) -> IResult<&str, i64> { 1 let (input, sign) = opt(tag("-"))(input)?; 2 let (input, value) = digit1(input)?; 3 4 5 6 7 Ok((input, value)) 8 } 9 Ok((input, value)) fn parse_i64(input: &str) -> IResult<&str, i64> { 1 let (input, sign) = opt(tag("-"))(input)?; 2 let (input, value) = digit1(input)?; 3 let mut value = value.parse::<i64>().unwrap(); 4 if sign.is_some() { 5 value *= -1; 6 } 7 8 } 9 fn parse_i64(input: &str) -> IResult<&str, i64> { let (input, sign) = opt(tag("-"))(input)?; let (input, value) = digit1(input)?; let mut value = value.parse::<i64>().unwrap(); if sign.is_some() { value *= -1; } Ok((input, value)) } 1 2 3 4 5 6 7 8 9 loige 99
fn parse_line(input: &str) -> IResult<&str, (Pos, Pos)> { let (input, (s_x, s_y, b_x, b_y)) = all_consuming(tuple(( preceded(tag("Sensor at x="), parse_i64), preceded(tag(", y="), parse_i64), preceded(tag(": closest beacon is at x="), parse_i64), preceded(tag(", y="), parse_i64), )))(input)?; let p1 = Pos { x: s_x, y: s_y }; let p2 = Pos { x: b_x, y: b_y }; Ok((input, (p1, p2))) } 1 2 3 4 5 6 7 8 9 10 11 fn parse_line(input: &str) -> IResult<&str, (Pos, Pos)> { } 1 let (input, (s_x, s_y, b_x, b_y)) = all_consuming(tuple(( 2 preceded(tag("Sensor at x="), parse_i64), 3 preceded(tag(", y="), parse_i64), 4 preceded(tag(": closest beacon is at x="), parse_i64), 5 preceded(tag(", y="), parse_i64), 6 )))(input)?; 7 let p1 = Pos { x: s_x, y: s_y }; 8 let p2 = Pos { x: b_x, y: b_y }; 9 Ok((input, (p1, p2))) 10 11 let (input, (s_x, s_y, b_x, b_y)) = all_consuming(tuple(( preceded(tag("Sensor at x="), parse_i64), preceded(tag(", y="), parse_i64), preceded(tag(": closest beacon is at x="), parse_i64), preceded(tag(", y="), parse_i64), )))(input)?; fn parse_line(input: &str) -> IResult<&str, (Pos, Pos)> { 1 2 3 4 5 6 7 let p1 = Pos { x: s_x, y: s_y }; 8 let p2 = Pos { x: b_x, y: b_y }; 9 Ok((input, (p1, p2))) 10 } 11 let p1 = Pos { x: s_x, y: s_y }; let p2 = Pos { x: b_x, y: b_y }; fn parse_line(input: &str) -> IResult<&str, (Pos, Pos)> { 1 let (input, (s_x, s_y, b_x, b_y)) = all_consuming(tuple(( 2 preceded(tag("Sensor at x="), parse_i64), 3 preceded(tag(", y="), parse_i64), 4 preceded(tag(": closest beacon is at x="), parse_i64), 5 preceded(tag(", y="), parse_i64), 6 )))(input)?; 7 8 9 Ok((input, (p1, p2))) 10 } 11 Ok((input, (p1, p2))) fn parse_line(input: &str) -> IResult<&str, (Pos, Pos)> { 1 let (input, (s_x, s_y, b_x, b_y)) = all_consuming(tuple(( 2 preceded(tag("Sensor at x="), parse_i64), 3 preceded(tag(", y="), parse_i64), 4 preceded(tag(": closest beacon is at x="), parse_i64), 5 preceded(tag(", y="), parse_i64), 6 )))(input)?; 7 let p1 = Pos { x: s_x, y: s_y }; 8 let p2 = Pos { x: b_x, y: b_y }; 9 10 } 11 fn parse_line(input: &str) -> IResult<&str, (Pos, Pos)> { let (input, (s_x, s_y, b_x, b_y)) = all_consuming(tuple(( preceded(tag("Sensor at x="), parse_i64), preceded(tag(", y="), parse_i64), preceded(tag(": closest beacon is at x="), parse_i64), preceded(tag(", y="), parse_i64), )))(input)?; let p1 = Pos { x: s_x, y: s_y }; let p2 = Pos { x: b_x, y: b_y }; Ok((input, (p1, p2))) } 1 2 3 4 5 6 7 8 9 10 11 loige 100
Which one do you think is faster? 🧐 loige regex regex_lazy nom 1. 2. 3. 101
Which one do you think is faster? 🧐 loige regex regex_lazy nom 1. 2. 3. 102
Which one do you think is faster? 🧐 loige regex regex_lazy nom 1. 2. 3. 3063.9 µs 9.3 µs 1.8 µs ⭐ +170117% +417% 103
The Iterator & the FromIterator traits Destructuring with if let Some(x) / while let Some(x)... Powerful pattern-matching syntax and the matches!() macro Newtype pattern + Deref & DerefMut trait The Display & Debug traits unreachable!() & todo!() macros defaultdict a-la-python using HashMap and the entry API Copy On Write (CoW) Helper methods of the Result and the Option types I would have also loved to tell you about... 🤯 104
Started with a very imperative style and ended up with a more functional style "if you look back at your code from 2 years ago and you are not ashamed you are not growing" Noticed that rust has been improving a lot in these 3 years Often needed helpers but they were in nightly (Vec::retain) Rust Analyser & Clippy have been suggesting new improvements over time! Rust is fantastic for Advent of Code! 🦀In conclusion... 105
Photo by on Nathan Dumlao Unsplash loige 106
Huge thanks to , , Cover photo by on @gbinside @AlleviTommaso @giufus Redaviqui Davilli Unsplash TNX loige nodejsdp.link Sorry, I have a contractual obligation to put this here 😛 107

What I learned by solving 50 Advent of Code challenges in Rust - RustNation UK 2023