I'm so happy you are doing AoC. I decided to try it in Rust this year (previous years I used Python) and it's great for me to see your videos after I've done my solution so I can refactor my code to be more Rust-idiomatic. Thanks for taking the time. I'll be learning a lot from following along.
@tobiasgraf52462 жыл бұрын
As already said on the first video. Same for me, keep on with the series. It helps so much when I'm finished coding, and your video pops up short after. I can reflect on my own implementation while watching your videos 👍🤗
@WanderWeird2 жыл бұрын
The docs. for PartialOrd state that an implementation must satisfy a transitivity rule: a < b and b < c implies that a < c. As such, it is not really correct to use PartialOrd for Rock, Paper, Scissors.
@chrisbiscardi2 жыл бұрын
mm yeah, I think you're right. This would be a trait implementation that was surprising if it were shipped in a production application. Perhaps I should've used an iter.cycle in the video instead, or just left it to match 🤔
@BlackSharkfr2 жыл бұрын
@@chrisbiscardi This and using the enum coercion is just adding complexity where it's not needed. But you did it just for showing off cool stuff.
@ltsSmitty2 жыл бұрын
I'm doing these in TS each morning and am really enjoying watching these in rust. I know nothing of rust (yet) but I hope you keep going all through advent!
@perc-ai2 жыл бұрын
Hey man a lot of us are moving away from TS and getting into Rust. I can only say amazing things about Rust
@chrisbiscardi2 жыл бұрын
@@perc-ai Rust and TS also work very well together via tools like napi-rs or wasm!
@tenthlegionstudios1343 Жыл бұрын
I appreciate you actually implementing the partial order trait. This is actually a great series for learning Rust. I have finished the Rust book and am going a few other books/projects. But going through advent of code is one of the best ways to learn. Thanks!
@MasterHigure2 жыл бұрын
Technically, you are required to ensure that the ordering of PartialOrd is transitive. The compiler doesn't check it for you, though, which is nice for hacky solutions on a type that will never be used in another project.
@valhalla_dev2 жыл бұрын
lol this is so much more graceful (even if complex) than my "death by if-statements" solution. I'm using AoC to learn Rust better, and you've been a big part of that journey as well. Good luck!
@gareth20212 жыл бұрын
for me rusts powerful match syntax worked great, easy copy pasting xd
@valhalla_dev2 жыл бұрын
@@gareth2021 See the problem is that I'm still so new at Rust that I'm writing it like Python. I didn't use any of the great features Rust has, like the match syntax that Chris shows later in the video, just the if(a == b) type syntax. AoC is teaching me some super powerful lessons on a nightly basis. Today's lessons were: - Read the prompt carefully (got X = loss, Z = win mixed up) - Write Rust code, not Python code in Rust - Use templated code (reading from a text file and splitting on lines, messed up the syntax on that several times costing me precious minutes)
@markday31452 жыл бұрын
@@gareth2021 Yes, this was definitely a good use case for match. I did a split(' ') on the lines, and then matched on a 2-tuple of &str. If I were to do it over again, I think I'd probably just match on the entire line since there are only 9 possibilities (I ended up listing all 9 possibilities for part 2 to figure out why my shape had to be).
@cristobaljavier2 жыл бұрын
It's so interesting to see different ways to solve the challenge as I'm not focusing so much on speed but more on learning in my solutions, and I'm learning a lot here, thanks for sharing.
@peter94772 жыл бұрын
I meant to do AoC (first year) but it turns out my daily life poses enough significant programming challenges that I haven't had a chance even to start. Fortunately I bookmarked this vid on day 1 and I guess I'll learn some more Rust vicariously. Thanks Chris!
@ArgoIo2 жыл бұрын
I really enjoy this series of videos. Though I'm late to the party, I really enjoy working through these problems. I solved this one by calculating a table for the scores, storing it in a HashMap and use it to map over the input.
@adamglass25992 жыл бұрын
it's actually a great demo of the AoC conundrum -- you're rarely sure which tradeoffs to make relative to developer efficiency, complexity, performance, learning value, etc. do you use enums, will the input be interpreted the same way in part 2, is part 2 going to involve shooting for a specific score, etc. You choose a set of tradeoffs and part2 sometimes goes your way and sometimes not. Sometimes i go back and rewrite the solutions for simplicity or clarity with full hindsight.
@aranasaurus2 жыл бұрын
Thanks again for these videos, they are such a huge help! As I was doing it last night I _wanted_ to use some kind of Comparison based approach but wasn't sure how to do it. So I ended up just doing matches inline. It's great to see how this way works. Looking forward to seeing how our solutions differ as the problems get more difficult as they always do.
@kentbowling75132 жыл бұрын
Another possibly way to maybe "complete the loop" on the ordering is possibly adding 1 to the second value (other) when you coerce it into a u8, then mod 4 it. This will cause a "Rock" to have a value of 0 when it's the 2nd (other). It's probably harder to read, but less control flow blocks etc.
@echobucket2 жыл бұрын
I tried making enums for this several different ways, and couldn't figure out how to make it work. Seeing your FromStr trait was an eye opener for me.
@samuelhurel64022 жыл бұрын
Using an Outcome enum made things a lot simpler to me when I did it. Great vid tho, I'll keep watching your videos after completion, always interesting to see how other people are tackling the problem
@chrisbiscardi2 жыл бұрын
yeah! An outcome enum is a great idea. I avoided it because I felt like I spent my complexity budget for the video in part 1 😅
@AceofSpades57572 жыл бұрын
When rushing to finish this one, I too made the rock beats scissors, etc. more complex than it should have been but I didn't know how to do it any better.
@BlackSharkfr2 жыл бұрын
I find matching on moves easier. And you can also use the powerful match syntax to simplify the work : match (their_move, your_move) { (Move::Paper, Move::Scissors) | (Move::Rock, Move::Paper) | (Move::Scissors, Move::Rock) => 6, // Win ! _ if their_move == your_move => 3, // Draw ! _ => 0, // Loose ! }
@chrisbiscardi2 жыл бұрын
yeah, taking advantage of the multiple match syntax is a great way to group similar cases and cut down the 9 lines!
@felixst-gelais67222 жыл бұрын
i love comparing my answers with u! we did pretty much the same thing which i thought was clunky but i dont feel so bad anymore :,)
@dj-maxus Жыл бұрын
Thank you for your awesome videos! Your channel really helps on my path of learning Rust. I was wondering how do you organize your windows this way? Is this some tool which helps you conveniently adjust multiple windows at once?
@chrisbiscardi Жыл бұрын
Glad you're enjoying the videos! I use yabai on macos for window management
@artemivasyuk16992 жыл бұрын
Enums with numbers was a cool thing
@chrisbiscardi2 жыл бұрын
The numbers are actually there by default too! But it starts at 0, which is why I set them up manually.
@amiganer6811302 жыл бұрын
I did it completly different (in Rust). Here we can see more auf the "Rust Way".
@ReedoTV2 жыл бұрын
I started almost exactly the same as you with a Move enum and a from impl. Then I got lazy and just did a match on the 9 possible line strings, returning the score lol.
@chrisbiscardi2 жыл бұрын
That's totally in the spirit of aoc! They're puzzles to have fun with so be sure to have fun!
@gimmypharel2 жыл бұрын
Whats the window tiling manager he uses?
@chrisbiscardi2 жыл бұрын
It's yabai on macos. I go over my setup here: kzbin.info/www/bejne/l6GoiaCAhZqrrtk
@gimmypharel2 жыл бұрын
@@chrisbiscardi thanks!
@awnion2 жыл бұрын
AoC Enterprise edition TM on Rust 😅 GJ!
@amoghrijal2 жыл бұрын
awesome!!!!!! thankyou!!
@dealloc2 жыл бұрын
It's validating that my implementation (which is very similar to yours, again, using traits) wasn't totally out there, although I still feel I was overly complicating the solution, compared to the simplicity of the challenge.
@chrisbiscardi2 жыл бұрын
Yeah definitely. Although Advent of code for me is more about experimentation and pushing the corners of the language I use less often. I match all the time, and I implement partialord manually basically never. The questions can always be done in a competitive style, (less code/structure, more tricks, pattern matching solutions) but that's not how I find it fun.
@dealloc2 жыл бұрын
@@chrisbiscardi Absolutely, I dont want to code golf it. My goal with these exercises is to become more familiar with Rust's language features and higher level abstractions.
@valeth64722 жыл бұрын
My solution is quite similar, I did use a dedicated RoundResult enum though instead of reusing Ordering. Also didn't know that you can do "as " on enum variants, I think I remember trying that in the past and it didn't work, could be wrong though.
@chrisbiscardi2 жыл бұрын
yeah the as cast is a neat trick but in hindsight I probably should've used an impl like this instead, which feels less "tricky". Hard to think of everything when I'm recording live though 😅 ``` impl Move { fn score(&self) -> u32 { match self { Rock => 1, Paper => 2, Scissors => 3 } } } ```
@jamese.spivak41702 жыл бұрын
meh, so many possible ways to implement this, but I like how you did it, even if it was technically a tiny bit more convoluted because I feel like in a real/larger program you would want to separate the logic into the trait like you did
@Neph02 жыл бұрын
I think `matches` were a better tool for today's exercise, great video nonetheless.
@yaksher Жыл бұрын
It's funny because while the implementation demonstrating traits and stuff is neat, in this case, you would probably have been better off just writing a single match statement on strings with 9 arms lmao
@glorkspangle2 жыл бұрын
Abuse of PartialOrd: Rock/Paper/Scissors do not form a partial order (the relation is not transitive). Interesting to see the Rust though.
@avinashthakur802 жыл бұрын
I also tried it in Rust, but you're writing too much of code. Which is good for big projects, but I didn't since it's small project
@verified_tinker18182 жыл бұрын
Thanks for the video! One thing I'd change is add Itertools and use `collect_tuple()` instead of indexing moves, like so: ``` let (opponents, yours) = line .split(' ') .map(|s| s.parse().unwrap()) .collect_tuple() .unwrap(); ``` Functionally, it changes nothing, and perhaps it's even a tad slower, _and_ the extra `unwrap()` call is unwieldy, but indexing feels so inelegant to me. In Part 2, I created an `Outcome` enum and matched it with the opponent's hand to decide my own: ``` let (opponents, outcome) = line.split(' ').collect_tuple().unwrap(); let outcome: Outcome = outcome.parse().unwrap(); let opponents: Hand = opponents.parse().unwrap(); let yours = match (outcome, opponents) { (Outcome::Defeat, Hand::Scissors) | (Outcome::Draw, Hand::Paper) | (Outcome::Victory, Hand::Rock) => Hand::Paper, (Outcome::Defeat, Hand::Rock) | (Outcome::Draw, Hand::Scissors) | (Outcome::Victory, Hand::Paper) => Hand::Scissors, (Outcome::Defeat, Hand::Paper) | (Outcome::Draw, Hand::Rock) | (Outcome::Victory, Hand::Scissors) => Hand::Rock, }; ``` IMO, it's a bit simpler this way, though the flood of unwraps is painful.
@chrisbiscardi2 жыл бұрын
true, but I haven't pulled in Itertools yet, so I don't have access to collect_tuple here.
@CuriousSpy2 жыл бұрын
about your PartialCmp. Try to do match (self, other) { (Move::A, Move::B) => {} }. A lot cleaner
@SighAme2 жыл бұрын
Great 18:42, I made something similar: pub fn part1(data: &str) -> u32 { data.split(' ') .map(|round| -> u32 { let mut round = round.chars(); let opponent = Move::new(round.next()); let you = Move::new(round.nth(1)); match (opponent, you) { (Rock, Rock) => Rock + Draw, (Rock, Paper) => Paper + Win, (Rock, Scissors) => Scissors + Lose, (Paper, Rock) => Rock + Lose, (Paper, Paper) => Paper + Draw, (Paper, Scissors) => Scissors + Win, (Scissors, Rock) => Rock + Win, (Scissors, Paper) => Paper + Lose, (Scissors, Scissors) => Scissors + Draw, } }) .sum() }
@a.l.i.c.e62272 жыл бұрын
I like your code, it's kinda similar to my code too XD
@perc-ai2 жыл бұрын
Who this is beautiful code. I did nearly the same but with if statements.
@perc-ai2 жыл бұрын
@@a.l.i.c.e6227 four gold stars so far 😊
@tommymalm2 жыл бұрын
With some math, tho unreadable for most pub fn main() { println!( "{}", include_bytes!("../input.txt") .split(|b| *b == b' ') .map(|l| ((l[0] - b'A') as i16, (l[2] - b'X') as i16,)) .map(|(a, b)| 1 + b + 3 * (1 + b - a).rem_euclid(3)) .sum::(), ); }
@narigoncs2 жыл бұрын
Just wanted to mention that you can also easily calculate the winning like this: fn get_winning(m: Move) -> Move { ((m as u32 % 3) + 1).into() } and then you implement From for Move!
@narigoncs2 жыл бұрын
Nevermind. I just now understood, that's pretty much what the partial_cmp does