commit 35d35403d21aa379f954f073e653b0e5564af9df
parent 83cc73821fde78d9d14642798a4631370fd1dc1a
Author: dracuxan <[email protected]>
Date: Mon, 1 Jun 2026 12:45:10 +0530
upd
Diffstat:
17 files changed, 270 insertions(+), 45 deletions(-)
diff --git a/.rustlings-state.txt b/.rustlings-state.txt
@@ -1,6 +1,6 @@
DON'T EDIT THIS FILE!
-traits4
+tests3
intro1
intro2
@@ -62,4 +62,12 @@ generics1
generics2
traits1
traits2
-traits3
-\ No newline at end of file
+traits3
+traits4
+traits5
+quiz3
+lifetimes1
+lifetimes2
+lifetimes3
+tests1
+tests2
+\ No newline at end of file
diff --git a/exercises/15_traits/traits4.rs b/exercises/15_traits/traits4.rs
@@ -11,7 +11,7 @@ impl Licensed for SomeSoftware {}
impl Licensed for OtherSoftware {}
// TODO: Fix the compiler error by only changing the signature of this function.
-fn compare_license_types(software1: SomeSoftware, software2: OtherSoftware) -> bool {
+fn compare_license_types(software1: impl Licensed, software2: impl Licensed) -> bool {
software1.licensing_info() == software2.licensing_info()
}
diff --git a/exercises/15_traits/traits5.rs b/exercises/15_traits/traits5.rs
@@ -19,7 +19,7 @@ impl SomeTrait for OtherStruct {}
impl OtherTrait for OtherStruct {}
// TODO: Fix the compiler error by only changing the signature of this function.
-fn some_func(item: ???) -> bool {
+fn some_func(item: impl OtherTrait + SomeTrait) -> bool {
item.some_function() && item.other_function()
}
diff --git a/exercises/16_lifetimes/lifetimes1.rs b/exercises/16_lifetimes/lifetimes1.rs
@@ -4,12 +4,8 @@
// not own their own data. What if their owner goes out of scope?
// TODO: Fix the compiler error by updating the function signature.
-fn longest(x: &str, y: &str) -> &str {
- if x.len() > y.len() {
- x
- } else {
- y
- }
+fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
+ if x.len() > y.len() { x } else { y }
}
fn main() {
diff --git a/exercises/16_lifetimes/lifetimes2.rs b/exercises/16_lifetimes/lifetimes2.rs
@@ -1,19 +1,15 @@
// Don't change this function.
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
- if x.len() > y.len() {
- x
- } else {
- y
- }
+ if x.len() > y.len() { x } else { y }
}
fn main() {
// TODO: Fix the compiler error by moving one line.
let string1 = String::from("long string is long");
+ let string2 = String::from("xyz");
let result;
{
- let string2 = String::from("xyz");
result = longest(&string1, &string2);
}
println!("The longest string is '{result}'");
diff --git a/exercises/16_lifetimes/lifetimes3.rs b/exercises/16_lifetimes/lifetimes3.rs
@@ -1,9 +1,9 @@
// Lifetimes are also needed when structs hold references.
// TODO: Fix the compiler errors about the struct.
-struct Book {
- author: &str,
- title: &str,
+struct Book<'a> {
+ author: &'a str,
+ title: &'a str,
}
fn main() {
diff --git a/exercises/17_tests/tests1.rs b/exercises/17_tests/tests1.rs
@@ -13,11 +13,12 @@ fn main() {
mod tests {
// TODO: Import `is_even`. You can use a wildcard to import everything in
// the outer module.
+ use crate::is_even;
#[test]
fn you_can_assert() {
// TODO: Test the function `is_even` with some values.
- assert!();
- assert!();
+ assert!(!is_even(1));
+ assert!(is_even(2));
}
}
diff --git a/exercises/17_tests/tests2.rs b/exercises/17_tests/tests2.rs
@@ -15,9 +15,9 @@ mod tests {
#[test]
fn you_can_assert_eq() {
// TODO: Test the function `power_of_2` with some values.
- assert_eq!();
- assert_eq!();
- assert_eq!();
- assert_eq!();
+ assert_eq!(power_of_2(1), 2);
+ assert_eq!(power_of_2(1), 2);
+ assert_eq!(power_of_2(1), 2);
+ assert_eq!(power_of_2(1), 2);
}
}
diff --git a/exercises/quizzes/quiz3.rs b/exercises/quizzes/quiz3.rs
@@ -12,14 +12,14 @@
// block to support alphabetical report cards in addition to numerical ones.
// TODO: Adjust the struct as described above.
-struct ReportCard {
- grade: f32,
+struct ReportCard<T> {
+ grade: T,
student_name: String,
student_age: u8,
}
// TODO: Adjust the impl block as described above.
-impl ReportCard {
+impl<T: std::fmt::Display> ReportCard<T> {
fn print(&self) -> String {
format!(
"{} ({}) - achieved a grade of {}",
diff --git a/solutions/15_traits/traits4.rs b/solutions/15_traits/traits4.rs
@@ -1,4 +1,35 @@
+trait Licensed {
+ fn licensing_info(&self) -> String {
+ "Default license".to_string()
+ }
+}
+
+struct SomeSoftware;
+struct OtherSoftware;
+
+impl Licensed for SomeSoftware {}
+impl Licensed for OtherSoftware {}
+
+fn compare_license_types(software1: impl Licensed, software2: impl Licensed) -> bool {
+ // ^^^^^^^^^^^^^ ^^^^^^^^^^^^^
+ software1.licensing_info() == software2.licensing_info()
+}
+
fn main() {
- // DON'T EDIT THIS SOLUTION FILE!
- // It will be automatically filled after you finish the exercise.
+ // You can optionally experiment here.
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn compare_license_information() {
+ assert!(compare_license_types(SomeSoftware, OtherSoftware));
+ }
+
+ #[test]
+ fn compare_license_information_backwards() {
+ assert!(compare_license_types(OtherSoftware, SomeSoftware));
+ }
}
diff --git a/solutions/15_traits/traits5.rs b/solutions/15_traits/traits5.rs
@@ -1,4 +1,39 @@
+trait SomeTrait {
+ fn some_function(&self) -> bool {
+ true
+ }
+}
+
+trait OtherTrait {
+ fn other_function(&self) -> bool {
+ true
+ }
+}
+
+struct SomeStruct;
+impl SomeTrait for SomeStruct {}
+impl OtherTrait for SomeStruct {}
+
+struct OtherStruct;
+impl SomeTrait for OtherStruct {}
+impl OtherTrait for OtherStruct {}
+
+fn some_func(item: impl SomeTrait + OtherTrait) -> bool {
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ item.some_function() && item.other_function()
+}
+
fn main() {
- // DON'T EDIT THIS SOLUTION FILE!
- // It will be automatically filled after you finish the exercise.
+ // You can optionally experiment here.
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_some_func() {
+ assert!(some_func(SomeStruct));
+ assert!(some_func(OtherStruct));
+ }
}
diff --git a/solutions/16_lifetimes/lifetimes1.rs b/solutions/16_lifetimes/lifetimes1.rs
@@ -1,4 +1,24 @@
+// The Rust compiler needs to know how to check whether supplied references are
+// valid, so that it can let the programmer know if a reference is at risk of
+// going out of scope before it is used. Remember, references are borrows and do
+// not own their own data. What if their owner goes out of scope?
+
+fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
+ // ^^^^ ^^ ^^ ^^
+ if x.len() > y.len() { x } else { y }
+}
+
fn main() {
- // DON'T EDIT THIS SOLUTION FILE!
- // It will be automatically filled after you finish the exercise.
+ // You can optionally experiment here.
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_longest() {
+ assert_eq!(longest("abcd", "123"), "abcd");
+ assert_eq!(longest("abc", "1234"), "1234");
+ }
}
diff --git a/solutions/16_lifetimes/lifetimes2.rs b/solutions/16_lifetimes/lifetimes2.rs
@@ -1,4 +1,29 @@
+fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
+ if x.len() > y.len() { x } else { y }
+}
+
fn main() {
- // DON'T EDIT THIS SOLUTION FILE!
- // It will be automatically filled after you finish the exercise.
+ let string1 = String::from("long string is long");
+ // Solution1: You can move `strings2` out of the inner block so that it is
+ // not dropped before the print statement.
+ let string2 = String::from("xyz");
+ let result;
+ {
+ result = longest(&string1, &string2);
+ }
+ println!("The longest string is '{result}'");
+ // `string2` dropped at the end of the function.
+
+ // =========================================================================
+
+ let string1 = String::from("long string is long");
+ let result;
+ {
+ let string2 = String::from("xyz");
+ result = longest(&string1, &string2);
+ // Solution2: You can move the print statement into the inner block so
+ // that it is executed before `string2` is dropped.
+ println!("The longest string is '{result}'");
+ // `string2` dropped here (end of the inner scope).
+ }
}
diff --git a/solutions/16_lifetimes/lifetimes3.rs b/solutions/16_lifetimes/lifetimes3.rs
@@ -1,4 +1,18 @@
+// Lifetimes are also needed when structs hold references.
+
+struct Book<'a> {
+ // ^^^^ added a lifetime annotation
+ author: &'a str,
+ // ^^
+ title: &'a str,
+ // ^^
+}
+
fn main() {
- // DON'T EDIT THIS SOLUTION FILE!
- // It will be automatically filled after you finish the exercise.
+ let book = Book {
+ author: "George Orwell",
+ title: "1984",
+ };
+
+ println!("{} by {}", book.title, book.author);
}
diff --git a/solutions/17_tests/tests1.rs b/solutions/17_tests/tests1.rs
@@ -1,4 +1,24 @@
+// Tests are important to ensure that your code does what you think it should
+// do.
+
+fn is_even(n: i64) -> bool {
+ n % 2 == 0
+}
+
fn main() {
- // DON'T EDIT THIS SOLUTION FILE!
- // It will be automatically filled after you finish the exercise.
+ // You can optionally experiment here.
+}
+
+#[cfg(test)]
+mod tests {
+ // When writing unit tests, it is common to import everything from the outer
+ // module (`super`) using a wildcard.
+ use super::*;
+
+ #[test]
+ fn you_can_assert() {
+ assert!(is_even(0));
+ assert!(!is_even(-1));
+ // ^ You can assert `false` using the negation operator `!`.
+ }
}
diff --git a/solutions/17_tests/tests2.rs b/solutions/17_tests/tests2.rs
@@ -1,4 +1,22 @@
+// Calculates the power of 2 using a bit shift.
+// `1 << n` is equivalent to "2 to the power of n".
+fn power_of_2(n: u8) -> u64 {
+ 1 << n
+}
+
fn main() {
- // DON'T EDIT THIS SOLUTION FILE!
- // It will be automatically filled after you finish the exercise.
+ // You can optionally experiment here.
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn you_can_assert_eq() {
+ assert_eq!(power_of_2(0), 1);
+ assert_eq!(power_of_2(1), 2);
+ assert_eq!(power_of_2(2), 4);
+ assert_eq!(power_of_2(3), 8);
+ }
}
diff --git a/solutions/quizzes/quiz3.rs b/solutions/quizzes/quiz3.rs
@@ -1,4 +1,65 @@
+// An imaginary magical school has a new report card generation system written
+// in Rust! Currently, the system only supports creating report cards where the
+// student's grade is represented numerically (e.g. 1.0 -> 5.5). However, the
+// school also issues alphabetical grades (A+ -> F-) and needs to be able to
+// print both types of report card!
+//
+// Make the necessary code changes in the struct `ReportCard` and the impl
+// block to support alphabetical report cards in addition to numerical ones.
+
+use std::fmt::Display;
+
+// Make the struct generic over `T`.
+struct ReportCard<T> {
+ // ^^^
+ grade: T,
+ // ^
+ student_name: String,
+ student_age: u8,
+}
+
+// To be able to print the grade, it has to implement the `Display` trait.
+impl<T: Display> ReportCard<T> {
+ // ^^^^^^^ require that `T` implements `Display`.
+ fn print(&self) -> String {
+ format!(
+ "{} ({}) - achieved a grade of {}",
+ &self.student_name, &self.student_age, &self.grade,
+ )
+ }
+}
+
fn main() {
- // DON'T EDIT THIS SOLUTION FILE!
- // It will be automatically filled after you finish the exercise.
+ // You can optionally experiment here.
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn generate_numeric_report_card() {
+ let report_card = ReportCard {
+ grade: 2.1,
+ student_name: "Tom Wriggle".to_string(),
+ student_age: 12,
+ };
+ assert_eq!(
+ report_card.print(),
+ "Tom Wriggle (12) - achieved a grade of 2.1",
+ );
+ }
+
+ #[test]
+ fn generate_alphabetic_report_card() {
+ let report_card = ReportCard {
+ grade: "A+",
+ student_name: "Gary Plotter".to_string(),
+ student_age: 11,
+ };
+ assert_eq!(
+ report_card.print(),
+ "Gary Plotter (11) - achieved a grade of A+",
+ );
+ }
}