rustlings

solving rustlings ft. dracuxan
git clone igris.git:dracuxan/rustlings.git
Log | Files | Refs

commit 35d35403d21aa379f954f073e653b0e5564af9df
parent 83cc73821fde78d9d14642798a4631370fd1dc1a
Author: dracuxan <[email protected]>
Date:   Mon,  1 Jun 2026 12:45:10 +0530

upd

Diffstat:
M.rustlings-state.txt | 14+++++++++++---
Mexercises/15_traits/traits4.rs | 2+-
Mexercises/15_traits/traits5.rs | 2+-
Mexercises/16_lifetimes/lifetimes1.rs | 8++------
Mexercises/16_lifetimes/lifetimes2.rs | 8++------
Mexercises/16_lifetimes/lifetimes3.rs | 6+++---
Mexercises/17_tests/tests1.rs | 5+++--
Mexercises/17_tests/tests2.rs | 8++++----
Mexercises/quizzes/quiz3.rs | 6+++---
Msolutions/15_traits/traits4.rs | 35+++++++++++++++++++++++++++++++++--
Msolutions/15_traits/traits5.rs | 39+++++++++++++++++++++++++++++++++++++--
Msolutions/16_lifetimes/lifetimes1.rs | 24++++++++++++++++++++++--
Msolutions/16_lifetimes/lifetimes2.rs | 29+++++++++++++++++++++++++++--
Msolutions/16_lifetimes/lifetimes3.rs | 18++++++++++++++++--
Msolutions/17_tests/tests1.rs | 24++++++++++++++++++++++--
Msolutions/17_tests/tests2.rs | 22++++++++++++++++++++--
Msolutions/quizzes/quiz3.rs | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
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+", + ); + } }