huh, I hadn't heard of Nom before, that's really cool! Definitely a tool to note down for later. I just pulled all the tokens out of a regex 😅
@chrisbiscardi23 күн бұрын
regex worked well for todays too!
@danielxu442613 күн бұрын
This is my regex bench result: day_03_bench fastest │ slowest │ median │ mean │ samples │ iters ├─ part1 253.3 µs │ 882.1 µs │ 262.6 µs │ 274.2 µs │ 100 │ 100 ╰─ part2 5.282 ms │ 7.66 ms │ 5.44 ms │ 5.553 ms │ 100 │ 100 I decided to learn Nom after checking out your benchmark results.
@awdsqe12323 күн бұрын
Nom looks so easy when you do it, but when I try I just get issues between `&str` and `&[u8]` or many other hurdles. :(
@KevinDay23 күн бұрын
I tried it for the first time Sunday, but ended up with an annoying lifetime issue when trying to bubble errors with `anyhow`. I honestly feel like nom's design might be outdated and I don't understand why it's so ubiquitous.
@chrisbiscardi23 күн бұрын
feel free to ask if you're running into trouble. either in the discord or here in the comments. &str vs &[u8] sounds like you might have been working with different input types and such. I usually stick with &str in the videos but nom can also process &[u8] and such as inputs. It looks easy in the video because I've already crossed the knowledge gap and learned the crate and the language.
@chrisbiscardi23 күн бұрын
not understanding something doesn't mean it is outdated. If you were having lifetime issues, are you familiar with how references work in Rust? nom typically works on &str, so if you're creating new data (like String) inside of parsers and trying to return shared references to that new data you could run into this because the String would drop at the end of the function.
@KevinDay23 күн бұрын
@@chrisbiscardi I fully understood *why* the lifetime issue was happening, but working around it would mean adding extra code all over the place that's not idiomatic for anyhow. Also, it has precisely zero integration with async/await, instead having a bespoke "streaming" copy of every module. And most functions automatically collect things into Vecs instead of returning iterators.
@awdsqe12323 күн бұрын
@@chrisbiscardi Yeah, I do like nom and how it's eating the bytes sequentially, but because it's very different from how most other rust libraries it gets a bit confusing. I think I was looking too much at the docs and not enough at the examples and md pages on the github.
@flwi23 күн бұрын
Nice solution! Clever combination of many1 and many_till. Didn't know about those and wrapped everything in Options to discard what I don't need. ``` many0(alt(( map(instruction_parser, Some), // Consume one char and return None if no instruction matches map(anychar, |_| None), ))); ``` Your approach seems more idiomatic to nom imo. At 3:11 you are resizing the terminal window and the vs-code window adjusts its size as well. What magic is that? Looks very useful.
@chrisbiscardi23 күн бұрын
I use yabai for window management on macos: github.com/koekeishiya/yabai
@shrugalic23 күн бұрын
I use Yabai as well, but Aerospace is becoming more popular, and it doesn't need SIP disabled.
@chrisbiscardi23 күн бұрын
@shrugalic I haven't seen aerospace yet, will give it a look
@zkeltonETH23 күн бұрын
Very nice. Gonna have to start using nom for parsing because I was just manually parsing the string input using .split and .find haha
@haemolacriaa23 күн бұрын
I used slices and starts_with, split, and strip_suffix here and honestly I think it's more appropriate for a small problem like this than using a parsing crate, but this would be great for learning that
@bas-ie18 күн бұрын
So helpful, ty!
@ddg-norysq146423 күн бұрын
Using crates feels like cheating. I personally use std only for advent of code
@chrisbiscardi23 күн бұрын
that's a totally valid way to do aoc. I think it would be interesting to do a no_std variation or solve some of the days in a compute shader too.
@haemolacriaa23 күн бұрын
yeah im trying it with only std
@ddg-norysq146422 күн бұрын
@@chrisbiscardi ohhh no_std that would be sick, maybe I'll do that next year
@bas-ie18 күн бұрын
I learn so many useful crates every time I do this though, that's part of the value proposition for me!
@daniel1302122 күн бұрын
I feel like nom is nice but for most scenarios it's over-engineered. The code is more complicated for simple parsers. It's also longer. I really like your videos because that's how i have learned NOM - I was following your AOC in the past. I can now use it, but sometimes it's simpler to use just regex even if it generates heavier code. Regex can be simple as well, and code can be like at most 20 lines long :)
@chrisbiscardi22 күн бұрын
the nom parser for part 1 for today is less than 20 lines long, and its only that long because I wrote it to be readable (and testable/documentatable, which doesn't really hold for regex). There's nothing wrong with using regex, especially on today's problem; it worked out well, but regex is way more complicated than nom... that complexity is largely hidden away in the engine implementation in the crate sure, but its not any less "over-engineered" as you put it. (I don't think either solution is over engineered to be clear). plus if we don't use parsing libraries for parsing problems then why do we have them?
@HirschyKiss22 күн бұрын
I followed your part 1 just because I watched the video at work and was interested in the base nom parsing. For part 2, which I found logically pretty simple, but my own logic was failing me a bit, I diverged and instead of doing the whole `ShouldProcess` additional enum, i did similar logic with an impl function on Instruction impl Instruction { fn multiply(&self, process: Instruction) -> (Instruction, u32) { match (self, process.clone()) { (Instruction::Mul((x, y)), Instruction::Do) => (Instruction::Do, x * y), (Instruction::Dont, _) => (Instruction::Dont, 0), (Instruction::Do, _) => (Instruction::Do, 0), (_, Instruction::Dont) => (Instruction::Dont, 0), _ => (process, 0), } } }