diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 08883cdd..03ab30cf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,6 +1,11 @@ -on: +on: push: workflow_dispatch: + inputs: + force_rebuild: + description: 'Force rebuild all labs (ignores cache)' + type: boolean + default: false repository_dispatch: types: [homework-update] @@ -25,12 +30,13 @@ jobs: - name: Cache complete homework build id: cache-homework-build uses: actions/cache@v4 + if: inputs.force_rebuild != true with: path: hw key: homework-complete-${{ steps.homeworks-hash.outputs.hash }} - name: Clone homeworks repository - if: steps.cache-homework-build.outputs.cache-hit != 'true' + if: steps.cache-homework-build.outputs.cache-hit != 'true' || inputs.force_rebuild == true run: | git clone --depth 1 https://github.com/rust-stuco/homeworks.git homeworks-temp @@ -38,7 +44,7 @@ jobs: id: set-matrix run: | chmod +x .github/scripts/discover-labs.sh - if [ -d "homeworks-temp" ]; then + if [ -d "homeworks-temp" ] || [ "${{ inputs.force_rebuild }}" = "true" ]; then matrix=$(.github/scripts/discover-labs.sh) else # Use empty matrix to skip lab building diff --git a/_data/site.json b/_data/site.json index 20c2449b..126c95f2 100644 --- a/_data/site.json +++ b/_data/site.json @@ -222,11 +222,11 @@ "hw_name": "PokerLab", "hw_handout": "/hw/pokerlab/pokerlab.zip", "hw_writeup": "/hw/pokerlab/doc/pokerlab/index.html", - "hw_released": false, + "hw_released": true, "hw_ec_name": "SummaryLab", "hw_ec_handout": "/hw/summarylab/summarylab.zip", "hw_ec_writeup": "/hw/summarylab/doc/summarylab/index.html", - "hw_ec_released": false, + "hw_ec_released": true, "details_released": true, "slides_released": true, "extras": [ diff --git a/hw/cardlab/cardlab.zip b/hw/cardlab/cardlab.zip deleted file mode 100644 index f66358b5..00000000 Binary files a/hw/cardlab/cardlab.zip and /dev/null differ diff --git a/hw/cardlab/doc/.lock b/hw/cardlab/doc/.lock deleted file mode 100755 index e69de29b..00000000 diff --git a/hw/cardlab/doc/cardlab/all.html b/hw/cardlab/doc/cardlab/all.html deleted file mode 100644 index 8bea884e..00000000 --- a/hw/cardlab/doc/cardlab/all.html +++ /dev/null @@ -1 +0,0 @@ -
Redirecting to ../../cardlab/struct.Card.html...
- - - \ No newline at end of file diff --git a/hw/cardlab/doc/cardlab/index.html b/hw/cardlab/doc/cardlab/index.html deleted file mode 100644 index 3df6e7b7..00000000 --- a/hw/cardlab/doc/cardlab/index.html +++ /dev/null @@ -1,149 +0,0 @@ -The goal of this homework is to make sure that you understand Rust’s Structs and Enums, semantically -known as Algebraic Data Types.
-In this homework, you will be modeling and implementing a Card type, which represents a card in
-a standard deck of 52 playing cards (excluding Jokers).
In the first part of this homework, you will model a Card by defining the fields and enums
-needed to represent a playing card. In the second part, you will then implement some comparison
-methods on Card that somebody using your Card might find useful (that “somebody” could be
-you in the future!).
This writeup is relatively long. Please make sure to read the entire writeup, as it contains -useful information and guidance that will make completing this homework easier!
-The reference solution can be found on our GitHub, but we ask that you first give a solid attempt at -finishing this homework before looking at the solution. If you find yourself stuck, please do not -hesitate to reach out to us for help!
-Finally, in a few weeks, we will ask you to use the Card type that you created in this homework
-to help with a future homework that models a game of Poker. So make sure to spend some time
-understanding what you have written, as you will need to use it in the future!
In the file src/card.rs, you will see a unit struct Card type, as well as several
-implementation blocks. In this first part, you will model the structure of this Card type.
There are many “correct” ways to do this, some more favorable than others. For example, you could
-model a Card like this:
pub struct Card {
- name: String,
-}
-
-let three_of_spades = Card::new(String::from("three of spades"));
-let king_of_spades = Card::new(String::from("king of spades"));
-assert!(three_of_spades < king_of_spades);If we were to adopt this model, how would we implement the logic saying that “three of spades” is
-less than “king of spades”? It is certainly possible, but it is probably tedious and inefficient.
-And what happens if someone writes Card::new(String::from("fourteen of gold"))? Now you also have
-to handle these edge cases.
What if we instead assigned a unique integer to each card? Since we only have 52 cards, this should -be very easy.
- -pub struct Card {
- value: u8,
-}However, how would we assign integers to specific cards? If we say that the integer 2 represents the
-two of diamonds, and the integer 3 represents the three of diamonds, what should represent the two
-of hearts? Of clubs? And even if you did figure out how to represent them, if someone using your
-card type chooses any value other than the 52 you choose for your Card type, you have now have to
-handle those errors.
Again, using a single integer is possible, but it might be painful to implement and error prone.
-For this lab, we will show you a model for Card that eliminates the possibility of incorrect
-state. More specifically, we will model the Card in such a way that it is impossible to create
-an invalid Card.
This model is purposefully inefficient (prioritizing correctness over performance), so if you would -like to try using a model different from the one we suggest, go for it!
-Here is the model for Card that we suggest:
pub struct Card {
- rank: Rank,
- suit: Suit,
-}Since playing cards are uniquely identified by the pair of (Rank, Suit), we can model our code in
-the same way. Rank and Suit can also be enums:
enum Suit {
- /// The Diamond suit, typically represented by a red ♦ symbol.
- Diamond,
- /// The Club suit, typically represented by a black ♣ symbol.
- Club,
- /// The Heart suit, typically represented by a red ♥ symbol.
- Heart,
- /// The Spade suit, typically represented by a black ♠ symbol.
- Spade,
-}
-
-enum Rank {
- /// A number card (2-10).
- Number(Number),
- /// A face card (Ace, King, Queen, Jack).
- Face(Face),
-}Modeling Suit is rather straightforward and obvious, but modeling Rank is a little more
-complicated. Because a card can have both a number as its value and as well as a face, we choose to
-represent the Rank type as an enum (sum type) between a Number type and a Face type.
It is up to you how you want to model Rank. If you choose to follow our model, you will need to
-define a Number and Face type. Additionally, it is likely that you will have to write a lot more
-boilerplate code (as the tradeoff for being more correct).
Once you have finished modeling Card, you can move on to implementation!
You will need to implement 5 public methods on Card in src/card.rs:
Click on the links above for more information on the function specification.
-Note that the last two methods (eq and cmp) are methods on standard library traits. We will
-talk more about traits in a few weeks, but for now just treat these methods as normal implementation
-methods. As you can probably guess, eq implements the == operator and cmp implements the
-remaining comparison operators (<, <=, >=, >).
If you go with our modeling above (with the Suit and Rank types), you will find that you want to
-compare two Rank types together. You can copy and paste the impl <Trait> for Card blocks and
-replace the Card for Rank / Suit and implement those methods to allow comparison for the types
-you have defined.
In other words, you’ll probably want to implement impl PartialEq for Rank, impl Ord for Rank,
-and a few more things. Ask on Piazza or consult the reference solution if you are confused!
We are aware that there is a very easy way to implement the comparison traits with derived traits. -You technically do not have to manually implement all of the comparison traits yourself.
-However, we believe that it is instructive to manually write out the implementations so that you -fully understand the code you are writing. If you do know how to use derived traits, you are -free to use them, but we ask that you make sure you understand exactly what those macros are -doing.
-Once you finish implementing these 5 methods (and pass all of the unit tests in src/tests.rs), you
-are done!
The autograder will run these two commands on your code:
-cargo clippy && cargo fmt --all -- --checkIf the autograder detects any errors from the command above, you will not be able to receive -any points. This may seem strict, but we have decided to follow standard best practices for -Rust.
-By following Rust’s style guidelines, you ensure -that anybody reading your code (who is familiar with Rust) will be able to easily navigate your -code. This can help with diving into an unfamiliar code base, and it also eliminates the need for -debate with others over style rules, saving time and energy.
-See the official guidelines for more information.
-If you are on a unix system, we will try to create a handin.zip automatically for you,
-but you will need to have zip already installed.
If you do not have zip installed on your system, install zip on your machine or use the CMU
-Linux SSH machines. If you need help with this, please reach out to us!
Once you have zip installed, we will create the handin.zip automatically for you (take a peek
-into build.rs file if you’re interested in how this works!).
Once you have the handin.zip file, submit it (and only the zip) to Gradescope.
If you are on a windows system, you can zip the src/ folder manually and upload that to
-Gradescope.
Note that you don’t need to name it handin.zip, you can name it whatever you’d like.
In general, feel free to discuss homeworks with other students! As long as you do not copy someone -else’s work, any communication is fair game.
-All formal questions should be asked on Piazza. Try to discuss on Piazza so that other students can -see your questions and answers as well!
-You can also discuss on Discord, but try to keep any technical questions on Piazza.
-We would like to reiterate that you should let us know if you spent anywhere in significant excess -of an hour on this homework.
-In addition, Rust has a notoriously steep learning curve, so if you find yourself not understanding -the concepts, you should reach out to us and let us know as well — chances are, you’re not the -only one!
-pub struct Card;Represents a standard playing card with a suit and a rank.
-Each card consists of one of the four suits (Diamond, Club, Heart, Spade), as well as a rank -that can be either a number card (2-10) or a face card (Jack, Queen, King, Ace).
-This type implements the traits PartialEq, Eq, PartialOrd, and Ord.
let ace_spades = Card::new("spade", 14);
-let king_spades = Card::new("spade", 13);
-let ten_spades = Card::new("spade", 10);
-let five_spades = Card::new("spade", 5);
-let ace_hearts = Card::new("heart", 14);
-let ace_clubs = Card::new("club", 14);
-
-// Compare cards of same suit but different rank.
-assert!(ace_spades > king_spades);
-assert!(king_spades > ten_spades);
-assert!(ten_spades > five_spades);
-
-// Compare cards of same rank but different suit.
-assert!(ace_spades > ace_hearts);
-assert!(ace_hearts > ace_clubs);
-
-// Test equality between identical cards.
-assert!(ace_spades == Card::new("spade", 14));Creates a new Card instance from a suit name and numeric rank.
-suit - A string representing the suit:
-"diamond""club""heart""spade"rank - A number from 1-13 representing the rank:
-"spade", "heart", "club", "diamond".let ace_of_spades = Card::new("spade", 14);
-let two_of_hearts = Card::new("heart", 2);
-let three_of_clubs = Card::new("club", 3);Returns a string representation of this card’s suit.
-let card = Card::new("club", 3);
-assert_eq!(card.suit_name(), "club");Returns the numeric rank of this card, where number cards = 2-10, and Jack = 11, Queen = 12, -King = 13, and Ace = 14.
-let card = Card::new("club", 3);
-assert_eq!(card.rank_value(), 3);Implements partial ordering between Cards.
Since Cards can always be compared, this is just a wrapper around the Ord implementation.
-See the Ord implementation for more information.
Implements total equality for Card. See the PartialEq implementation for more information.
U::from(self).\nCreates a new Card instance from a suit name and numeric …\nReturns the numeric rank of this card, where number cards …\nReturns a string representation of this card’s suit.")
\ No newline at end of file
diff --git a/hw/cardlab/doc/settings.html b/hw/cardlab/doc/settings.html
deleted file mode 100644
index 61709849..00000000
--- a/hw/cardlab/doc/settings.html
+++ /dev/null
@@ -1 +0,0 @@
-1//! This module contains the definition and implementation of [`Card`], which represents a card in
-2//! a standard deck of 52 cards. [`Card`]s are uniquely identified by their rank (which can be the
-3//! numbers 2-10 or Jack, Queen, King, or Ace) and their suit (which can be Diamond, Club, Heart,
-4//! or Spade).
-5//!
-6//! Note to students: we would like to emphasize that you _do not_ have to represent / model playing
-7//! cards in the same way that we do.
-8//!
-9//! Additionally, we are aware that there is a _very easy_ way to implement the comparison traits
-10//! for all of the relevant subtypes (`Rank`, `Suit`, `Number`, etc.), and we have purposefully not
-11//! implemented them in that way in the reference solution.
-12//!
-13//! If you would like to use derived traits, you are allowed to. However, we felt that it would be
-14//! more instructive to manually write out the implementations in the reference solution.
-15
-16/// Represents a standard playing card with a suit and a rank.
-17///
-18/// Each card consists of one of the four suits (Diamond, Club, Heart, Spade), as well as a rank
-19/// that can be either a number card (2-10) or a face card (Jack, Queen, King, Ace).
-20///
-21/// This type implements the traits [`PartialEq`], [`Eq`], [`PartialOrd`], and [`Ord`].
-22///
-23/// # Examples
-24///
-25/// ```
-26/// # use cardlab::Card;
-27/// #
-28/// let ace_spades = Card::new("spade", 14);
-29/// let king_spades = Card::new("spade", 13);
-30/// let ten_spades = Card::new("spade", 10);
-31/// let five_spades = Card::new("spade", 5);
-32/// let ace_hearts = Card::new("heart", 14);
-33/// let ace_clubs = Card::new("club", 14);
-34///
-35/// // Compare cards of same suit but different rank.
-36/// assert!(ace_spades > king_spades);
-37/// assert!(king_spades > ten_spades);
-38/// assert!(ten_spades > five_spades);
-39///
-40/// // Compare cards of same rank but different suit.
-41/// assert!(ace_spades > ace_hearts);
-42/// assert!(ace_hearts > ace_clubs);
-43///
-44/// // Test equality between identical cards.
-45/// assert!(ace_spades == Card::new("spade", 14));
-46/// ```
-47pub struct Card;
-48
-49impl Card {
-50 /// Creates a new Card instance from a suit name and numeric rank.
-51 ///
-52 /// # Parameters
-53 ///
-54 /// * `suit` - A string representing the suit:
-55 /// * `"diamond"`
-56 /// * `"club"`
-57 /// * `"heart"`
-58 /// * `"spade"`
-59 /// * `rank` - A number from 1-13 representing the rank:
-60 /// * 2-10: Number cards
-61 /// * 11: Jack
-62 /// * 12: Queen
-63 /// * 13: King
-64 /// * 14: Ace
-65 ///
-66 /// # Panics
-67 ///
-68 /// * If suit is not one of: `"spade"`, `"heart"`, `"club"`, `"diamond"`.
-69 /// * If rank is not in the range [2, 14].
-70 ///
-71 /// # Examples
-72 ///
-73 /// ```
-74 /// # use cardlab::Card;
-75 /// #
-76 /// let ace_of_spades = Card::new("spade", 14);
-77 /// let two_of_hearts = Card::new("heart", 2);
-78 /// let three_of_clubs = Card::new("club", 3);
-79 /// ```
-80 pub fn new(suit: &str, rank: u8) -> Self {
-81 todo!("implement me once you've finished modeling `Card`!")
-82 }
-83
-84 /// Returns a string representation of this card's suit.
-85 ///
-86 /// # Examples
-87 ///
-88 /// ```
-89 /// # use cardlab::Card;
-90 /// #
-91 /// let card = Card::new("club", 3);
-92 /// assert_eq!(card.suit_name(), "club");
-93 /// ```
-94 pub fn suit_name(&self) -> &'static str {
-95 todo!("implement me once you've finished modeling `Card`!")
-96 }
-97
-98 /// Returns the numeric rank of this card, where number cards = 2-10, and Jack = 11, Queen = 12,
-99 /// King = 13, and Ace = 14.
-100 ///
-101 /// # Examples
-102 ///
-103 /// ```
-104 /// # use cardlab::Card;
-105 /// #
-106 /// let card = Card::new("club", 3);
-107 /// assert_eq!(card.rank_value(), 3);
-108 /// ```
-109 pub fn rank_value(&self) -> u8 {
-110 todo!("implement me once you've finished modeling `Card`!")
-111 }
-112}
-113
-114/// Implements partial equality comparison between [`Card`]s. Two [`Card`]s are equal if they have
-115/// the same suit and rank.
-116impl PartialEq for Card {
-117 fn eq(&self, other: &Self) -> bool {
-118 todo!("implement me once you've finished modeling `Card`!")
-119 }
-120}
-121
-122/// Implements total equality for [`Card`]. See the `PartialEq` implementation for more information.
-123///
-124/// Since equality is reflexive for [`Card`]s (`a == a`), we implement [`Eq`] for [`Card`].
-125///
-126/// For more information on why [`Eq`] does not have any methods, see the documentation for both
-127/// [`PartialEq`] and [`Eq`].
-128impl Eq for Card {}
-129
-130/// Implements total ordering between [`Card`]s. [`Card`]s are compared first by rank, then by suit
-131/// (Diamond < Club < Heart < Spade) if ranks are equal.
-132impl Ord for Card {
-133 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
-134 todo!("implement me once you've finished modeling `Card`!")
-135 }
-136}
-137
-138/// Implements partial ordering between [`Card`]s.
-139///
-140/// Since [`Card`]s can always be compared, this is just a wrapper around the `Ord` implementation.
-141/// See the `Ord` implementation for more information.
-142impl PartialOrd for Card {
-143 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
-144 Some(self.cmp(other))
-145 }
-146}fn:) to \
- restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \
- enum, trait, type, macro, \
- and const.","Search functions by type signature (e.g., vec -> usize or \
- -> vec or String, enum:Cow -> bool)","You can look for items with an exact name by putting double quotes around \
- your request: \"string\"",`Look for functions that accept or return \
- slices and \
- arrays by writing square \
- brackets (e.g., -> [u8] or [] -> Option)`,"Look for items inside another one by searching for a path: vec::Vec",].map(x=>""+x+"
").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="${value.replaceAll(" ", " ")}`;}else{error[index]=value;}});output+=`The goal of this homework is to tie together several of the things we have talked about over the -past few weeks. This includes code-related topics (such as structs, standard collections, and -generics), but we also want to make sure you understand some of the development tools that Rust -provides (such as crates, modules, and libraries).
-For this lab, we will only give you testing and benchmarking code. You should see a lib.rs file in
-the src/ directory. We want you to structure your code however you would like! If you are unsure,
-you can write all of your code in the lib.rs file and then move things out into different files as
-necessary. If you have trouble setting things up, you can always reference the reference solution on
-our GitHub.
We will additionally give you access to the Cargo.toml file for the first time! There are many
-ways to abuse this. For example, you could import someone else’s implementation of a bloom filter,
-or just import someone else’s implementation of a bit vector.
You are not allowed to import crates that complete this entire lab with minimal effort on your -part. You are allowed to import crates that augment your own implementation in some way. -This includes crates that have “better” hashing functions or even crates with SIMD support.
-We will be checking these manually. If you have any questions about this, or if you are wondering -if a crate is allowed, please let us know!
-In this lab, you will implement a bloom filter! Bloom filters are arguably one of the most important -probabilistic data structures in all of Computer Systems (and perhaps even Computer Science).
-If you are unfamiliar with bloom filters, there are great resources online explaining how they work. -Here are three of many good explanations:
- -TLDR; Bloom filters comprise of 2 main components:
-Since we require 15-122, we will assume you understand how to implement a bit vector. We would
-recommend implementing the bit vector with a vector of bytes, or a Vec<u8>.
If you are unfamiliar with bit vectors, you can read this -for a high-level summary. Please let us know if you need help with this part! You can always -reference the reference solution on our GitHub (as long -as you are not copying and pasting it verbatim).
-As a reminder, you are not allowed to import someone else’s implementation of a bit vector.
-Once you have implemented a bit vector, you must create a BloomFilter type that has the following
-methods:
impl<T: Hash> BloomFilter<T> {
- /// Creates a new `BloomFilter` given the maximum number of elements that will be inserted into
- /// the filter and a bound on the size of the `BloomFilter`'s bitvector.
- pub fn new(num_bits: usize, num_hashes: usize) -> Self { ... }
-
- /// Inserts an element into the bloom filter.
- pub fn insert(&mut self, elem: &T) { ... }
-
- /// Checks if an element might have been previously inserted into the bloom filter.
- pub fn contains(&self, elem: &T) -> bool { ... }
-}Notice that the implementation is generic over T. The structure of your BloomFilter should
-probably look like this:
/// An approximate-membership query / probabilistic data structure that supports point lookups.
-pub struct BloomFilter<T> {
- <-- other fields go here -->
-
- /// A type marker used to express that this `BloomFilter` is generic over a single type.
- ///
- /// Note that this means this `BloomFilter` is _not_ allowed to "store" elements of different
- /// types. Each `BloomFilter` instance is specific to a single type (Monomorphization), but the
- /// type itself is generic.
- ///
- /// We could have gone with the approach of making only hashing generic, but for simplicity we
- /// will only allow the `BloomFilter` to track elements of a single type.
- phantom: PhantomData<T>,
-}Your bloom filter must be generic over any type T, only restricting the methods to T: Hash.
-If you are confused by what this means, please review Week 5’s lecture on Traits, or ask us on
-Piazza!
You’ll definitely want to start by implementing the bit vector. You know how to write unit tests -now, so throw in a few of those to make sure it is correct!
-Once you finish the bit vector, you may want to write some pseudo code for insert and contains
-so that you know what fields your BloomFilter struct needs.
Finally, you will have to decide how you want to hash your elements. There are many, many ways to do -this: some are more efficient, some are easier to implement. Good luck!
-We are purposefully not giving much guidance for this homework. We want this lab to be an exercise -of writing Rust in the “real world.” This means thinking about how to solve the problem yourself, -reading documentation, and using online resources to help you program. You will likely either have -to look up how to hash a value in plain Rust (through the standard library), or you will have to -look up third-party crates that have similar functionality.
-With that being said, we also strongly recommend trying to limit your use of LLMs to help you in -this lab. We obviously cannot prevent you from using them, but you limit your ability to learn by -relying on something else to write code for you.
-There are 4 integration tests located in the tests directory, and 2 benchmarks located in the
-benches directory. To get full credit on this assignment, you must pass all 4 integration tests
-and perform roughly the same or better than our reference solution (by roughly the same, we mean
-it just has to do better than half the performance of our purposefully slow solution).
On Gradescope, the write benchmark takes approximately 7 microseconds, and the read benchmark takes -approximately 19 microseconds (as of 11/6/24).
-Ideally, your implementation should be faster since our reference solution is purposefully slow. -However, we will be lenient with grading this, and as long as you made an effort to try and make it -faster, you will likely get full credit.
-This semester, we are going to attempt an in-person peer review session in our last lecture!
-Since you have almost full agency on how you design your bloom filter, we want to make sure you have -the opportunity to not only look at someone else’s implementation, but also have someone else review -the code that you write and the decisions that you made.
-You will be able to gain extra credit points just by being present, and additional points based on -the review you give and receive.
-More details to come soon!
-The autograder will run these two commands on your code:
-cargo clippy && cargo fmt --all -- --check
-If the autograder detects any errors from the command above, -you will not be able to receive any points. This may seem strict, but we have decided to follow -standard best practices for Rust.
-By following Rust’s style guidelines, -you ensure that anybody reading your code (who is familiar with Rust) will be -able to easily navigate your code. This can help with diving into an unfamiliar code base, -and it also eliminates the need for debate with others over style rules, saving time and energy.
-See the official guidelines for more information.
-If you are on a unix system, we will try to create a handin.zip automatically for you,
-but you will need to have zip already installed.
If you do not have zip installed on your system,
-install zip on your machine or use the CMU Linux SSH machines.
-If you need help with this, please reach out to us!
Once you have zip installed, we will create the handin.zip automatically for you
-(take a peek into build.rs if you’re interested in how this works!).
Once you have the handin.zip file, submit it to Gradescope.
If you are on a windows system, you can zip the src/ folder manually
-and upload that to Gradescope.
Note that you don’t need to name it handin.zip, you can name it whatever you’d like.
In general, feel free to discuss homeworks with other students! -As long as you do not copy someone else’s work, any communication is fair game.
-All formal questions should be asked on Piazza. Try to discuss on Piazza so that -other students can see your questions and answers as well!
-You can also discuss on Discord, but try to keep any technical questions on Piazza.
-We would like to reiterate that you should let us know if you spent -anywhere in significant excess of an hour on this homework.
-In addition, Rust has a notoriously steep learning curve, -so if you find yourself not understanding the concepts, -you should reach out to us and let us know as well — -chances are, you’re not the only one!
-fn:) to \
- restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \
- enum, trait, type, macro, \
- and const.","Search functions by type signature (e.g., vec -> usize or \
- -> vec or String, enum:Cow -> bool)","You can look for items with an exact name by putting double quotes around \
- your request: \"string\"","Look for functions that accept or return \
- slices and \
- arrays by writing \
- square brackets (e.g., -> [u8] or [] -> Option)","Look for items inside another one by searching for a path: vec::Vec",].map(x=>""+x+"
").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="${value.replaceAll(" ", " ")}`}else{error[index]=value}});output+=`The goal of this homework is to familiarize yourself with Rust’s system of Ownership.
-Lecture was heavily based on -Chapter 4 of the Rust Book. -We strongly suggest that you make sure you understand the rules of Ownership before attempting -this homework, and this text is a great place to reference!
-This homework is a bit shorter than the previous one, mainly so you can have extra time to read -through the book and stew with the concepts a bit.
-If you find yourself getting stuck, it might be good to take a small break and go over the borrow -checker’s rules.
-Remember to always read the error messages that the compiler gives you, and as always, we encourage -you to reach out for help!
-Like the previous homework, you will modify 3 files that don’t compile by adding, removing, or -reorganizing code to make them compile! The process should be identical to the previous homework, -except the exercises are now specific to slices.
-When you are done, you should be able to run cargo test with all of the modules (pub mods) in
-src/slices/mod.rs uncommented.
Like the previous section, you will modify 5 files to make them compile. The first 3 exercises
-involve the Vec type, which is an owned type.
For this homework, all you need to know is the vec![] macro and the push method on vectors.
-Recall the vec![] creates a new vector with elements, and push appends an element onto the end
-of a vector.
In this section, you’ll be working with String and &str instead of Vec. Recall that String
-is an owned type and &str is borrowed type.
The first three exercises in src/strings are just like the previous section, where you need to
-make some changes for the functions to compile.
A useful thing to know here is that a &String can be deref coerced into a &str when passed as
-a function parameter (you can imagine it turning into a different type as it enters the function).
Other than that, just remember to always read what the compiler tells you (it may or may not give -away the answer)!
-For strings4.rs, you will need to look at some real documentation.
You could just google the answer, but it would be good to familiarize yourself with official Rust
-documentation! Linked here is the documentation for
-str, which might be useful.
There’s a search bar at the top of the documentation that you should make use of. Try searching for
-a method called trim there!
The autograder will run these two commands on your code:
-cargo clippy && cargo fmt --all -- --checkIf the autograder detects any errors from the command above, you will not be able to receive -any points. This may seem strict, but we have decided to follow standard best practices for -Rust.
-By following Rust’s style guidelines, you ensure -that anybody reading your code (who is familiar with Rust) will be able to easily navigate your -code. This can help with diving into an unfamiliar code base, and it also eliminates the need for -debate with others over style rules, saving time and energy.
-See the official guidelines for more information.
-If you are on a unix system, we will try to create a handin.zip automatically for you,
-but you will need to have zip already installed.
If you do not have zip installed on your system, install zip on your machine or use the CMU
-Linux SSH machines. If you need help with this, please reach out to us!
Once you have zip installed, we will create the handin.zip automatically for you (take a peek
-into build.rs file if you’re interested in how this works!).
Once you have the handin.zip file, submit it (and only the zip) to Gradescope.
If you are on a windows system, you can zip the src/ folder manually and upload that to
-Gradescope.
Note that you don’t need to name it handin.zip, you can name it whatever you’d like.
In general, feel free to discuss homeworks with other students! As long as you do not copy someone -else’s work, any communication is fair game.
-All formal questions should be asked on Piazza. Try to discuss on Piazza so that other students can -see your questions and answers as well!
-You can also discuss on Discord, but try to keep any technical questions on Piazza.
-We would like to reiterate that you should let us know if you spent anywhere in significant excess -of an hour on this homework.
-In addition, Rust has a notoriously steep learning curve, so if you find yourself not understanding -the concepts, you should reach out to us and let us know as well — chances are, you’re not the -only one!
-All examples taken from -rustlings exercises -and practice.rs
-Uncomment each of these and ensure that it compiles with cargo test.
-We recommend uncommenting them one at a time.
-Make sure you read ALL of the error messages! They contain VERY useful information.
All examples taken from practice.rs
-Uncomment each of these and ensure that it compiles with cargo test.
-We recommend uncommenting them one at a time.
-Make sure you read ALL of the error messages! They contain VERY useful information.
All examples taken from -rustlings exercises
-Uncomment each of these and ensure that it compiles with cargo test.
-We recommend uncommenting them one at a time.
-Make sure you read ALL of the error messages! They contain VERY useful information.
1//! All examples taken from
-2//! [rustlings exercises](https://github.com/rust-lang/rustlings/tree/main/exercises/move_semantics)
-3//! and [practice.rs](https://practice.rs/ownership/ownership.html)
-4//!
-5//! Uncomment each of these and ensure that it compiles with `cargo test`.
-6//! We recommend uncommenting them one at a time.
-7//! Make sure you read ALL of the error messages! They contain VERY useful information.
-8
-9// pub mod move_semantics1;
-10// pub mod move_semantics2;
-11// pub mod move_semantics3;
-12// pub mod move_semantics4;
-13// pub mod move_semantics5;1//! All examples taken from [practice.rs](https://practice.rs/compound-types/slice.html)
-2//!
-3//! Uncomment each of these and ensure that it compiles with `cargo test`.
-4//! We recommend uncommenting them one at a time.
-5//! Make sure you read ALL of the error messages! They contain VERY useful information.
-6
-7pub mod slices1;
-8// pub mod slices2;
-9// pub mod slices3;1//! All examples taken from
-2//! [rustlings exercises](https://github.com/rust-lang/rustlings/tree/main/exercises/move_semantics)
-3//!
-4//! Uncomment each of these and ensure that it compiles with `cargo test`.
-5//! We recommend uncommenting them one at a time.
-6//! Make sure you read ALL of the error messages! They contain VERY useful information.
-7
-8// pub mod strings1;
-9// pub mod strings2;
-10// pub mod strings3;
-11// pub mod strings4;fn:) to \
- restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \
- enum, trait, type, macro, \
- and const.","Search functions by type signature (e.g., vec -> usize or \
- -> vec or String, enum:Cow -> bool)","You can look for items with an exact name by putting double quotes around \
- your request: \"string\"",`Look for functions that accept or return \
- slices and \
- arrays by writing square \
- brackets (e.g., -> [u8] or [] -> Option)`,"Look for items inside another one by searching for a path: vec::Vec",].map(x=>""+x+"
").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="${value.replaceAll(" ", " ")}`;}else{error[index]=value;}});output+=`The goal of this homework is to make sure you know how to create a command line tool in Rust, as -well as how to write unit tests for your programs.
-This homework is going to be very different from other homeworks. There is no autograder, and we -will be manually grading your submission for not just correctness but also code quality and -robustness through a code review.
-For this homework, you will follow
-Chapter 12 of the Rust Book and create
-a project called minigrep. Follow the hyperlink and go through all of
-Chapter 12, building minigrep as you
-go along.
There will be no handout for this homework. Instead, run cargo new minigrep in your terminal to
-get started!
We encourage you to not skim through the book and blindly copy and paste any code you see. On top of -asking you to write robust code, we will require one “extra” thing from your submission, which will -check if you actually understand what you are pasting into your submission.
-You must add at least 1 additional feature to minigrep on top of the functionality described in
-the Book. Given this requirement, it will be more efficient for you to read the (relatively short)
-Chapter 12 in its entirety, rather than
-copy and paste everything and then reverse engineer. See the Extra Features
-section below for some potential features you could add. You must document this feature as a
-documentation comment (we will run cargo doc on your submission when we grade it, so it the
-documentation should be in the root of your library crate).
Another soft requirement is that you add unit tests. This won’t count towards the first 100 points, -but will definitely contribute a non-significant amount to your code review score. We care more -about quality over quantity, but you should have at least 2 types of test cases (general -functionality, edge cases, potentially even performance benchmarking if you want to go above and -beyond with criterion).
-The extra feature you want to add is up to you once you’ve finished the base minigrep.
-c or --count, which changes
-the output to show how many lines a pattern is in, rather than printing out all of the lines.regex crate.clap to
-make the command line interface more user-friendly.anyhow or
-thiserror into your error handling code.If you would like to do this with a different third-party crate, please ask us for permission first!
-There are many things that you could do here, so try and be creative if you have time!
-A good source of inspiration would be the man page for
-grep. If you have more than one additional
-feature, we will probably give you extra credit points in your code review.
Whatever you choose, make sure you document it by indicating what your feature is in your
-documentation comments. The very first thing we will do when grading your submission will be running
-cargo doc --open, so make sure it is obvious!
You should also make an effort to include a help message in your binary (triggered by -h or
---help flags). Make sure to include a description of each flag and its behavior. The help message
-should also be printed if the user gives invalid command line arguments.
Your submission will be manually graded, and we will give you a code review. If you simply follow -along the tutorial and add a simple additional feature, you will get a full 100 points on this -assignment. The code review will give you up to 100 extra credit points.
-We are mainly looking at the correctness of your feature (does your feature work how you describe in -your documentation and does it run without modifications), the robustness of your code (architecture -and design), the quality of tests you add, and general style (documentation and comments).
-If you simply follow along the tutorial and add a simple additional feature, you will not score -very well on the code review. A high-quality submission should look very different from the code -presented in the tutorial.
-The way we grade this assignment will be different from almost every Computer Science course here at -CMU, where grading is mainly based on an autograder, and maybe a handful of points deductions for -style. Instead, we will be looking at your code wholistically, judging it based on how people expect -you to write code outside of school.
-However, we understand that this is still a StuCo, which is why this is all for extra credit. -Nevertheless, we still believe that this is an important exercise to go through as you will likely -need to go through this process in the future.
-We are going to be really harsh! This practice is taken from CMU’s Operating Systems course, -15-410/605. Please don’t worry if you receive a low code review -score, and remember that this is all extra credit!
-This time, you will submit the entire minigrep crate to Gradescope (instead of just the src/
-directory)!
Please do not include the target/ subdirectory when you zip the crate’s root folder, either
-manually or with cargo clean. You can always regenerate it with cargo build and cargo test.
Make sure that your code is fully formatted and linted with the following commands:
-cargo clippy && cargo fmt --all -- --checkBy following Rust’s style guidelines, you ensure -that anybody reading your code (who is familiar with Rust) will be able to easily navigate your -code. This can help with diving into an unfamiliar code base, and it also eliminates the need for -debate with others over style rules, saving time and energy.
-See the official guidelines for more information.
-In general, feel free to discuss homeworks with other students! As long as you do not copy someone -else’s work, any communication is fair game.
-All formal questions should be asked on Piazza. Try to discuss on Piazza so that other students can -see your questions and answers as well!
-You can also discuss on Discord, but try to keep any technical questions on Piazza.
-We would like to reiterate that you should let us know if you spent anywhere in significant excess -of an hour on this homework.
-In addition, Rust has a notoriously steep learning curve, so if you find yourself not understanding -the concepts, you should reach out to us and let us know as well — chances are, you’re not the -only one!
--1
#![doc = include_str!("../README.md")]
-fn:) to \
- restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \
- enum, trait, type, macro, \
- and const.","Search functions by type signature (e.g., vec -> usize or \
- -> vec or String, enum:Cow -> bool)","You can look for items with an exact name by putting double quotes around \
- your request: \"string\"","Look for functions that accept or return \
- slices and \
- arrays by writing \
- square brackets (e.g., -> [u8] or [] -> Option)","Look for items inside another one by searching for a path: vec::Vec",].map(x=>""+x+"
").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="fn:) to \
- restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \
- enum, trait, type, macro, \
- and const.","Search functions by type signature (e.g., vec -> usize or \
- -> vec or String, enum:Cow -> bool)","You can look for items with an exact name by putting double quotes around \
- your request: \"string\"","Look for functions that accept or return \
- slices and \
- arrays by writing \
- square brackets (e.g., -> [u8] or [] -> Option)","Look for items inside another one by searching for a path: vec::Vec",].map(x=>""+x+"
").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="${value.replaceAll(" ", " ")}`}else{error[index]=value}});output+=`${value.replaceAll(" ", " ")}`}else{error[index]=value}});output+=`pub fn read_the_docs(n: usize) -> Vec<usize>For every ith number from 0..n, find the sum of the first i
-fibonacci numbers and square that sum.
Then, for each of those squared sums, keep only the ones that are -divisible by 2 or 3.
-Let’s say that there are now m remaining numbers. For every jth
-number from 1..m, integer divide the number by j.
-And since 0 is going to end up being the first of the m numbers anyways,
-don’t do 0 / 0, and just return 0 instead.
Return these numbers as a vector of usize.
You will probably want to implement sum_fib_range before implementing this.
Let’s walk through a call of read_the_docs(6).
The first 6 fibonacci numbers are:
-0, 1, 1, 2, 3, 5
-We want 6 summations:
-0, 1, 2, 4, 7, 12
-Then we square these:
-0, 1, 4, 16, 49, 144
-We keep only those divisible by 2 or 3 (here only even numbers):
-0, 4, 16, 144
-Let’s attach the position of each number to the above:
-value: 0, 4, 16, 144
-index: 0 1 2 3
-Dividing each out:
-0, 4, 8, 48
-Let’s see if this works:
- -assert_eq!(vec![0, 4, 8, 48], read_the_docs(6));This time we will not give you any constraints on how to -implement this function.
-However, you will probably find it a lot easier
-to use iterators and dot chaining than to use a bunch of for loops.
-You may even want to reuse some of the code you wrote for previous parts…
Note that our reference solution is 6 short lines -(which means we have at least 5 chained methods)!
-pub fn sum_fib_range(start: usize, end: usize) -> usizeFind the sum of the range of fibonacci numbers defined by start and end.
You will probably want to implement this before implementing read_the_docs.
Recall the fibonacci numbers from this sequence:
-0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233...
-If we want to sum the 4th to 8th fibonacci number, we would need to sum
-3 + 5 + 8 + 13.
assert_eq!(29, sum_fib_range(4, 8));Try to not use any for loops, if statements, or mutable variables!
-You are also allowed to use code from other parts of this homework.
-Make sure to use the correct things!
By re-using some code from other modules, our reference solution fits in 1 line!
-A lot of documentation, if you choose to read it. -Do this second, and only if you have time to spare.
-ith number from 0..n, find the sum of the first i
-fibonacci numbers and square that sum.start and end.This module contains some functions that require higher-order functions to implement them.
-Implement this module after the iterators module.
We recommend implementing sum_squares before fib_fun, since sum_squares is really
-just a warmup exercise.
See the function documentation within these modules for more information.
-pub fn sum_of_squared_odd_numbers(largest_square: usize) -> usizeMake sure to read the documentation for sum_of_squared_odd_numbers_bad first.
Implement this function to do the same thing as sum_of_squared_odd_numbers_bad,
-but without any for loops, if statements, or mutable variables!
You could just click the link in the bad version’s docs and copy the answer… -but try and do it on your own so you get practice thinking for yourself!
-assert_eq!(35, sum_of_squared_odd_numbers(30));pub fn sum_of_squared_odd_numbers_bad(largest_square: usize) -> usizeFinds the sum of squared odd numbers, where the largest squared odd number
-is less than or equal to largest_square.
The first 4 odd squares are 1, 9, 25, and 49.
-If we call sum_of_squared_odd_numbers_bad(30), this will add together
-1 + 9 + 25 and return 35.
assert_eq!(35, sum_of_squared_odd_numbers_bad(30));Note that we yanked this -example -from Rust by Example.
-Please don’t look at this website until you have read the rest of this file.
-A quick exercise to get familiar with using iterators and higher-order functions. -Do this first.
-sum_of_squared_odd_numbers_bad first.largest_square.The goal of this homework is to make sure you are comfortable with Rust’s Iterators and Closures.
-This homework is more puzzle-oriented than the last few homeworks, where instead of implementing -one relatively complicated thing, you will implement 6 somewhat-less-complicated things.
-Since we’re halfway through the semester, we will be providing less guidance in this writeup. -Remember, you just need to make the tests pass!
-Since you know how to read tests now, we encourage you to read some of the tests -before you start writing any code.
-All tests are located in src/tests.rs.
Click this hyperlink to go to the documentation for iterators!
Click this hyperlink to go to the documentation for hofs!
If you are on a unix system, we will try to create a handin.zip automatically for you,
-but you will need to have zip already installed.
If you do not have zip installed on your system,
-install zip on your machine or use the CMU Linux SSH machines.
-If you need help with this, please reach out to us!
Once you have zip installed, we will create the handin.zip automatically for you
-(take a peek into build.rs if you’re interested in how this works!).
Once you have the handin.zip file, submit it to Gradescope.
If you are on a windows system, you can zip the src/ folder manually
-and upload that to Gradescope.
Note that you don’t need to name it handin.zip, you can name it whatever you’d like.
In general, feel free to discuss homeworks with other students! -As long as you do not copy someone else’s work, any communication is fair game.
-All formal questions should be asked on Piazza. Try to discuss on Piazza so that -other students can see your questions and answers as well!
-You can also discuss on Discord, but try to keep any technical questions on Piazza.
-We would like to reiterate that you should let us know if you spent -anywhere in significant excess of an hour on this homework.
-In addition, Rust has a notoriously steep learning curve, -so if you find yourself not understanding the concepts, -you should reach out to us and let us know as well — -chances are, you’re not the only one!
-pub struct Cycle<I: Clone> { /* private fields */ }A struct that is intended to be an iterator that infinitely cycles through the elements of -another iterator.
-Implement the Iterator trait for Cycle!
Advances the iterator and returns the next item in the cycle.
-This will cycle back to the original iterator when the current iterator is exhausted.
-iter_next_chunk)N values. Read moreiter_advance_by)n elements. Read morenth element of the iterator. Read moreiter_intersperse)separator
-between adjacent items of the original iterator. Read moren elements. Read moren elements, or fewer
-if the underlying iterator ends sooner. Read moreiter_map_windows)f for each contiguous window of size N over
-self and returns an iterator over the outputs of f. Like slice::windows(),
-the windows during mapping overlap as well. Read moreiter_collect_into)iter_is_partitioned)true precede all those that return false. Read moreiterator_try_reduce)try_find)iter_array_chunks)N elements of the iterator at a time. Read moreiter_order_by)Iterator with those
-of another with respect to the specified comparison function. Read morePartialOrd elements of
-this Iterator with those of another. The comparison works like short-circuit
-evaluation, returning a result without comparing the remaining elements.
-As soon as an order can be determined, the evaluation stops and a result is returned. Read moreiter_order_by)Iterator with those
-of another with respect to the specified comparison function. Read moreiter_order_by)Iterator are lexicographically
-less than those of another. Read moreIterator are lexicographically
-less or equal to those of another. Read moreIterator are lexicographically
-greater than those of another. Read moreIterator are lexicographically
-greater than or equal to those of another. Read moreis_sorted)is_sorted)pub struct Double<I> { /* private fields */ }Creates an iterator that doubles each element of an input iterator.
-This iterator yields each element of the original iterator twice in succession. -Is that similar to another thing that you may have implemented in this homework?
-Note that you are allowed to important anything from this crate into this file with use.
Implement the Iterator trait for Double!
Advances the iterator and returns the next doubled element.
-This delegates to the internal Interleave iterator to yield each element twice.
iter_next_chunk)N values. Read moreiter_advance_by)n elements. Read morenth element of the iterator. Read moreiter_intersperse)separator
-between adjacent items of the original iterator. Read moren elements. Read moren elements, or fewer
-if the underlying iterator ends sooner. Read moreiter_map_windows)f for each contiguous window of size N over
-self and returns an iterator over the outputs of f. Like slice::windows(),
-the windows during mapping overlap as well. Read moreiter_collect_into)iter_is_partitioned)true precede all those that return false. Read moreiterator_try_reduce)try_find)iter_array_chunks)N elements of the iterator at a time. Read moreiter_order_by)Iterator with those
-of another with respect to the specified comparison function. Read morePartialOrd elements of
-this Iterator with those of another. The comparison works like short-circuit
-evaluation, returning a result without comparing the remaining elements.
-As soon as an order can be determined, the evaluation stops and a result is returned. Read moreiter_order_by)Iterator with those
-of another with respect to the specified comparison function. Read moreiter_order_by)Iterator are lexicographically
-less than those of another. Read moreIterator are lexicographically
-less or equal to those of another. Read moreIterator are lexicographically
-greater than those of another. Read moreIterator are lexicographically
-greater than or equal to those of another. Read moreis_sorted)is_sorted)pub struct Fibonacci { /* private fields */ }Represents an iterator that generates the Fibonacci sequence.
-Think about what information you need to continuously and efficiently generate the next number -in the sequence? You will want to store that information in this struct.
-Implement the Iterator trait for Fibonacci!
Advances the iterator and returns the next Fibonacci number in the sequence.
-Ask yourself this: when should we return None instead of Some(n)?
iter_next_chunk)N values. Read moreiter_advance_by)n elements. Read morenth element of the iterator. Read moreiter_intersperse)separator between adjacent
-items of the original iterator. Read moreiter_intersperse)separator
-between adjacent items of the original iterator. Read moren elements. Read moren elements, or fewer
-if the underlying iterator ends sooner. Read moreiter_map_windows)f for each contiguous window of size N over
-self and returns an iterator over the outputs of f. Like slice::windows(),
-the windows during mapping overlap as well. Read moreiter_collect_into)iter_is_partitioned)true precede all those that return false. Read moreiterator_try_reduce)try_find)iter_array_chunks)N elements of the iterator at a time. Read moreiter_order_by)Iterator with those
-of another with respect to the specified comparison function. Read morePartialOrd elements of
-this Iterator with those of another. The comparison works like short-circuit
-evaluation, returning a result without comparing the remaining elements.
-As soon as an order can be determined, the evaluation stops and a result is returned. Read moreiter_order_by)Iterator with those
-of another with respect to the specified comparison function. Read moreiter_order_by)Iterator are lexicographically
-less than those of another. Read moreIterator are lexicographically
-less or equal to those of another. Read moreIterator are lexicographically
-greater than those of another. Read moreIterator are lexicographically
-greater than or equal to those of another. Read moreis_sorted)is_sorted)is_sorted)This module contains 4 iterators that you will implement!
-Implement this module before the hofs module.
You don’t have to implement these in the order that we state, but we would recommend -following our suggestions.
-Implement the Fibonacci sequence as an iterator!
This is mainly a warmup for the next 3 parts.
-Implement an iterator that takes as input another iterator, and instead of exhausting the input -iterator when it reaches its last element, cycle back to the first element.
-You’ll need to figure out what information we need to keep track of to implement this iterator,
-and store it in Cycle.
Don’t worry too much about performance here, just make sure it works!
-Given two input iterators, create an iterator that interleaves the outputs of the two iterators.
-Note that we require the two input iterators to have the same associated Item type.
Similarly to Cycle, you will need to figure out what to store in the struct
-Interleave.
Given a single input iterator, double every single output!
-Hint: What is the easiest way to implement this using code you have already written?
-An interleaved iterator! Do this third.
-pub struct Interleave<I, J> { /* private fields */ }Creates an iterator that interleaves elements from two provided iterators.
-This iterator alternates between the first and second iterators until both are exhausted.
-Implement the Iterator trait for Interleave!
Advances the iterator and returns the next interleaved element.
-This alternates between taking elements from the first and second iterators. -If one iterator is exhausted, the remaining elements will be taken from the other iterator.
-iter_next_chunk)N values. Read moreiter_advance_by)n elements. Read morenth element of the iterator. Read moreiter_intersperse)separator
-between adjacent items of the original iterator. Read moren elements. Read moren elements, or fewer
-if the underlying iterator ends sooner. Read moreiter_map_windows)f for each contiguous window of size N over
-self and returns an iterator over the outputs of f. Like slice::windows(),
-the windows during mapping overlap as well. Read moreiter_collect_into)iter_is_partitioned)true precede all those that return false. Read moreiterator_try_reduce)try_find)iter_array_chunks)N elements of the iterator at a time. Read moreiter_order_by)Iterator with those
-of another with respect to the specified comparison function. Read morePartialOrd elements of
-this Iterator with those of another. The comparison works like short-circuit
-evaluation, returning a result without comparing the remaining elements.
-As soon as an order can be determined, the evaluation stops and a result is returned. Read moreiter_order_by)Iterator with those
-of another with respect to the specified comparison function. Read moreiter_order_by)Iterator are lexicographically
-less than those of another. Read moreIterator are lexicographically
-less or equal to those of another. Read moreIterator are lexicographically
-greater than those of another. Read moreIterator are lexicographically
-greater than or equal to those of another. Read moreis_sorted)is_sorted)ith number from 0..n, find the sum of the first i","Find the sum of the range of fibonacci numbers defined by …","Make sure to read the documentation for …","Finds the sum of squared odd numbers, where the largest …","A cycling iterator! Do this second.","A doubled iterator! Do this fourth.","The Fibonacci sequence! Do this first.","An interleaved iterator! Do this third.","A struct that is intended to be an iterator that …","","","","","Returns the argument unchanged.","Calls U::from(self).","","Creates a new Cycle iterator from the given iterator.","Advances the iterator and returns the next item in the …","","","","","Creates an iterator that doubles each element of an input …","","","","","Returns the argument unchanged.","Calls U::from(self).","","Creates a new Double iterator from the given iterator.","Advances the iterator and returns the next doubled element.","","","","","Represents an iterator that generates the Fibonacci …","","","","","Implement a default implementation for Fibonacci, where …","Returns the argument unchanged.","Calls U::from(self).","","Create a new Fibonacci struct starting with the given start…","Advances the iterator and returns the next Fibonacci …","","","","","Creates an iterator that interleaves elements from two …","","","","","Returns the argument unchanged.","Calls U::from(self).","","Creates a new Interleave iterator from the given two …","Advances the iterator and returns the next interleaved …","","","",""],"i":[0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,0,10,10,10,10,10,10,10,10,10,10,10,10,10,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,12,12,12,12,12,12,12,12,12,12,12,12,12],"f":[0,0,0,0,[1,[[2,[1]]]],[[1,1],1],[1,1],[1,1],0,0,0,0,0,[-1,-2,[],[]],[-1,-2,[],[]],[[[3,[-1]]],[[3,[-1]]],[4,4]],[[-1,-2],5,[],[]],[-1,-1,[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,[[3,[-1]]],4],[[[3,[-1]]],6,[4,7]],[-1,-2,[],[]],[-1,[[8,[-2]]],[],[]],[-1,[[8,[-2]]],[],[]],[-1,9,[]],0,[-1,-2,[],[]],[-1,-2,[],[]],[[[10,[-1]]],[[10,[-1]]],4],[[-1,-2],5,[],[]],[-1,-1,[]],[-1,-2,[],[]],[-1,-2,[],[]],[-1,[[10,[-1]]],[7,4]],[[[10,[-1]]],6,[7,4]],[-1,-2,[],[]],[-1,[[8,[-2]]],[],[]],[-1,[[8,[-2]]],[],[]],[-1,9,[]],0,[-1,-2,[],[]],[-1,-2,[],[]],[11,11],[[-1,-2],5,[],[]],[[],11],[-1,-1,[]],[-1,-2,[],[]],[-1,-2,[],[]],[[1,1],11],[11,[[6,[-1]]],[]],[-1,-2,[],[]],[-1,[[8,[-2]]],[],[]],[-1,[[8,[-2]]],[],[]],[-1,9,[]],0,[-1,-2,[],[]],[-1,-2,[],[]],[[[12,[-1,-2]]],[[12,[-1,-2]]],4,4],[[-1,-2],5,[],[]],[-1,-1,[]],[-1,-2,[],[]],[-1,-2,[],[]],[[-1,-2],[[12,[-1,-2]]],7,[[7,[],[[13,[]]]]]],[[[12,[-1,-2]]],6,7,[[7,[],[[13,[]]]]]],[-1,-2,[],[]],[-1,[[8,[-2]]],[],[]],[-1,[[8,[-2]]],[],[]],[-1,9,[]]],"c":[],"p":[[1,"usize"],[5,"Vec",69],[5,"Cycle",12],[10,"Clone",70],[1,"tuple"],[6,"Option",71],[10,"Iterator",72],[6,"Result",73],[5,"TypeId",74],[5,"Double",26],[5,"Fibonacci",40],[5,"Interleave",55],[17,"Item"]],"b":[]}]\
-]'));
-if (typeof exports !== 'undefined') exports.searchIndex = searchIndex;
-else if (window.initSearch) window.initSearch(searchIndex);
diff --git a/hw/iterlab/doc/settings.html b/hw/iterlab/doc/settings.html
deleted file mode 100644
index 565520f6..00000000
--- a/hw/iterlab/doc/settings.html
+++ /dev/null
@@ -1,2 +0,0 @@
-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -
use crate::iterators::fibonacci::Fibonacci;
-
-/// Find the sum of the range of fibonacci numbers defined by `start` and `end`.
-///
-/// You will probably want to implement this before implementing [`read_the_docs`].
-///
-/// # Example:
-///
-/// Recall the fibonacci numbers from this sequence:
-///
-/// ```text
-/// 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233...
-/// ```
-///
-/// If we want to sum the 4th to 8th fibonacci number, we would need to sum
-/// `3 + 5 + 8 + 13`.
-///
-/// ```
-/// # use iterlab::hofs::fib_fun::sum_fib_range;
-/// assert_eq!(29, sum_fib_range(4, 8));
-/// ```
-///
-/// Try to not use any for loops, if statements, or mutable variables!
-///
-/// You are also allowed to use code from other parts of this homework.
-/// Make sure to `use` the correct things!
-///
-/// By re-using some code from other modules, our reference solution fits in 1 line!
-pub fn sum_fib_range(start: usize, end: usize) -> usize {
- todo!()
-}
-
-/// For every `i`th number from `0..n`, find the sum of the first `i`
-/// fibonacci numbers and square that sum.
-///
-/// Then, for each of those squared sums, keep only the ones that are
-/// divisible by 2 or 3.
-///
-/// Let's say that there are now `m` remaining numbers. For every `j`th
-/// number from `1..m`, integer divide the number by `j`.
-/// And since 0 is going to end up being the first of the `m` numbers anyways,
-/// don't do `0 / 0`, and just return 0 instead.
-///
-/// Return these numbers as a vector of `usize`.
-///
-/// You will probably want to implement [`sum_fib_range`] before implementing this.
-///
-/// # Example
-///
-/// Let's walk through a call of `read_the_docs(6)`.
-///
-/// The first 6 fibonacci numbers are:
-/// ```text
-/// 0, 1, 1, 2, 3, 5
-/// ```
-///
-/// We want 6 summations:
-/// ```text
-/// 0, 1, 2, 4, 7, 12
-/// ```
-///
-/// Then we square these:
-/// ```text
-/// 0, 1, 4, 16, 49, 144
-/// ```
-///
-/// We keep only those divisible by 2 or 3 (here only even numbers):
-/// ```text
-/// 0, 4, 16, 144
-/// ```
-///
-/// Let's attach the position of each number to the above:
-/// ```text
-/// value: 0, 4, 16, 144
-/// index: 0 1 2 3
-/// ```
-///
-/// Dividing each out:
-/// ```text
-/// 0, 4, 8, 48
-/// ```
-///
-/// Let's see if this works:
-/// ```
-/// # use iterlab::hofs::fib_fun::read_the_docs;
-/// assert_eq!(vec![0, 4, 8, 48], read_the_docs(6));
-/// ```
-///
-/// ---
-///
-/// This time we will not give you any constraints on how to
-/// implement this function.
-///
-/// However, you will probably find it a lot easier
-/// to use iterators and dot chaining than to use a bunch of `for` loops.
-/// You may even want to reuse some of the code you wrote for previous parts...
-///
-/// Note that our reference solution is 6 short lines
-/// (which means we have at least 5 chained methods)!
-pub fn read_the_docs(n: usize) -> Vec<usize> {
- todo!()
-}
-// Would you have preferred this to be in src/hofs.rs or src/hofs/mod.rs?
-
-//! This module contains some functions that require higher-order functions to implement them.
-//!
-//! Implement this module _after_ the [`iterators`](self) module.
-//!
-//! We recommend implementing [`sum_squares`] _before_ [`fib_fun`], since [`sum_squares`] is really
-//! just a warmup exercise.
-//!
-//! See the function documentation within these modules for more information.
-
-/// A quick exercise to get familiar with using iterators and higher-order functions.
-/// Do this **first**.
-pub mod sum_squares;
-
-/// A lot of documentation, if you choose to read it.
-/// Do this **second**, and only if you have time to spare.
-pub mod fib_fun;
-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -
/// Finds the sum of squared odd numbers, where the largest squared odd number
-/// is less than or equal to `largest_square`.
-///
-/// # Example:
-///
-/// The first 4 odd squares are 1, 9, 25, and 49.
-///
-/// If we call `sum_of_squared_odd_numbers_bad(30)`, this will add together
-/// `1 + 9 + 25` and return 35.
-///
-/// ```
-/// # use iterlab::hofs::sum_squares::sum_of_squared_odd_numbers_bad;
-/// assert_eq!(35, sum_of_squared_odd_numbers_bad(30));
-/// ```
-///
-/// Note that we yanked this
-/// [example](https://doc.rust-lang.org/rust-by-example/fn/hof.html)
-/// from Rust by Example.
-///
-/// _Please_ don't look at this website until you have read the rest of this file.
-pub fn sum_of_squared_odd_numbers_bad(largest_square: usize) -> usize {
- // Imperative approach
-
- // Declare accumulator variable
- let mut acc = 0;
- // Iterate: 0, 1, 2, ... to infinity
- for n in 0.. {
- // Square the number
- let n_squared = n * n;
-
- if n_squared > largest_square {
- // Break loop if exceeded the upper limit
- break;
- } else if n_squared % 2 == 1 {
- // Accumulate value, if it's odd
- acc += n_squared;
- }
- }
-
- acc
-}
-
-/// Make sure to read the documentation for [`sum_of_squared_odd_numbers_bad`] first.
-///
-/// Implement this function to do the same thing as [`sum_of_squared_odd_numbers_bad`],
-/// but without any `for` loops, `if` statements, or `mut`able variables!
-///
-/// You _could_ just click the link in the bad version's docs and copy the answer...
-/// but try and do it on your own so you get practice thinking for yourself!
-///
-/// # Example:
-///
-/// ```
-/// # use iterlab::hofs::sum_squares::sum_of_squared_odd_numbers;
-/// assert_eq!(35, sum_of_squared_odd_numbers(30));
-/// ```
-pub fn sum_of_squared_odd_numbers(largest_square: usize) -> usize {
- todo!()
-}
-/// A struct that is intended to be an iterator that infinitely cycles through the elements of
-/// another iterator.
-#[derive(Clone)]
-pub struct Cycle<I: Clone> {
- todo: std::marker::PhantomData<I>, // Replace me!
-}
-
-impl<I: Clone> Cycle<I> {
- /// Creates a new `Cycle` iterator from the given iterator.
- pub fn new(iter: I) -> Self {
- todo!()
- }
-}
-
-/// Implement the `Iterator` trait for `Cycle`!
-impl<I: Clone + Iterator> Iterator for Cycle<I> {
- /// Output the same type as the input.
- type Item = <I as Iterator>::Item;
-
- /// Advances the iterator and returns the next item in the cycle.
- ///
- /// This will cycle back to the original iterator when the current iterator is exhausted.
- fn next(&mut self) -> Option<<I as Iterator>::Item> {
- todo!()
- }
-}
-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -
use super::interleave::Interleave;
-
-/// Creates an iterator that doubles each element of an input iterator.
-///
-/// This iterator yields each element of the original iterator twice in succession.
-/// Is that similar to another thing that you may have implemented in this homework?
-///
-/// Note that you are allowed to important anything from this crate into this file with `use`.
-#[derive(Clone)]
-pub struct Double<I> {
- todo: std::marker::PhantomData<I>, // Replace me!
-}
-
-impl<I> Double<I>
-where
- I: Iterator + Clone,
-{
- /// Creates a new `Double` iterator from the given iterator.
- pub fn new(iter: I) -> Self {
- todo!()
- }
-}
-
-/// Implement the `Iterator` trait for `Double`!
-impl<I: Iterator + Clone> Iterator for Double<I> {
- /// Output the same type as the input.
- type Item = <I as Iterator>::Item;
-
- /// Advances the iterator and returns the next doubled element.
- ///
- /// This delegates to the internal `Interleave` iterator to yield each element twice.
- fn next(&mut self) -> Option<<I as Iterator>::Item> {
- todo!()
- }
-}
-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -
/// Represents an iterator that generates the Fibonacci sequence.
-///
-/// Think about what information you need to continuously and efficiently generate the next number
-/// in the sequence? You will want to store that information in this struct.
-#[derive(Clone)]
-pub struct Fibonacci {
- todo: (), // Replace me!
-}
-
-impl Default for Fibonacci {
- /// Implement a default implementation for `Fibonacci`, where the sequence starts with 0 and 1.
- fn default() -> Self {
- todo!()
- }
-}
-
-impl Fibonacci {
- /// Create a new `Fibonacci` struct starting with the given `start` and `next` values.
- pub fn new(start: usize, next: usize) -> Self {
- todo!()
- }
-}
-
-/// Implement the `Iterator` trait for `Fibonacci`!
-impl Iterator for Fibonacci {
- /// What should iterated type be?
- type Item = i8;
-
- /// Advances the iterator and returns the next Fibonacci number in the sequence.
- ///
- /// Ask yourself this: when should we return `None` instead of `Some(n)`?
- fn next(&mut self) -> Option<Self::Item> {
- todo!()
- }
-}
-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -
/// Creates an iterator that interleaves elements from two provided iterators.
-///
-/// This iterator alternates between the first and second iterators until both are exhausted.
-#[derive(Clone)]
-pub struct Interleave<I, J> {
- todo1: std::marker::PhantomData<I>, // Replace me!
- todo2: std::marker::PhantomData<J>, // Replace me!
-}
-
-impl<I, J> Interleave<I, J>
-where
- I: Iterator,
- J: Iterator<Item = I::Item>,
-{
- /// Creates a new `Interleave` iterator from the given two iterators.
- ///
- /// Both iterators must have the same element type.
- pub fn new(first_iter: I, second_iter: J) -> Self {
- todo!()
- }
-}
-
-/// Implement the `Iterator` trait for `Interleave`!
-impl<I, J> Iterator for Interleave<I, J>
-where
- I: Iterator,
- J: Iterator<Item = I::Item>, // Both iterators should yield the same type
-{
- /// Output the same type as the input.
- type Item = <I as Iterator>::Item;
-
- /// Advances the iterator and returns the next interleaved element.
- ///
- /// This alternates between taking elements from the first and second iterators.
- /// If one iterator is exhausted, the remaining elements will be taken from the other iterator.
- fn next(&mut self) -> Option<<I as Iterator>::Item> {
- todo!()
- }
-}
-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -
// Would you have preferred this to be in src/iterators.rs or src/iterators/mod.rs?
-
-//! This module contains 4 iterators that you will implement!
-//!
-//! Implement this module _before_ the [`hofs`](self) module.
-//!
-//! You don't _have_ to implement these in the order that we state, but we would recommend
-//! following our suggestions.
-//!
-//!
-//! # Fibonacci
-//!
-//! Implement the [`Fibonacci`](fibonacci::Fibonacci) sequence as an iterator!
-//!
-//! This is mainly a warmup for the next 3 parts.
-//!
-//!
-//! # Cycle
-//!
-//! Implement an iterator that takes as input another iterator, and instead of exhausting the input
-//! iterator when it reaches its last element, cycle back to the first element.
-//!
-//! You'll need to figure out what information we need to keep track of to implement this iterator,
-//! and store it in [`Cycle`](cycle::Cycle).
-//!
-//! Don't worry too much about performance here, just make sure it works!
-//!
-//!
-//! # Interleave
-//!
-//! Given two input iterators, create an iterator that interleaves the outputs of the two iterators.
-//! Note that we require the two input iterators to have the same associated `Item` type.
-//!
-//! Similarly to [`Cycle`](cycle::Cycle), you will need to figure out what to store in the struct
-//! [`Interleave`](interleave::Interleave).
-//!
-//!
-//! # Double
-//!
-//! Given a single input iterator, double every single output!
-//!
-//! Hint: What is the _easiest_ way to implement this using code you have already written?
-
-/// The Fibonacci sequence! Do this **first**.
-pub mod fibonacci;
-
-/// A cycling iterator! Do this **second**.
-pub mod cycle;
-
-/// An interleaved iterator! Do this **third**.
-pub mod interleave;
-
-/// A doubled iterator! Do this **fourth**.
-pub mod double;
-fn:) to \
- restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \
- enum, trait, type, macro, \
- and const.","Search functions by type signature (e.g., vec -> usize or \
- -> vec or String, enum:Cow -> bool)","You can look for items with an exact name by putting double quotes around \
- your request: \"string\"","Look for functions that accept or return \
- slices and \
- arrays by writing \
- square brackets (e.g., -> [u8] or [] -> Option)","Look for items inside another one by searching for a path: vec::Vec",].map(x=>""+x+"
").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="${value.replaceAll(" ", " ")}`}else{error[index]=value}});output+=`The goal of this homework is to make sure you are comfortable with some of the generic collection
-types in the std::collections module.
You will implement two data structures that track multiplicity (the number of times elements appear) -on top of their normal operations.
-The first will be a MultiSet, which is a set that can have
-duplicate entries. The second will be a MultiMap, which is a map that
-maps keys to any number of values.
For MultiSet, we have not provided what types the fields should be.
-We recommend that you use one of the collection types provided in the std::collections module
-to help you build these new types.
We would like you think a bit more about your own code than previous homeworks, so we will be -providing less detail than before on implementation details. Instead, you should read the -documentation and implement the data structure and methods so that they follow the documentation and -pass all the test cases.
-MultiSetClick this hyperlink to go to the documentation for MultiSet!
MultiMapClick this hyperlink to go to the documentation for MultiMap!
The autograder will run these two commands on your code:
-cargo clippy && cargo fmt --all -- --checkIf the autograder detects any errors from the command above, you will not be able to receive -any points. This may seem strict, but we have decided to follow standard best practices for -Rust.
-By following Rust’s style guidelines, you ensure -that anybody reading your code (who is familiar with Rust) will be able to easily navigate your -code. This can help with diving into an unfamiliar code base, and it also eliminates the need for -debate with others over style rules, saving time and energy.
-See the official guidelines for more information.
-If you are on a unix system, we will try to create a handin.zip automatically for you,
-but you will need to have zip already installed.
If you do not have zip installed on your system, install zip on your machine or use the CMU
-Linux SSH machines. If you need help with this, please reach out to us!
Once you have zip installed, we will create the handin.zip automatically for you (take a peek
-into build.rs file if you’re interested in how this works!).
Once you have the handin.zip file, submit it (and only the zip) to Gradescope.
If you are on a windows system, you can zip the src/ folder manually and upload that to
-Gradescope.
Note that you don’t need to name it handin.zip, you can name it whatever you’d like.
In general, feel free to discuss homeworks with other students! As long as you do not copy someone -else’s work, any communication is fair game.
-All formal questions should be asked on Piazza. Try to discuss on Piazza so that other students can -see your questions and answers as well!
-You can also discuss on Discord, but try to keep any technical questions on Piazza.
-We would like to reiterate that you should let us know if you spent anywhere in significant excess -of an hour on this homework.
-In addition, Rust has a notoriously steep learning curve, so if you find yourself not understanding -the concepts, you should reach out to us and let us know as well — chances are, you’re not the -only one!
-pub struct MultiMap<K: Hash + Eq, V: Eq> {
- pub inner: HashMap<K, Vec<V>>,
-}A multimap that associates keys with multiple values.
-This structure is similar to a HashMap, but it allows multiple values to be
-associated with a single key, instead of the usual one-to-one mapping.
-It is implemented using a HashMap where each
-value is a Vec of the associated values.
let mut multimap = MultiMap::new();
-multimap.insert(1, "hello");
-multimap.insert(1, "world");
-multimap.insert(2, "foo");
-
-assert_eq!(multimap.get_values(&1).unwrap(), &["hello", "world"]);
-assert_eq!(multimap.get_values(&2).unwrap(), &["foo"]);Eq + HashSee the note in the documentation for MultiSet.
Note that unlike MultiSet, it is fine to expose the
-inner hash table here because we are not storing any other metadata
-(in the previous section, you probably had more than one field tracking data).
-This means that an outsider can’t mess up our data structure by breaking any invariants.
-So this type is really just a wrapper around the inner data structure
-that provides some useful methods.
Also, we wanted to expose it to help with our test cases 😊.
-inner: HashMap<K, Vec<V>>The internal HashMap storing the key-value associations.
Inserts a key-value pair into the MultiMap.
If the key already exists, the value is added to the existing vector of values.
-let mut multimap = MultiMap::new();
-multimap.insert(1, "hello");
-multimap.insert(1, "world");
-
-assert_eq!(multimap.get_values(&1).unwrap(), &["hello", "world"]);Removes a specific value from the values associated with a key.
-Returns true if the value was removed, false if the key or value was not found.
Note that removing all values of a key will remove the key itself and the
-Vec<V> mapped to it.
let mut multimap: MultiMap<i32, &'static str> = MultiMap::new();
-multimap.insert(1, "hello");
-multimap.insert(1, "world");
-
-assert!(multimap.remove_value(&1, &"hello"));
-assert_eq!(multimap.get_values(&1).unwrap(), &["world"]);Removes all values associated with a key and returns them.
-Returns None if the key was not found.
let mut multimap = MultiMap::new();
-multimap.insert(1, "hello");
-multimap.insert(1, "world");
-
-assert_eq!(multimap.remove_key(&1).unwrap(), &["hello", "world"]);
-assert!(multimap.get_values(&1).is_none());Gets the values associated with a key, if any.
-Returns a reference to the vector of values if the key exists, otherwise None.
-The returned reference is immutable and can’t be modified.
let mut multimap = MultiMap::new();
-multimap.insert(1, "hello");
-
-assert_eq!(multimap.get_values(&1).unwrap(), &["hello"]);As an exercise, see if you can convert the return type to be Option<&[V]> instead.
-All of the tests cases should still be able to compile!
Gets a mutable reference to the values associated with a key, if any.
-Returns a mutable reference to the vector of values if the key exists, otherwise None.
let mut multimap = MultiMap::new();
-multimap.insert(1, "hello");
-
-if let Some(values) = multimap.get_values_mut(&1) {
- values.push("world");
-}
-
-assert_eq!(multimap.get_values(&1).unwrap(), &["hello", "world"]);pub struct MultiSet<K: Eq + Hash> { /* private fields */ }A multiset that can store elements of type K.
Multisets, also known as bags, are collections that allow for duplicate elements. -This type efficiently tracks the multiplicity of each element.
-let mut words = MultiSet::new();
-words.insert("hello");
-words.insert("world");
-words.insert("hello");
-
-assert_eq!(words.count(&"hello"), 2); // "hello" appears twice
-assert_eq!(words.count(&"world"), 1);You will need to decide what private fields your type should have. We would recommend
-looking at the std::collections module and see if there are any collections there that
-could be helpful for this problem!
-Once you have an idea, replace the _replace_me with your own fields!
Eq + HashFor now, ignore the Eq + Hash annotation next to the generic. These are traits, and
-we will talk about them next week. This annotation is saying that we must be able to
-check equality between two values of type K, and that K must have some
-hash method that allows us to hash an element of type K.
-This may or may not be useful for the inner data structure that you choose…
This shouldn’t have any effect your implementation, -but if you run into trouble with this, please let us know!
-Removes an element.
-If the element does not exist in the MultiSet,
-returns false. Otherwise, it removes and returns true.
Remove 5 from a new MultiSet:
let mut multiset: MultiSet<i32> = MultiSet::new();
-multiset.insert(5);
-assert_eq!(1, multiset.count(&5));
-assert!(multiset.remove(&5));
-assert_eq!(0, multiset.count(&5));
-assert!(!multiset.remove(&5));HashMap storing the key-value associations.\nInserts a key-value pair into the MultiMap.\nCalls U::from(self).\nCreates a new, empty MultiMap.\nRemoves all values associated with a key and returns them.\nRemoves a specific value from the values associated with a …\nA multiset that can store elements of type K.\nChecks if a given value is in the MultiSet.\nCounts the occurrences of value.\nReturns the argument unchanged.\nInserts an element.\nCalls U::from(self).\nChecks if a MultiSet is empty.\nCounts all the elements, including each duplicate.\nCreates a new empty MultiSet.\nRemoves an element.")
\ No newline at end of file
diff --git a/hw/multilab/doc/settings.html b/hw/multilab/doc/settings.html
deleted file mode 100644
index e03061c5..00000000
--- a/hw/multilab/doc/settings.html
+++ /dev/null
@@ -1 +0,0 @@
-1use std::collections::HashMap;
-2use std::hash::Hash;
-3
-4/// A multimap that associates keys with multiple values.
-5///
-6/// This structure is similar to a [`HashMap`], but it allows multiple values to be
-7/// associated with a single key, instead of the usual one-to-one mapping.
-8/// It is implemented using a [`HashMap`] where each
-9/// value is a [`Vec`] of the associated values.
-10///
-11/// # Examples
-12///
-13/// ```rust
-14/// # use multilab::multimap::MultiMap;
-15/// #
-16/// let mut multimap = MultiMap::new();
-17/// multimap.insert(1, "hello");
-18/// multimap.insert(1, "world");
-19/// multimap.insert(2, "foo");
-20///
-21/// assert_eq!(multimap.get_values(&1).unwrap(), &["hello", "world"]);
-22/// assert_eq!(multimap.get_values(&2).unwrap(), &["foo"]);
-23/// ```
-24///
-25/// ### `Eq + Hash`
-26/// See the note in the documentation for [`MultiSet`](crate::multiset::MultiSet).
-27///
-28/// ### Public Field
-29///
-30/// Note that unlike [`MultiSet`](crate::multiset::MultiSet), it is fine to expose the
-31/// inner hash table here because we are not storing any other metadata
-32/// (in the previous section, you probably had more than one field tracking data).
-33/// This means that an outsider can't mess up our data structure by breaking any invariants.
-34/// So this type is really just a wrapper around the inner data structure
-35/// that provides some useful methods.
-36///
-37/// Also, we wanted to expose it to help with our test cases 😊.
-38#[derive(Debug)]
-39pub struct MultiMap<K: Hash + Eq, V: Eq> {
-40 /// The internal [`HashMap`] storing the key-value associations.
-41 pub inner: HashMap<K, Vec<V>>,
-42}
-43
-44impl<K: Hash + Eq, V: Eq> MultiMap<K, V> {
-45 /// Creates a new, empty [`MultiMap`].
-46 pub fn new() -> Self {
-47 todo!()
-48 }
-49
-50 /// Inserts a key-value pair into the [`MultiMap`].
-51 ///
-52 /// If the key already exists, the value is added to the existing vector of values.
-53 ///
-54 /// # Examples
-55 ///
-56 /// ```rust
-57 /// # use multilab::multimap::MultiMap;
-58 /// #
-59 /// let mut multimap = MultiMap::new();
-60 /// multimap.insert(1, "hello");
-61 /// multimap.insert(1, "world");
-62 ///
-63 /// assert_eq!(multimap.get_values(&1).unwrap(), &["hello", "world"]);
-64 /// ```
-65 pub fn insert(&mut self, key: K, value: V) {
-66 todo!()
-67 }
-68
-69 /// Removes a specific value from the values associated with a key.
-70 ///
-71 /// Returns `true` if the value was removed, `false` if the key or value was not found.
-72 ///
-73 /// Note that removing all values of a key will remove the key itself and the
-74 /// `Vec<V>` mapped to it.
-75 ///
-76 /// # Examples
-77 ///
-78 /// ```rust
-79 /// # use multilab::multimap::MultiMap;
-80 /// #
-81 /// let mut multimap: MultiMap<i32, &'static str> = MultiMap::new();
-82 /// multimap.insert(1, "hello");
-83 /// multimap.insert(1, "world");
-84 ///
-85 /// assert!(multimap.remove_value(&1, &"hello"));
-86 /// assert_eq!(multimap.get_values(&1).unwrap(), &["world"]);
-87 /// ```
-88 #[allow(clippy::needless_range_loop)]
-89 pub fn remove_value(&mut self, key: &K, value: &V) -> bool {
-90 todo!()
-91 }
-92
-93 /// Removes all values associated with a key and returns them.
-94 ///
-95 /// Returns `None` if the key was not found.
-96 ///
-97 /// # Examples
-98 ///
-99 /// ```rust
-100 /// # use multilab::multimap::MultiMap;
-101 /// #
-102 /// let mut multimap = MultiMap::new();
-103 /// multimap.insert(1, "hello");
-104 /// multimap.insert(1, "world");
-105 ///
-106 /// assert_eq!(multimap.remove_key(&1).unwrap(), &["hello", "world"]);
-107 /// assert!(multimap.get_values(&1).is_none());
-108 /// ```
-109 pub fn remove_key(&mut self, key: &K) -> Option<Vec<V>> {
-110 todo!()
-111 }
-112
-113 /// Gets the values associated with a key, if any.
-114 ///
-115 /// Returns a reference to the vector of values if the key exists, otherwise `None`.
-116 /// The returned reference is immutable and can't be modified.
-117 ///
-118 /// # Examples
-119 ///
-120 /// ```rust
-121 /// # use multilab::multimap::MultiMap;
-122 /// #
-123 /// let mut multimap = MultiMap::new();
-124 /// multimap.insert(1, "hello");
-125 ///
-126 /// assert_eq!(multimap.get_values(&1).unwrap(), &["hello"]);
-127 /// ```
-128 ///
-129 /// # Challenge
-130 ///
-131 /// As an exercise, see if you can convert the return type to be `Option<&[V]>` instead.
-132 /// All of the tests cases should still be able to compile!
-133 pub fn get_values(&self, key: &K) -> Option<&[V]> {
-134 todo!()
-135 }
-136
-137 /// Gets a mutable reference to the values associated with a key, if any.
-138 ///
-139 /// Returns a mutable reference to the vector of values if the key exists, otherwise `None`.
-140 ///
-141 /// # Examples
-142 ///
-143 /// ```rust
-144 /// # use multilab::multimap::MultiMap;
-145 /// #
-146 /// let mut multimap = MultiMap::new();
-147 /// multimap.insert(1, "hello");
-148 ///
-149 /// if let Some(values) = multimap.get_values_mut(&1) {
-150 /// values.push("world");
-151 /// }
-152 ///
-153 /// assert_eq!(multimap.get_values(&1).unwrap(), &["hello", "world"]);
-154 /// ```
-155 pub fn get_values_mut(&mut self, key: &K) -> Option<&mut Vec<V>> {
-156 todo!()
-157 }
-158}
-159
-160impl<K, V> Default for MultiMap<K, V>
-161where
-162 K: Eq + Hash,
-163 V: Eq,
-164{
-165 fn default() -> Self {
-166 Self::new()
-167 }
-168}1use std::collections::HashMap;
-2use std::hash::Hash;
-3
-4/// A multiset that can store elements of type `K`.
-5///
-6/// Multisets, also known as bags, are collections that allow for duplicate elements.
-7/// This type efficiently tracks the multiplicity of each element.
-8///
-9/// # Examples
-10///
-11/// ```
-12/// # use multilab::multiset::MultiSet;
-13/// #
-14/// let mut words = MultiSet::new();
-15/// words.insert("hello");
-16/// words.insert("world");
-17/// words.insert("hello");
-18///
-19/// assert_eq!(words.count(&"hello"), 2); // "hello" appears twice
-20/// assert_eq!(words.count(&"world"), 1);
-21/// ```
-22///
-23/// You will need to decide what private fields your type should have. We would recommend
-24/// looking at the [`std::collections`] module and see if there are any collections there that
-25/// could be helpful for this problem!
-26/// Once you have an idea, replace the `_replace_me` with your own fields!
-27///
-28/// ### `Eq + Hash`
-29/// For now, ignore the `Eq + Hash` annotation next to the generic. These are _traits_, and
-30/// we will talk about them next week. This annotation is saying that we must be able to
-31/// check equality between two values of type `K`, and that `K` must have some
-32/// hash method that allows us to hash an element of type `K`.
-33/// _This may or may not be useful for the inner data structure that you choose..._
-34///
-35/// This shouldn't have any effect your implementation,
-36/// but if you run into trouble with this, please let us know!
-37pub struct MultiSet<K: Eq + Hash> {
-38 _replace_me: std::marker::PhantomData<K>
-39}
-40
-41impl<K> MultiSet<K>
-42where
-43 K: Eq + Hash,
-44{
-45 /// Creates a new empty [`MultiSet`].
-46 pub fn new() -> Self {
-47 todo!()
-48 }
-49
-50 /// Checks if a [`MultiSet`] is empty.
-51 ///
-52 /// # Examples
-53 ///
-54 /// A new empty [`MultiSet`] with 0 total elements:
-55 ///
-56 /// ```
-57 /// # use multilab::multiset::MultiSet;
-58 /// #
-59 /// let multiset: MultiSet<char> = MultiSet::new();
-60 /// assert_eq!(0, multiset.len());
-61 /// ```
-62 pub fn is_empty(&self) -> bool {
-63 todo!()
-64 }
-65
-66 /// Counts all the elements, including each duplicate.
-67 ///
-68 /// # Examples
-69 ///
-70 /// A [`MultiSet`] after insering 1, 2, and 1 has 3 total elements:
-71 ///
-72 /// ```
-73 /// # use multilab::multiset::MultiSet;
-74 /// #
-75 /// let mut multiset = MultiSet::new();
-76 /// multiset.insert(1);
-77 /// multiset.insert(2);
-78 /// multiset.insert(1);
-79 /// assert_eq!(multiset.len(), 3);
-80 /// ```
-81 pub fn len(&self) -> usize {
-82 todo!()
-83 }
-84
-85 /// Checks if a given value is in the [`MultiSet`].
-86 ///
-87 /// # Examples
-88 ///
-89 /// ```
-90 /// # use multilab::multiset::MultiSet;
-91 /// #
-92 /// let mut multiset = MultiSet::new();
-93 /// multiset.insert(1);
-94 /// multiset.insert(2);
-95 /// multiset.insert(1);
-96 /// assert!(multiset.contains(&1));
-97 /// assert!(multiset.contains(&2));
-98 /// assert!(!multiset.contains(&3));
-99 /// ```
-100 pub fn contains(&self, value: &K) -> bool {
-101 todo!()
-102 }
-103
-104 /// Inserts an element.
-105 ///
-106 /// # Examples
-107 ///
-108 /// Insert `5` into a new [`MultiSet`]:
-109 ///
-110 /// ```
-111 /// use multilab::multiset::MultiSet;
-112 ///
-113 /// let mut multiset: MultiSet<i32> = MultiSet::new();
-114 /// assert_eq!(0, multiset.count(&5));
-115 /// multiset.insert(5);
-116 /// assert_eq!(1, multiset.count(&5));
-117 /// ```
-118 pub fn insert(&mut self, value: K) {
-119 todo!()
-120 }
-121
-122 /// Removes an element.
-123 ///
-124 /// If the element does not exist in the [`MultiSet`],
-125 /// returns false. Otherwise, it removes and returns true.
-126 ///
-127 /// # Examples
-128 ///
-129 /// Remove `5` from a new [`MultiSet`]:
-130 ///
-131 /// ```
-132 /// # use multilab::multiset::MultiSet;
-133 /// #
-134 /// let mut multiset: MultiSet<i32> = MultiSet::new();
-135 /// multiset.insert(5);
-136 /// assert_eq!(1, multiset.count(&5));
-137 /// assert!(multiset.remove(&5));
-138 /// assert_eq!(0, multiset.count(&5));
-139 /// assert!(!multiset.remove(&5));
-140 /// ```
-141 pub fn remove(&mut self, value: &K) -> bool {
-142 todo!()
-143 }
-144
-145 /// Counts the occurrences of `value`.
-146 ///
-147 /// # Examples
-148 ///
-149 /// ```
-150 /// # use multilab::multiset::MultiSet;
-151 /// #
-152 /// let mut multiset: MultiSet<u8> = MultiSet::new();
-153 /// multiset.insert(0);
-154 /// multiset.insert(0);
-155 /// multiset.insert(1);
-156 /// multiset.insert(0);
-157 /// assert_eq!(3, multiset.count(&0));
-158 /// assert_eq!(1, multiset.count(&1));
-159 /// ```
-160 pub fn count(&self, value: &K) -> usize {
-161 todo!()
-162 }
-163}
-164
-165impl<K> Default for MultiSet<K>
-166where
-167 K: Eq + Hash,
-168{
-169 fn default() -> Self {
-170 Self::new()
-171 }
-172}fn:) to \
- restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \
- enum, trait, type, macro, \
- and const.","Search functions by type signature (e.g., vec -> usize or \
- -> vec or String, enum:Cow -> bool)","You can look for items with an exact name by putting double quotes around \
- your request: \"string\"",`Look for functions that accept or return \
- slices and \
- arrays by writing square \
- brackets (e.g., -> [u8] or [] -> Option)`,"Look for items inside another one by searching for a path: vec::Vec",].map(x=>""+x+"
").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="${value.replaceAll(" ", " ")}`;}else{error[index]=value;}});output+=`#[repr(u8)]pub enum Rank {
-Show 13 variants
Two = 2,
- Three = 3,
- Four = 4,
- Five = 5,
- Six = 6,
- Seven = 7,
- Eight = 8,
- Nine = 9,
- Ten = 10,
- Jack = 11,
- Queen = 12,
- King = 13,
- Ace = 14,
-}Represents the rank of a playing card, which can be either a number card (2-10) or a face card -(Ace, King, Queen, Jack).
-let five_spades = Card::new(Suit::Spade, Rank::Five);
-let seven_spades = Card::new(Suit::Spade, Rank::Seven);
-assert!(seven_spades > five_spades);
-
-let queen_hearts = Card::new(Suit::Heart, Rank::Queen);
-let seven_clubs = Card::new(Suit::Club, Rank::Seven);
-assert!(queen_hearts > seven_clubs);
-
-let king_diamonds = Card::new(Suit::Diamond, Rank::King);
-let ace_clubs = Card::new(Suit::Club, Rank::Ace);
-assert!(ace_clubs > king_diamonds);The Jack card, traditionally representing a royal servant or knight.
-The Queen card, traditionally representing a female royal figure.
-The King card, traditionally representing a male royal figure.
-The Ace card, which often has special rules in many card games.
-pub enum Suit {
- Diamond,
- Club,
- Heart,
- Spade,
-}Represents the four possible suits in a standard deck of playing cards.
-The suits are ordered in the traditional manner:
-let spade_card = Card::new(Suit::Spade, Rank::Two);
-let diamond_card = Card::new(Suit::Diamond, Rank::Two);
-assert_eq!(spade_card, diamond_card);The Diamond suit, typically represented by a red ♦ symbol.
-The Club suit, typically represented by a black ♣ symbol.
-The Heart suit, typically represented by a red ♥ symbol.
-The Spade suit, typically represented by a black ♠ symbol.
-This module contains the definition and implementation of Card, which represents a card in
-a standard deck of 52 cards. Cards are uniquely identified by their rank (which can be the
-numbers 2-10 or Jack, Queen, King, or Ace) and their suit (which can be Diamond, Club, Heart,
-or Spade).
Note to students: You are allowed to modify this file and replace the implementation with -something similar to your own implementation in Card Lab.
-However, make sure you understand that the function signatures are different, and that the
-Rank and Suit types are now public! Additionally, we now no longer make a distinction
-between suits. For example, we will say that the Ace of Spades has equal value to the Ace of
-Diamonds.
pub struct Card { /* private fields */ }Represents a standard playing card with a suit and a rank.
-Each card consists of one of the four suits (Diamond, Club, Heart, Spade), as well as a rank -that can be either a number card (2-10) or a face card (Jack, Queen, King, Ace).
-This type implements the traits PartialEq, Eq, PartialOrd, and Ord. Note that
-Card only considers the Rank of the Card when doing comparisons, so the Three of Clubs
-is considered to have equal value to the Three of Hearts.
This is achieved using the [derivative] macro, where instead of using all of the fields of a
-struct to auto-implement a trait, we are able to ignore specific fields. If you have questions
-about this, please do not hesitate to ask!
let ace_spades = Card::new(Suit::Spade, Rank::Ace);
-let king_spades = Card::new(Suit::Spade, Rank::King);
-let ten_spades = Card::new(Suit::Spade, Rank::Ten);
-let five_spades = Card::new(Suit::Spade, Rank::Five);
-let ace_hearts = Card::new(Suit::Heart, Rank::Ace);
-let ace_clubs = Card::new(Suit::Club, Rank::Ace);
-
-// Compare cards of same suit but different rank.
-assert!(ace_spades > king_spades);
-assert!(king_spades > ten_spades);
-assert!(ten_spades > five_spades);
-
-// Compare cards with same rank
-assert_eq!(ace_spades, ace_hearts);
-assert_eq!(ace_hearts, ace_clubs);
-
-// Test equality between identical cards.
-assert_eq!(ace_spades, Card::new(Suit::Spade, Rank::Ace));Creates a new Card instance from a Suit and Rank.
-suit - The suit of the card as a Suit enum valuerank - The rank of the card as a Rank enum valuelet ace_of_spades = Card::new(Suit::Spade, Rank::Ace);
-let two_of_hearts = Card::new(Suit::Heart, Rank::Two);
-let three_of_clubs = Card::new(Suit::Club, Rank::Three);pub enum PokerHand {
- HighCard(HighCard),
- OnePair(OnePair),
- TwoPair(TwoPair),
- ThreeOfAKind(ThreeOfAKind),
- Straight(Straight),
- Flush(Flush),
- FullHouse(FullHouse),
- FourOfAKind(FourOfAKind),
- StraightFlush(StraightFlush),
-}Represents different poker hand rankings with their respective cards. Each variant contains the -relevant cards that make up the hand.
-Note to students: When you auto derive PartialOrd and Ord, the enum variants are ordered
-by declaration order. For example, HighCard will always come before OnePair.
This type has easily derivable comparison traits, as later PokerHand variants always beat
-earlier ones, and each of the variants are able to be compared with themselves.
See the integration tests in tests/poker_tests.rs for examples.
Given 5 cards as input, creates a PokerHand with the correct ranking.
Note that there is definitely a cleaner way to implement Poker hands, but by breaking it -down into these specific types we can support partial implementation that don’t handle every -single kind of Poker hand!
-Module for poker hand evaluation and comparison.
-There is a bit of Poker lingo that this file uses. If you find yourself confused by anything, -please reach out to us and ask! The term that will probably be most confusing is a “kicker”. -A “kicker”, also known as a “side card”, is simply a card that does not take part in determine -the rank of a hand. For example, if we want to compare 2 four-of-a-kinds, the fifth card in each -hand would be considered the kicker. Note that kickers are still important in breaking ties.
-A good way to approach this assignment is to first read the code in src/card.rs, and then
-read all of the starter code in this file (src/hand.rs). If you are unfamiliar with Poker, you
-may also want to read up on the hands you can make on Wikipedia. Finally (as a good rule of
-thumb for any programming course), make sure to go over the test cases to make sure you have a
-correct idea of what you should implement.
You are also allowed to change any of the private fields of structs in this file, as long as
-you are able to implement the all of the Hand methods without issue. You are also allowed to
-modify the PokerHand::solve method, but be aware that the test cases are solely using that
-method to check the correctness of your implementation, so make sure not to play around with it
-too much.
Hand of 5 playing Cards.pub struct Flush { /* private fields */ }Represents five cards of the same suit. The suit of the cards is ignored since we do not need it -for comparison.
-pub struct FourOfAKind { /* private fields */ }Represents a hand containing four cards of the same rank and one kicker.
-source. Read morepub struct FullHouse { /* private fields */ }Represents a hand containing three cards of one rank and two cards of another rank.
-pub struct Hand { /* private fields */ }Returns a StraightFlush if the hand contains consecutive cards of the same suit,
-otherwise returns None.
This function assumes that all higher-ranking hand checks have been called.
-Returns a FourOfAKind if the hand contains four cards of the same rank, otherwise
-returns None.
This function assumes that all higher-ranking hand checks have been called.
-Returns a FullHouse if the hand contains a triple and a pair, otherwise returns None.
This function assumes that all higher-ranking hand checks have been called.
-Returns a Flush if all cards in the hand have the same suit, otherwise returns None.
This function assumes that all higher-ranking hand checks have been called.
-Returns a Straight if the cards form a straight (consecutive ranks), otherwise returns
-None.
This function can also handle wheels / Ace-low straights (Ace, 2, 3, 4, 5).
-This function assumes that all higher-ranking hand checks have been called.
-Returns a ThreeOfAKind if the hand contains three cards of the same rank, otherwise
-returns None.
This function assumes that all higher-ranking hand checks have been called.
-Returns a TwoPair if the hand contains two pairs, otherwise None.
This function assumes that all higher-ranking hand checks have been called.
-Returns a OnePair if the hand contains a pair of cards with matching rank, otherwise
-returns None.
This function assumes that all higher-ranking hand checks have been called.
-pub struct HighCard { /* private fields */ }Represents a high card hand, consisting of five unpaired cards.
-pub struct OnePair { /* private fields */ }Represents a hand containing one pair and three kickers.
-pub struct Straight { /* private fields */ }Represents five consecutive cards of different suits, storing only the highest card rank.
-Straights can range from Ace-high straights to wheels. A wheel refers to the lowest possible -5-high straight (Ace, 2, 3, 4, 5). In this case, even though the Ace is normally the highest -card, it counts as a low card (like a 1), making a wheel.
-pub struct StraightFlush { /* private fields */ }Represents five consecutive cards of the same suit. The suit of the cards is ignored since we do -not need it for comparison.
-source. Read morepub struct ThreeOfAKind { /* private fields */ }Represents a hand containing three cards of the same rank and two kickers.
-source. Read morepub struct TwoPair { /* private fields */ }Represents a hand containing two pairs and one kicker.
-This goal of this homework is to further expose you to working with structs and enums, as well as -auto-implementing the traits found in the standard library.
-You will be modeling Poker by implementing comparison between -sets of cards, or a “hand” of cards.
-This lab is a continuation of an earlier lab (Card Lab), in which you modeled a playing card in a
-standard 52-card deck. In that lab, you implemented the comparison traits for individual cards. In
-this lab, you will now model a comparison among multiple Cards, specifically a PokerHand type
-that represents a “hand” of 5 cards.
We have provided our own definition and implementation of Card in src/card.rs. Take some time
-to read over the documentation and code for Card, as it is slightly different than the one we
-asked you to implement in the previous lab (the differences will hopefully make implementing
-PokerHand easier).
You should compare and contrast the card.rs file in this assignment to the one from your own Card
-Lab. You’ll notice that we are no longer manually implementing any of the comparison traits, and
-instead we are using the derive macro to auto-implement their behavior. Make sure you understand
-how the derived traits work!
You will need to fill in the implementation of 8 methods on the Hand type (located in
-src/hand/rs), which is essentially a wrapper struct for an array of 5 Cards. We use these
-methods on Hand to implement the solve method on PokerHand. We have provided the
-definition and implementation of PokerHand to you, and you can read more about this type in its
-documentation.
There are 30 test cases, all located inside tests/poker_tests.rs. Each test is worth 5 points, for
-a total of up to 150 points. By implementing more methods on Hand, you will pass more test
-cases. Remember that you can test your code by running cargo test!
We would recommend going bottom up: start with implementing the method for detecting a single pair, -then two pairs, etc. You could get 80/150 points just by implementing one method (though we would -encourage you to try and implement all of them for extra credit)! You also do not need to go in -order, and if you want to skip any of the methods that is totally fine.
-You are allowed to change any of the fields of the structs defined in src/hand.rs if you feel that
-it would be easier for you to use different fields. As long as you pass the test cases, mostly
-everything is fair game (other than plagiarism). If you have any questions about this, please do not
-hesitate to ask us!
The autograder will run these two commands on your code:
-cargo clippy && cargo fmt --all -- --checkIf the autograder detects any errors from the command above, you will not be able to receive -any points. This may seem strict, but we have decided to follow standard best practices for -Rust.
-By following Rust’s style guidelines, you ensure -that anybody reading your code (who is familiar with Rust) will be able to easily navigate your -code. This can help with diving into an unfamiliar code base, and it also eliminates the need for -debate with others over style rules, saving time and energy.
-See the official guidelines for more information.
-If you are on a unix system, we will try to create a handin.zip automatically for you,
-but you will need to have zip already installed.
If you do not have zip installed on your system, install zip on your machine or use the CMU
-Linux SSH machines. If you need help with this, please reach out to us!
Once you have zip installed, we will create the handin.zip automatically for you (take a peek
-into build.rs file if you’re interested in how this works!).
Once you have the handin.zip file, submit it (and only the zip) to Gradescope.
If you are on a windows system, you can zip the src/ folder manually and upload that to
-Gradescope.
Note that you don’t need to name it handin.zip, you can name it whatever you’d like.
In general, feel free to discuss homeworks with other students! As long as you do not copy someone -else’s work, any communication is fair game.
-All formal questions should be asked on Piazza. Try to discuss on Piazza so that other students can -see your questions and answers as well!
-You can also discuss on Discord, but try to keep any technical questions on Piazza.
-We would like to reiterate that you should let us know if you spent anywhere in significant excess -of an hour on this homework.
-In addition, Rust has a notoriously steep learning curve, so if you find yourself not understanding -the concepts, you should reach out to us and let us know as well — chances are, you’re not the -only one!
-U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCreates a new Card instance from a Suit and Rank.\nReturns a reference to this card’s rank.\nReturns a reference to this card’s suit.\nRepresents five cards of the same suit. The suit of the …\nRepresents a hand containing four cards of the same rank …\nRepresents a hand containing three cards of one rank and …\nRepresents a standard Hand of 5 playing Cards.\nRepresents a high card hand, consisting of five unpaired …\nRepresents a hand containing one pair and three kickers.\nRepresents different poker hand rankings with their …\nRepresents five consecutive cards of different suits, …\nRepresents five consecutive cards of the same suit. The …\nRepresents a hand containing three cards of the same rank …\nRepresents a hand containing two pairs and one kicker.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns a Flush if all cards in the hand have the same …\nReturns a FourOfAKind if the hand contains four cards of …\nReturns a FullHouse if the hand contains a triple and a …\nReturns a OnePair if the hand contains a pair of cards …\nReturns a Straight if the cards form a straight …\nReturns a StraightFlush if the hand contains consecutive …\nReturns a ThreeOfAKind if the hand contains three cards of …\nReturns a TwoPair if the hand contains two pairs, …\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nCreates a new Hand of 5 Cards.\nGiven 5 cards as input, creates a PokerHand with the …")
\ No newline at end of file
diff --git a/hw/pokerlab/doc/settings.html b/hw/pokerlab/doc/settings.html
deleted file mode 100644
index fa9574b6..00000000
--- a/hw/pokerlab/doc/settings.html
+++ /dev/null
@@ -1 +0,0 @@
--1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180
//! This module contains the definition and implementation of [`Card`], which represents a card in
-//! a standard deck of 52 cards. [`Card`]s are uniquely identified by their rank (which can be the
-//! numbers 2-10 or Jack, Queen, King, or Ace) and their suit (which can be Diamond, Club, Heart,
-//! or Spade).
-//!
-//! Note to students: You are allowed to modify this file and replace the implementation with
-//! something similar to your own implementation in Card Lab.
-//!
-//! However, make sure you understand that the function signatures are different, and that the
-//! `Rank` and `Suit` types are now public! Additionally, we now no longer make a distinction
-//! between suits. For example, we will say that the Ace of Spades has equal value to the Ace of
-//! Diamonds.
-
-use derivative::Derivative;
-
-/// Represents a standard playing card with a suit and a rank.
-///
-/// Each card consists of one of the four suits (Diamond, Club, Heart, Spade), as well as a rank
-/// that can be either a number card (2-10) or a face card (Jack, Queen, King, Ace).
-///
-/// This type implements the traits [`PartialEq`], [`Eq`], [`PartialOrd`], and [`Ord`]. Note that
-/// `Card` only considers the [`Rank`] of the `Card` when doing comparisons, so the Three of Clubs
-/// is considered to have equal value to the Three of Hearts.
-///
-/// This is achieved using the [`derivative`] macro, where instead of using all of the fields of a
-/// struct to auto-implement a trait, we are able to ignore specific fields. If you have questions
-/// about this, please do not hesitate to ask!
-///
-/// # Examples
-///
-/// ```
-/// # use pokerlab::card::{Card, Suit, Rank};
-/// #
-/// let ace_spades = Card::new(Suit::Spade, Rank::Ace);
-/// let king_spades = Card::new(Suit::Spade, Rank::King);
-/// let ten_spades = Card::new(Suit::Spade, Rank::Ten);
-/// let five_spades = Card::new(Suit::Spade, Rank::Five);
-/// let ace_hearts = Card::new(Suit::Heart, Rank::Ace);
-/// let ace_clubs = Card::new(Suit::Club, Rank::Ace);
-///
-/// // Compare cards of same suit but different rank.
-/// assert!(ace_spades > king_spades);
-/// assert!(king_spades > ten_spades);
-/// assert!(ten_spades > five_spades);
-///
-/// // Compare cards with same rank
-/// assert_eq!(ace_spades, ace_hearts);
-/// assert_eq!(ace_hearts, ace_clubs);
-///
-/// // Test equality between identical cards.
-/// assert_eq!(ace_spades, Card::new(Suit::Spade, Rank::Ace));
-/// ```
-#[derive(Debug, Clone, Copy, Derivative)]
-#[derivative(PartialEq, Eq, PartialOrd, Ord)]
-pub struct Card {
- rank: Rank,
- #[derivative(PartialEq = "ignore", PartialOrd = "ignore", Ord = "ignore")]
- suit: Suit,
-}
-
-impl Card {
- /// Creates a new Card instance from a Suit and Rank.
- ///
- /// # Parameters
- ///
- /// * `suit` - The suit of the card as a [`Suit`] enum value
- /// * `rank` - The rank of the card as a [`Rank`] enum value
- ///
- /// # Examples
- ///
- /// ```
- /// # use pokerlab::card::{Card, Suit, Rank};
- /// #
- /// let ace_of_spades = Card::new(Suit::Spade, Rank::Ace);
- /// let two_of_hearts = Card::new(Suit::Heart, Rank::Two);
- /// let three_of_clubs = Card::new(Suit::Club, Rank::Three);
- /// ```
- pub fn new(suit: Suit, rank: Rank) -> Self {
- Card { suit, rank }
- }
-
- /// Returns a reference to this card's suit.
- ///
- /// # Examples
- ///
- /// ```
- /// # use pokerlab::card::{Card, Suit, Rank};
- /// #
- /// let card = Card::new(Suit::Club, Rank::Three);
- /// assert_eq!(Suit::Club, card.suit());
- /// ```
- pub fn suit(&self) -> Suit {
- self.suit
- }
-
- /// Returns a reference to this card's rank.
- ///
- /// # Examples
- ///
- /// ```
- /// # use pokerlab::card::{Card, Suit, Rank};
- /// #
- /// let card = Card::new(Suit::Club, Rank::Three);
- /// assert_eq!(Rank::Three, card.rank());
- /// ```
- pub fn rank(&self) -> Rank {
- self.rank
- }
-}
-
-/// Represents the four possible suits in a standard deck of playing cards.
-///
-/// The suits are ordered in the traditional manner:
-/// - Diamonds (lowest)
-/// - Clubs
-/// - Hearts
-/// - Spades (highest)
-///
-/// # Examples
-///
-/// ```
-/// # use pokerlab::card::{Card, Suit, Rank};
-/// #
-/// let spade_card = Card::new(Suit::Spade, Rank::Two);
-/// let diamond_card = Card::new(Suit::Diamond, Rank::Two);
-/// assert_eq!(spade_card, diamond_card);
-/// ```
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum Suit {
- /// The Diamond suit, typically represented by a red ♦ symbol.
- Diamond,
- /// The Club suit, typically represented by a black ♣ symbol.
- Club,
- /// The Heart suit, typically represented by a red ♥ symbol.
- Heart,
- /// The Spade suit, typically represented by a black ♠ symbol.
- Spade,
-}
-
-/// Represents the rank of a playing card, which can be either a number card (2-10) or a face card
-/// (Ace, King, Queen, Jack).
-///
-/// # Examples
-///
-/// ```
-/// # use pokerlab::card::{Card, Suit, Rank};
-/// #
-/// let five_spades = Card::new(Suit::Spade, Rank::Five);
-/// let seven_spades = Card::new(Suit::Spade, Rank::Seven);
-/// assert!(seven_spades > five_spades);
-///
-/// let queen_hearts = Card::new(Suit::Heart, Rank::Queen);
-/// let seven_clubs = Card::new(Suit::Club, Rank::Seven);
-/// assert!(queen_hearts > seven_clubs);
-///
-/// let king_diamonds = Card::new(Suit::Diamond, Rank::King);
-/// let ace_clubs = Card::new(Suit::Club, Rank::Ace);
-/// assert!(ace_clubs > king_diamonds);
-/// ```
-#[repr(u8)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub enum Rank {
- Two = 2,
- Three = 3,
- Four = 4,
- Five = 5,
- Six = 6,
- Seven = 7,
- Eight = 8,
- Nine = 9,
- Ten = 10,
- /// The Jack card, traditionally representing a royal servant or knight.
- Jack = 11,
- /// The Queen card, traditionally representing a female royal figure.
- Queen = 12,
- /// The King card, traditionally representing a male royal figure.
- King = 13,
- /// The Ace card, which often has special rules in many card games.
- Ace = 14,
-}
--1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222 -223 -224 -225 -226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238 -239 -240 -241 -242 -243 -244 -245 -246 -247 -248 -249 -250 -251 -252 -253 -254 -255 -256 -257 -258 -259 -260 -261 -262 -263 -264 -265 -266 -267 -268 -269 -270 -271 -272 -273 -274 -275 -276 -277 -278 -279 -280 -281 -282 -283 -284
//! Module for poker hand evaluation and comparison.
-//!
-//! There is a bit of Poker lingo that this file uses. If you find yourself confused by anything,
-//! please reach out to us and ask! The term that will probably be most confusing is a "kicker".
-//! A "kicker", also known as a "side card", is simply a card that does not take part in determine
-//! the rank of a hand. For example, if we want to compare 2 four-of-a-kinds, the fifth card in each
-//! hand would be considered the kicker. Note that kickers are still important in breaking ties.
-//!
-//! A good way to approach this assignment is to first read the code in `src/card.rs`, and then
-//! read all of the starter code in this file (`src/hand.rs`). If you are unfamiliar with Poker, you
-//! may also want to read up on the hands you can make on [Wikipedia]. Finally (as a good rule of
-//! thumb for any programming course), make sure to go over the test cases to make sure you have a
-//! correct idea of what you should implement.
-//!
-//! You are also allowed to change _any_ of the private fields of structs in this file, as long as
-//! you are able to implement the all of the [`Hand`] methods without issue. You are also allowed to
-//! modify the [`PokerHand::solve`] method, but be aware that the test cases are _solely_ using that
-//! method to check the correctness of your implementation, so make sure not to play around with it
-//! too much.
-//!
-//! [Wikipedia]: https://en.wikipedia.org/wiki/List_of_poker_hands
-
-use crate::card::{Card, Rank};
-
-/// Represents different poker hand rankings with their respective cards. Each variant contains the
-/// relevant cards that make up the hand.
-///
-/// Note to students: When you auto derive [`PartialOrd`] and [`Ord`], the enum variants are ordered
-/// by declaration order. For example, [`HighCard`] will always come before [`OnePair`].
-///
-/// This type has easily derivable comparison traits, as later [`PokerHand`] variants always beat
-/// earlier ones, and each of the variants are able to be compared with themselves.
-///
-/// See the integration tests in `tests/poker_tests.rs` for examples.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub enum PokerHand {
- HighCard(HighCard),
- OnePair(OnePair),
- TwoPair(TwoPair),
- ThreeOfAKind(ThreeOfAKind),
- Straight(Straight),
- Flush(Flush),
- FullHouse(FullHouse),
- FourOfAKind(FourOfAKind),
- StraightFlush(StraightFlush),
-}
-
-/// Represents a high card hand, consisting of five unpaired cards.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub struct HighCard {
- /// The highest card rank in the hand.
- high_card: Rank,
- /// The remaining four card ranks in descending order.
- kickers: [Rank; 4],
-}
-
-/// Represents a hand containing one pair and three kickers.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub struct OnePair {
- /// The rank of the matched pair of cards.
- pair: Rank,
- /// The remaining three card ranks in descending order.
- kickers: [Rank; 3],
-}
-
-/// Represents a hand containing two pairs and one kicker.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub struct TwoPair {
- /// The higher ranked pair.
- first_pair: Rank,
- /// The lower ranked pair.
- second_pair: Rank,
- /// The remaining unpaired card.
- kicker: Rank,
-}
-
-/// Represents a hand containing three cards of the same rank and two kickers.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub struct ThreeOfAKind {
- /// The rank of the three matched cards.
- triple: Rank,
- /// The remaining two card ranks in descending order.
- kickers: [Rank; 2],
-}
-
-/// Represents five consecutive cards of different suits, storing only the highest card rank.
-///
-/// Straights can range from Ace-high straights to wheels. A wheel refers to the lowest possible
-/// 5-high straight (Ace, 2, 3, 4, 5). In this case, even though the Ace is normally the highest
-/// card, it counts as a low card (like a 1), making a wheel.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Straight {
- /// The highest rank in the straight (highest can be an Ace, lowest is a 5 for a wheel).
- high_card: Rank,
-}
-
-/// Represents five cards of the same suit. The suit of the cards is ignored since we do not need it
-/// for comparison.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Flush {
- /// The ranks of the five cards in descending order.
- ranks: [Rank; 5],
-}
-
-/// Represents a hand containing three cards of one rank and two cards of another rank.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub struct FullHouse {
- /// The rank of the three matched cards.
- triple: Rank,
- /// The rank of the two matched cards.
- pair: Rank,
-}
-
-/// Represents a hand containing four cards of the same rank and one kicker.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub struct FourOfAKind {
- /// The rank shared by all four cards.
- quad: Rank,
- /// The remaining unpaired card rank.
- kicker: Rank,
-}
-
-/// Represents five consecutive cards of the same suit. The suit of the cards is ignored since we do
-/// not need it for comparison.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub struct StraightFlush {
- /// The highest rank in the straight (highest can be an Ace, lowest is a 5 for a wheel).
- high_card: Rank,
-}
-
-impl PokerHand {
- /// Given 5 cards as input, creates a `PokerHand` with the correct ranking.
- ///
- /// Note that there is definitely a cleaner way to implement Poker hands, but by breaking it
- /// down into these specific types we can support partial implementation that don't handle every
- /// single kind of Poker hand!
- pub fn solve(hand: Hand) -> Self {
- // Check for a straight flush first (highest ranking hand).
- if let Some(straight_flush) = hand.get_straight_flush() {
- return PokerHand::StraightFlush(straight_flush);
- }
-
- // Check for a four of a kind.
- if let Some(four_of_a_kind) = hand.get_four_of_a_kind() {
- return PokerHand::FourOfAKind(four_of_a_kind);
- }
-
- // Check for a full house.
- if let Some(full_house) = hand.get_full_house() {
- return PokerHand::FullHouse(full_house);
- }
-
- // Check for a flush.
- if let Some(flush) = hand.get_flush() {
- return PokerHand::Flush(flush);
- }
-
- // Check for a straight.
- if let Some(straight) = hand.get_straight() {
- return PokerHand::Straight(straight);
- }
-
- // Check for a three of a kind.
- if let Some(three_of_a_kind) = hand.get_triple() {
- return PokerHand::ThreeOfAKind(three_of_a_kind);
- }
-
- // Check for a two pair.
- if let Some(two_pair) = hand.get_two_pair() {
- return PokerHand::TwoPair(two_pair);
- }
-
- // Check for a one pair.
- if let Some(one_pair) = hand.get_one_pair() {
- return PokerHand::OnePair(one_pair);
- }
-
- // If no other hand is found, it's a high card hand.
- PokerHand::HighCard(HighCard {
- high_card: hand.cards[0].rank(),
- kickers: [
- hand.cards[1].rank(),
- hand.cards[2].rank(),
- hand.cards[3].rank(),
- hand.cards[4].rank(),
- ],
- })
- }
-}
-
-/// Represents a standard `Hand` of 5 playing [`Card`]s.
-///
-/// Note that the cards will always be stored in sorted descending order (only by [`Rank`]).
-#[derive(Debug)]
-pub struct Hand {
- /// The cards in the hand.
- cards: [Card; 5],
-}
-
-impl Hand {
- /// Creates a new `Hand` of 5 [`Card`]s.
- ///
- /// Stores the cards in reverse (descending) sorted order.
- ///
- /// Returns [`None`] if any cards are duplicates.
- pub fn new(mut cards: [Card; 5]) -> Option<Self> {
- // Sort in reverse order.
- cards.sort_by(|a, b| b.cmp(a));
-
- // Check for any duplicate cards.
- for i in 0..4 {
- // Need to also check if the suits are equal since `Card` equality does not consider
- // suits when checking comparison.
- if cards[i] == cards[i + 1] && cards[i].suit() == cards[i + 1].suit() {
- return None;
- }
- }
-
- Some(Self { cards })
- }
-
- /// Returns a [`StraightFlush`] if the hand contains consecutive cards of the same suit,
- /// otherwise returns `None`.
- ///
- /// This function assumes that all higher-ranking hand checks have been called.
- pub fn get_straight_flush(&self) -> Option<StraightFlush> {
- todo!("check if the current hand is both a straight and a flush")
- }
-
- /// Returns a [`FourOfAKind`] if the hand contains four cards of the same rank, otherwise
- /// returns `None`.
- ///
- /// This function assumes that all higher-ranking hand checks have been called.
- pub fn get_four_of_a_kind(&self) -> Option<FourOfAKind> {
- todo!("check if the current hand contains all four cards of a specific rank")
- }
-
- /// Returns a [`FullHouse`] if the hand contains a triple and a pair, otherwise returns `None`.
- ///
- /// This function assumes that all higher-ranking hand checks have been called.
- pub fn get_full_house(&self) -> Option<FullHouse> {
- todo!("check if the current hand has both three of a kind and a pair")
- }
-
- /// Returns a [`Flush`] if all cards in the hand have the same suit, otherwise returns `None`.
- ///
- /// This function assumes that all higher-ranking hand checks have been called.
- pub fn get_flush(&self) -> Option<Flush> {
- todo!("check if all cards in the current hand have the same suit")
- }
-
- /// Returns a [`Straight`] if the cards form a straight (consecutive ranks), otherwise returns
- /// `None`.
- ///
- /// This function can also handle wheels / Ace-low straights (Ace, 2, 3, 4, 5).
- ///
- /// This function assumes that all higher-ranking hand checks have been called.
- pub fn get_straight(&self) -> Option<Straight> {
- todo!("check if the current hand contains contiguously-ranked cards")
- }
-
- /// Returns a [`ThreeOfAKind`] if the hand contains three cards of the same rank, otherwise
- /// returns `None`.
- ///
- /// This function assumes that all higher-ranking hand checks have been called.
- pub fn get_triple(&self) -> Option<ThreeOfAKind> {
- todo!("check if the current hand contains three cards with equal rank")
- }
-
- /// Returns a [`TwoPair`] if the hand contains two pairs, otherwise `None`.
- ///
- /// This function assumes that all higher-ranking hand checks have been called.
- pub fn get_two_pair(&self) -> Option<TwoPair> {
- todo!("check if the current hand contains two pairs of two cards with equal rank")
- }
-
- /// Returns a [`OnePair`] if the hand contains a pair of cards with matching rank, otherwise
- /// returns `None`.
- ///
- /// This function assumes that all higher-ranking hand checks have been called.
- pub fn get_one_pair(&self) -> Option<OnePair> {
- todo!("check if the current hand contains two cards with equal rank")
- }
-}
-fn:) to \
- restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \
- enum, trait, type, macro, \
- and const.","Search functions by type signature (e.g., vec -> usize or \
- -> vec or String, enum:Cow -> bool)","You can look for items with an exact name by putting double quotes around \
- your request: \"string\"","Look for functions that accept or return \
- slices and \
- arrays by writing \
- square brackets (e.g., -> [u8] or [] -> Option)","Look for items inside another one by searching for a path: vec::Vec",].map(x=>""+x+"
").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="${value.replaceAll(" ", " ")}`}else{error[index]=value}});output+=`All examples taken from rustlings -exercises
-Uncomment each of these and ensure that it compiles with cargo test -- fixme.
-We recommend uncommenting them one at a time.
-Make sure you read ALL of the error messages! They contain VERY useful information.