Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

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

In 2020 I started to be a bit more serious about learning Rust. After having read a few books and having done some coding challenges, I decided to start live-streaming my attempts to solve Advent of Code challenges using Rust. Fast forward to 2022 I completed 50 challenges and learned a lot about how to use Rust to solve specific programming challenges. In this talk, I’ll be sharing some common tips and tricks that I discovered while live-coding also thanks to the beautiful Rust community that gave me tons of suggestions! Some topics I’ll be covering in this talk: parsing input, data structures, error handling, iterators, performance, allocating and manipulating 2d matrices, etc.

Luciano Mammino

February 17, 2023
Tweet

More Decks by Luciano Mammino

Other Decks in Technology

Transcript

  1. 2023-02-15 1

    View full-size slide

  2. 2023-02-15 2

    View full-size slide

  3. 2023-02-15 3
    😅

    View full-size slide

  4. 👋 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

    View full-size slide

  5. 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:
    [email protected]
    fth.link/careers
    5

    View full-size slide

  6. loige
    podcast
    awsbites.com
    How do you write Lambda Functions in Rust?
    6

    View full-size slide

  7. 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

    View full-size slide

  8. 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`, 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 Future for PollFn
    where
    F: FnMut(&mut Context<'_>) -> Poll,
    {
    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

    View full-size slide

  9. 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

    View full-size slide

  10. Yeah,
    but it's not really about tech...
    loige 10

    View full-size slide

  11. It's about people
    loige 11

    View full-size slide

  12. It's about people
    loige
    @gbinside
    12

    View full-size slide

  13. It's about people
    loige 13

    View full-size slide

  14. 🔥 Hot take
    If you are struggling to learn Rust
    (or anything else, really)...
    Find a learning buddy!
    loige 14

    View full-size slide

  15. Advent of Code . com
    loige
    github.com/lmammino/rust-advent
    15

    View full-size slide

  16. 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

    View full-size slide

  17. Iterator
    combinators
    loige 19

    View full-size slide

  18. 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

    View full-size slide

  19. fn classic(input: &str) -> u64 {
    let mut max = 0;
    let batches = input.split("\n\n");
    for batch in batches {
    let lines = batch.lines();
    let mut total = 0;
    for line in lines {
    let value = line.parse::().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("\n\n");
    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::().unwrap();
    8
    total += value;
    9
    }
    10
    if total > max {
    11
    max = total;
    12
    }
    13
    }
    14
    15
    }
    16
    let batches = input.split("\n\n");
    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::().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("\n\n");
    3
    4
    let lines = batch.lines();
    5
    let mut total = 0;
    6
    for line in lines {
    7
    let value = line.parse::().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("\n\n");
    3
    for batch in batches {
    4
    5
    6
    for line in lines {
    7
    let value = line.parse::().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("\n\n");
    3
    for batch in batches {
    4
    let lines = batch.lines();
    5
    let mut total = 0;
    6
    7
    let value = line.parse::().unwrap();
    8
    total += value;
    9
    10
    if total > max {
    11
    max = total;
    12
    }
    13
    }
    14
    max
    15
    }
    16
    let value = line.parse::().unwrap();
    fn classic(input: &str) -> u64 {
    1
    let mut max = 0;
    2
    let batches = input.split("\n\n");
    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("\n\n");
    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::().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("\n\n");
    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::().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("\n\n");
    for batch in batches {
    let lines = batch.lines();
    let mut total = 0;
    for line in lines {
    let value = line.parse::().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

    View full-size slide

  20. fn combinators(input: &str) -> u64 {
    input
    .split("\n\n")
    .map(|batch| {
    batch
    .lines()
    .map(|line| line.parse::().unwrap())
    .sum::()
    })
    .max()
    .unwrap()
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    input
    .split("\n\n")
    fn combinators(input: &str) -> u64 {
    1
    2
    3
    .map(|batch| {
    4
    batch
    5
    .lines()
    6
    .map(|line| line.parse::().unwrap())
    7
    .sum::()
    8
    })
    9
    .max()
    10
    .unwrap()
    11
    }
    12
    .map(|batch| {
    })
    fn combinators(input: &str) -> u64 {
    1
    input
    2
    .split("\n\n")
    3
    4
    batch
    5
    .lines()
    6
    .map(|line| line.parse::().unwrap())
    7
    .sum::()
    8
    9
    .max()
    10
    .unwrap()
    11
    }
    12
    batch
    .lines()
    .map(|line| line.parse::().unwrap())
    .sum::()
    fn combinators(input: &str) -> u64 {
    1
    input
    2
    .split("\n\n")
    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("\n\n")
    3
    .map(|batch| {
    4
    batch
    5
    .lines()
    6
    .map(|line| line.parse::().unwrap())
    7
    .sum::()
    8
    })
    9
    10
    11
    }
    12
    fn combinators(input: &str) -> u64 {
    input
    .split("\n\n")
    .map(|batch| {
    batch
    .lines()
    .map(|line| line.parse::().unwrap())
    .sum::()
    })
    .max()
    .unwrap()
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Combinators approach
    loige
    22

    View full-size slide

  21. Nice, but the classic noob version
    must be much faster, right?
    🤔
    loige 23

    View full-size slide

  22. ⚡ NOT REALLY!
    loige 24

    View full-size slide

  23. Yeah, but I am sure that
    iterator combinators are
    not always flexible enough, right?
    🤔
    loige 25

    View full-size slide

  24. 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

    View full-size slide

  25. fn combinators(input: &str) -> u64 {
    input
    .split("\n\n")
    .map(|batch| {
    batch
    .lines()
    .map(|line| line.parse::().unwrap())
    .sum::()
    })
    .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("\n\n")
    3
    .map(|batch| {
    4
    batch
    5
    .lines()
    6
    .map(|line| line.parse::().unwrap())
    7
    .sum::()
    8
    })
    9
    10
    .take(3)
    11
    .sum()
    12
    }
    13
    .take(3)
    fn combinators(input: &str) -> u64 {
    1
    input
    2
    .split("\n\n")
    3
    .map(|batch| {
    4
    batch
    5
    .lines()
    6
    .map(|line| line.parse::().unwrap())
    7
    .sum::()
    8
    })
    9
    .sort_descending()
    10
    11
    .sum()
    12
    }
    13
    .sum()
    fn combinators(input: &str) -> u64 {
    1
    input
    2
    .split("\n\n")
    3
    .map(|batch| {
    4
    batch
    5
    .lines()
    6
    .map(|line| line.parse::().unwrap())
    7
    .sum::()
    8
    })
    9
    .sort_descending()
    10
    .take(3)
    11
    12
    }
    13
    fn combinators(input: &str) -> u64 {
    input
    .split("\n\n")
    .map(|batch| {
    batch
    .lines()
    .map(|line| line.parse::().unwrap())
    .sum::()
    })
    .sort_descending()
    .take(3)
    .sum()
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    loige
    27

    View full-size slide

  26. .sort_descending()
    fn combinators(input: &str) -> u64 {
    1
    input
    2
    .split("\n\n")
    3
    .map(|batch| {
    4
    batch
    5
    .lines()
    6
    .map(|line| line.parse::().unwrap())
    7
    .sum::()
    8
    })
    9
    10
    .take(3)
    11
    .sum()
    12
    }
    13
    loige
    🤷
    28

    View full-size slide

  27. But iterator combinators can be
    "extended"
    🤫
    loige
    $ cargo add itertools
    29

    View full-size slide

  28. use itertools::Itertools;
    fn combinators(input: &str) -> u64 {
    input
    .split("\n\n")
    .map(|batch| {
    batch
    .lines()
    .map(|line| line.parse::().unwrap())
    .sum::()
    })
    .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("\n\n")
    5
    .map(|batch| {
    6
    batch
    7
    .lines()
    8
    .map(|line| line.parse::().unwrap())
    9
    .sum::()
    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("\n\n")
    5
    .map(|batch| {
    6
    batch
    7
    .lines()
    8
    .map(|line| line.parse::().unwrap())
    9
    .sum::()
    10
    })
    11
    12
    13
    .take(3)
    14
    .sum()
    15
    }
    16
    use itertools::Itertools;
    fn combinators(input: &str) -> u64 {
    input
    .split("\n\n")
    .map(|batch| {
    batch
    .lines()
    .map(|line| line.parse::().unwrap())
    .sum::()
    })
    .sorted()
    .rev()
    .take(3)
    .sum()
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    loige
    30

    View full-size slide

  29. .sorted()
    use itertools::Itertools;
    1
    2
    fn combinators(input: &str) -> u64 {
    3
    input
    4
    .split("\n\n")
    5
    .map(|batch| {
    6
    batch
    7
    .lines()
    8
    .map(|line| line.parse::().unwrap())
    9
    .sum::()
    10
    })
    11
    12
    .rev()
    13
    .take(3)
    14
    .sum()
    15
    }
    16
    loige
    🤩
    added by itertools
    31

    View full-size slide

  30. But... Do we really want to sort?
    😕
    loige 32

    View full-size slide

  31. 💡IDEA:
    Consume the iterator and, as you go,
    keep the current top 3 in a vec...
    loige 33

    View full-size slide

  32. 💡IDEA:
    Consume the iterator and, as you go,
    keep the current top 3 in a vec...
    loige
    100
    22
    44
    1
    120
    top3 = []
    34

    View full-size slide

  33. loige
    100
    22
    44
    1
    120
    top3 = []
    👉
    💡IDEA:
    Consume the iterator and, as you go,
    keep the current top 3 in a vec...
    35

    View full-size slide

  34. 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

    View full-size slide

  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...
    37

    View full-size slide

  36. 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

    View full-size slide

  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...
    39

    View full-size slide

  38. 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

    View full-size slide

  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...
    41

    View full-size slide

  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...
    42

    View full-size slide

  41. 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

    View full-size slide

  42. 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

    View full-size slide

  43. trait TopN {
    fn top_n(self, n: usize) -> Vec;
    }
    1
    2
    3
    loige
    That's what we want for now,
    but can it be more "generic"?
    🧐
    45

    View full-size slide

  44. trait TopN {
    fn top_n(self, n: usize) -> Vec;
    }
    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

    View full-size slide

  45. That's a cool trait indeed... but I am
    sure we cannot implement it for "all"
    iterators, right?!
    🤷
    loige 47

    View full-size slide

  46. Of course, we can!
    💪
    loige
    It's called a "blanket implementation".
    48

    View full-size slide

  47. impl> TopN for U {
    fn top_n(self, n: usize) -> Vec {
    }
    }
    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 for all
    types U (iterators producing T)!
    49

    View full-size slide

  48. impl> TopN for U {
    fn top_n(self, n: usize) -> Vec {
    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> TopN for U {
    1
    fn top_n(self, n: usize) -> Vec {
    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> TopN for U {
    1
    fn top_n(self, n: usize) -> Vec {
    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

    View full-size slide

  49. if value > *top_value {
    impl> TopN for U {
    1
    fn top_n(self, n: usize) -> Vec {
    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

    View full-size slide

  50. impl> TopN for U {
    1
    fn top_n(self, n: usize) -> Vec {
    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

    View full-size slide

  51. fn combinators_no_sort(input: &str) -> u64 {
    input
    .split("\n\n")
    .map(|batch| {
    batch
    .lines()
    .map(|line| line.parse::().unwrap())
    .sum::()
    })
    .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("\n\n")
    3
    .map(|batch| {
    4
    batch
    5
    .lines()
    6
    .map(|line| line.parse::().unwrap())
    7
    .sum::()
    8
    })
    9
    10
    11
    12
    }
    13
    loige
    53

    View full-size slide

  52. .top_n(3)
    fn combinators_no_sort(input: &str) -> u64 {
    1
    input
    2
    .split("\n\n")
    3
    .map(|batch| {
    4
    batch
    5
    .lines()
    6
    .map(|line| line.parse::().unwrap())
    7
    .sum::()
    8
    })
    9
    10
    .iter()
    11
    .sum()
    12
    }
    13
    loige
    😍
    OMG, we added this!
    54

    View full-size slide

  53. OK, but you used a Vec there...
    I heard rustaceans don't like
    unnecessary allocations, right?!
    🤷
    loige 55

    View full-size slide

  54. trait Top {
    fn top(self, n: usize) -> Vec;
    }
    impl> Top for U {
    fn top(self, n: usize) -> Vec {
    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

    View full-size slide

  55. trait Top {
    fn top(self, n: usize) -> [T;n];
    }
    impl> Top 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 {
    1
    2
    }
    3
    4
    impl> Top for U {
    5
    fn top(self, n: usize) -> [T;n] {
    6
    let mut top = [T;n];
    7
    // ...
    8
    top
    9
    }
    10
    }
    11
    loige
    57

    View full-size slide

  56. fn top(self) -> [T; N];
    trait Top {
    1
    2
    }
    3
    4
    impl> Top for U {
    5
    fn top(self) -> [T; N] {
    6
    let mut top = [T;N];
    7
    // ...
    8
    top
    9
    }
    10
    }
    11
    loige
    const generics syntax
    58

    View full-size slide

  57. let mut top = [T;N];
    trait Top {
    1
    fn top(self) -> [T; N];
    2
    }
    3
    4
    impl> Top for U {
    5
    fn top(self) -> [T; N] {
    6
    7
    // ...
    8
    top
    9
    }
    10
    }
    11
    loige
    59

    View full-size slide

  58. let mut top = [Default::default(); N];
    trait Top {
    1
    fn top(self) -> [T; N];
    2
    }
    3
    4
    impl> Top for U {
    5
    fn top(self) -> [T; N] {
    6
    7
    // ...
    8
    top
    9
    }
    10
    }
    11
    loige
    60

    View full-size slide

  59. impl> Top for
    let mut top = [Default::default(); N];
    trait Top {
    1
    fn top(self) -> [T; N];
    2
    }
    3
    4
    5
    fn top(self) -> [T; N] {
    6
    7
    // ...
    8
    top
    9
    }
    10
    }
    11
    loige
    61

    View full-size slide

  60. impl> Top for
    let mut top = [Default::default(); N];
    trait Top {
    1
    fn top(self) -> [T; N];
    2
    }
    3
    4
    5
    fn top(self) -> [T; N] {
    6
    7
    // ...
    8
    top
    9
    }
    10
    }
    11
    loige
    Do we really need this?
    62

    View full-size slide

  61. impl> Top for U {
    let mut top = core::array::from_fn(|_| Default::default());
    trait Top {
    1
    fn top(self) -> [T; N];
    2
    }
    3
    4
    5
    fn top(self) -> [T; N] {
    6
    7
    // ...
    8
    top
    9
    }
    10
    }
    11
    loige
    Allows us to avoid Copy
    63

    View full-size slide

  62. impl> Top for U {
    let mut top = core::array::from_fn(|_| Default::default());
    trait Top {
    1
    fn top(self) -> [T; N];
    2
    }
    3
    4
    5
    fn top(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

    View full-size slide

  63. fn combinators_no_sort_const(input: &str) -> u64 {
    input
    .split("\n\n")
    .map(|batch| {
    batch
    .lines()
    .map(|line| line.parse::().unwrap())
    .sum::()
    })
    .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("\n\n")
    3
    .map(|batch| {
    4
    batch
    5
    .lines()
    6
    .map(|line| line.parse::().unwrap())
    7
    .sum::()
    8
    })
    9
    10
    .iter()
    11
    .sum()
    12
    }
    13
    loige
    65

    View full-size slide

  64. .top::<3>()
    fn combinators_no_sort_const(input: &str) -> u64 {
    1
    input
    2
    .split("\n\n")
    3
    .map(|batch| {
    4
    batch
    5
    .lines()
    6
    .map(|line| line.parse::().unwrap())
    7
    .sum::()
    8
    })
    9
    10
    .iter()
    11
    .sum()
    12
    }
    13
    loige
    Slightly different syntax
    🐟
    Phew... we did it!
    😮 💨
    66

    View full-size slide

  65. Which one do you think is faster?
    🧐
    loige
    Itertools
    no_sort_vec
    no_sort_array
    1.
    2.
    3.
    67

    View full-size slide

  66. 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

    View full-size slide

  67. But let's talk more about
    const generics, what else can you do
    with them?
    loige 69

    View full-size slide

  68. struct Point([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([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([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([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([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([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

    View full-size slide

  69. 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

    View full-size slide

  70. 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

    View full-size slide

  71. .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

    View full-size slide

  72. struct Grid {
    cells: [[Option; W]; H],
    }
    1
    2
    3
    y2021 - Day 25: Sea Cucumber
    loige
    You can use const generics to define a matrix
    with configurable dimensions
    74

    View full-size slide

  73. struct Grid {
    cells: [[Option; 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 {
    1
    cells: [[Option; 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 {
    1
    cells: [[Option; 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 {
    cells: [[Option; 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

    View full-size slide

  74. Parsing
    (Ergo, extracting data from text)
    loige 76

    View full-size slide

  75. mask = 000000000000000000000000000000X1001X
    mem[42] = 100
    mask = 00000000000000000000000000000000X0XX
    mem[26] = 1
    ...
    y2020 - Day 14: Docking Data
    loige
    enum Instr {
    Mask(String),
    Mem(u64, u64),
    }
    77

    View full-size slide

  76. use std::str::FromStr;
    impl FromStr for Instr {
    type Err = String;
    fn from_str(s: &str) -> Result {
    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 {
    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 {
    }
    }
    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 {
    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 {
    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 {
    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 {
    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

    View full-size slide

  77. 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

    View full-size slide

  78. 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

    View full-size slide

  79. 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

    View full-size slide

  80. 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 {
    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 {
    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 {
    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 {
    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

    View full-size slide

  81. fn from_str(s: &'a str) -> Result {
    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

    View full-size slide

  82. 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

    View full-size slide

  83. 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

    View full-size slide

  84. 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 {
    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 {
    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 {
    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 {
    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 {
    }
    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 {
    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 {
    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

    View full-size slide

  85. 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

    View full-size slide

  86. 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

    View full-size slide

  87. use regex::Regex;
    fn parse_line_regex(line: &str) -> (Pos, Pos) {
    let re = Regex::new(
    r"Sensor at x=(?P[-]?\d+), y=(?P[-]?\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[-]?\d+), y=(?P[-]?\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[-]?\d+), y=(?P[-]?\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[-]?\d+), y=(?P[-]?\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[-]?\d+), y=(?P[-]?\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[-]?\d+), y=(?P[-]?\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[-]?\d+), y=(?P[-]?\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[-]?\d+), y=(?P[-]?\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

    View full-size slide

  88. pub fn parse_regex(input: &str) -> impl Iterator + '_
    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[-]?\d+), y=(?P[-]?\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

    View full-size slide

  89. How can we initialize the regex globally?
    loige
    $ cargo add lazy_static
    95

    View full-size slide

  90. #[macro_use]
    extern crate lazy_static;
    use regex::Regex;
    lazy_static! {
    static ref LINE_REGEX: Regex = Regex::new(r"Sensor at x=(?P[-]?\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 + '_
    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[-]?\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 + '_
    17
    input.lines().map(parse_line_regex)
    18
    }
    19
    lazy_static! {
    static ref LINE_REGEX: Regex = Regex::new(r"Sensor at x=(?P[-]?\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 + '_
    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[-]?\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 + '_
    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[-]?\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 + '_
    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

    View full-size slide

  91. 🤷 BTW,
    should I tell you that when you solve a
    problem with a Regex... BLAH BLAH BLAH?!
    loige 97

    View full-size slide

  92. Ok, let's do proper parsing with nom!
    💪
    loige
    $ cargo add nom
    98

    View full-size slide

  93. fn parse_i64(input: &str) -> IResult<&str, i64> {
    let (input, sign) = opt(tag("-"))(input)?;
    let (input, value) = digit1(input)?;
    let mut value = value.parse::().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::().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::().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::().unwrap();
    4
    if sign.is_some() {
    5
    value *= -1;
    6
    }
    7
    Ok((input, value))
    8
    }
    9
    let mut value = value.parse::().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::().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::().unwrap();
    if sign.is_some() {
    value *= -1;
    }
    Ok((input, value))
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    loige
    99

    View full-size slide

  94. 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

    View full-size slide

  95. Which one do you think is faster?
    🧐
    loige
    regex
    regex_lazy
    nom
    1.
    2.
    3.
    101

    View full-size slide

  96. Which one do you think is faster?
    🧐
    loige
    regex
    regex_lazy
    nom
    1.
    2.
    3.
    102

    View full-size slide

  97. 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

    View full-size slide

  98. 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

    View full-size slide

  99. 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

    View full-size slide

  100. Photo by on
    Nathan Dumlao Unsplash
    loige 106

    View full-size slide

  101. 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

    View full-size slide