mirror of
https://github.com/rust-lang/rustlings.git
synced 2026-01-09 20:29:18 +00:00
Finish Rustlings
This commit is contained in:
parent
95b259dfb3
commit
81ead79f01
70
]
Normal file
70
]
Normal file
@ -0,0 +1,70 @@
|
||||
// iterators2.rs
|
||||
// In this exercise, you'll learn some of the unique advantages that iterators
|
||||
// can offer. Follow the steps to complete the exercise.
|
||||
// As always, there are hints if you execute `rustlings hint iterators2`!
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
// Step 1.
|
||||
// Complete the `capitalize_first` function.
|
||||
// "hello" -> "Hello"
|
||||
fn main() {}
|
||||
|
||||
pub fn capitalize_first(input: &str) -> String {
|
||||
let mut c = input.chars();
|
||||
match c.next() {
|
||||
None => String::new(),
|
||||
Some(last) => last.to_string().to_uppercase() + c.as_str(),
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2.
|
||||
// Apply the `capitalize_first` function to a slice of string slices.
|
||||
// Return a vector of strings.
|
||||
// ["hello", "world"] -> ["Hello", "World"]
|
||||
pub fn capitalize_words_vector(words: &[&str]) -> Vec<String> {
|
||||
let mut final_words = vec![];
|
||||
for word in words {
|
||||
final_words.push(capitalize_first(word));
|
||||
}
|
||||
final_words
|
||||
}
|
||||
|
||||
// Step 3.
|
||||
// Apply the `capitalize_first` function again to a slice of string slices.
|
||||
// Return a single string.
|
||||
// ["hello", " ", "world"] -> "Hello World"
|
||||
pub fn capitalize_words_string(words: &[&str]) -> String {
|
||||
let mut return_string = String::new();
|
||||
for word in words {
|
||||
return_string.append(capitalize_first(word));
|
||||
}
|
||||
return_string
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_success() {
|
||||
assert_eq!(capitalize_first("hello"), "Hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty() {
|
||||
assert_eq!(capitalize_first(""), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iterate_string_vec() {
|
||||
let words = vec!["hello", "world"];
|
||||
assert_eq!(capitalize_words_vector(&words), ["Hello", "World"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iterate_into_string() {
|
||||
let words = vec!["hello", " ", "world"];
|
||||
assert_eq!(capitalize_words_string(&words), "Hello World");
|
||||
}
|
||||
}
|
||||
5
exercises/Cargo.lock
generated
Normal file
5
exercises/Cargo.lock
generated
Normal file
@ -0,0 +1,5 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "exercises"
|
||||
version = "0.1.0"
|
||||
286
exercises/Cargo.toml
Normal file
286
exercises/Cargo.toml
Normal file
@ -0,0 +1,286 @@
|
||||
# This Cargo.toml is AUTOGENERATED, you shouldn't need to edit it.
|
||||
# The `rustling` commands do not rely on this manifest at all, its only purpose
|
||||
# is to help editors analyze your code.
|
||||
# To regenerate it, run `cargo generate-manifest`.
|
||||
[package]
|
||||
name = 'exercises'
|
||||
version = '0.1.0'
|
||||
edition = '2018'
|
||||
authors = ['The Rustlings Maintainers']
|
||||
publish = false
|
||||
|
||||
[[bin]]
|
||||
name = 'clippy1'
|
||||
path = 'clippy/clippy1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'clippy2'
|
||||
path = 'clippy/clippy2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'as_ref_mut'
|
||||
path = 'conversions/as_ref_mut.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'from_into'
|
||||
path = 'conversions/from_into.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'from_str'
|
||||
path = 'conversions/from_str.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'try_from_into'
|
||||
path = 'conversions/try_from_into.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'using_as'
|
||||
path = 'conversions/using_as.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'enums1'
|
||||
path = 'enums/enums1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'enums2'
|
||||
path = 'enums/enums2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'enums3'
|
||||
path = 'enums/enums3.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'errors1'
|
||||
path = 'error_handling/errors1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'errors2'
|
||||
path = 'error_handling/errors2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'errors3'
|
||||
path = 'error_handling/errors3.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'errorsn'
|
||||
path = 'error_handling/errorsn.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'result1'
|
||||
path = 'error_handling/result1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'functions1'
|
||||
path = 'functions/functions1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'functions2'
|
||||
path = 'functions/functions2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'functions3'
|
||||
path = 'functions/functions3.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'functions4'
|
||||
path = 'functions/functions4.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'functions5'
|
||||
path = 'functions/functions5.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'generics1'
|
||||
path = 'generics/generics1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'generics2'
|
||||
path = 'generics/generics2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'generics3'
|
||||
path = 'generics/generics3.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'if1'
|
||||
path = 'if/if1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'if2'
|
||||
path = 'if/if2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'macros1'
|
||||
path = 'macros/macros1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'macros2'
|
||||
path = 'macros/macros2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'macros3'
|
||||
path = 'macros/macros3.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'macros4'
|
||||
path = 'macros/macros4.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'modules1'
|
||||
path = 'modules/modules1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'modules2'
|
||||
path = 'modules/modules2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'move_semantics1'
|
||||
path = 'move_semantics/move_semantics1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'move_semantics2'
|
||||
path = 'move_semantics/move_semantics2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'move_semantics3'
|
||||
path = 'move_semantics/move_semantics3.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'move_semantics4'
|
||||
path = 'move_semantics/move_semantics4.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'option1'
|
||||
path = 'option/option1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'option2'
|
||||
path = 'option/option2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'primitive_types1'
|
||||
path = 'primitive_types/primitive_types1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'primitive_types2'
|
||||
path = 'primitive_types/primitive_types2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'primitive_types3'
|
||||
path = 'primitive_types/primitive_types3.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'primitive_types4'
|
||||
path = 'primitive_types/primitive_types4.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'primitive_types5'
|
||||
path = 'primitive_types/primitive_types5.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'primitive_types6'
|
||||
path = 'primitive_types/primitive_types6.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'quiz1'
|
||||
path = 'quiz1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'quiz2'
|
||||
path = 'quiz2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'quiz3'
|
||||
path = 'quiz3.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'quiz4'
|
||||
path = 'quiz4.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'arc1'
|
||||
path = 'standard_library_types/arc1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'box1'
|
||||
path = 'standard_library_types/box1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'iterators2'
|
||||
path = 'standard_library_types/iterators2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'iterators3'
|
||||
path = 'standard_library_types/iterators3.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'iterators4'
|
||||
path = 'standard_library_types/iterators4.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'strings1'
|
||||
path = 'strings/strings1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'strings2'
|
||||
path = 'strings/strings2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'structs1'
|
||||
path = 'structs/structs1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'structs2'
|
||||
path = 'structs/structs2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'structs3'
|
||||
path = 'structs/structs3.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'tests1'
|
||||
path = 'tests/tests1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'tests2'
|
||||
path = 'tests/tests2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'tests3'
|
||||
path = 'tests/tests3.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'threads1'
|
||||
path = 'threads/threads1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'traits1'
|
||||
path = 'traits/traits1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'traits2'
|
||||
path = 'traits/traits2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'variables1'
|
||||
path = 'variables/variables1.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'variables2'
|
||||
path = 'variables/variables2.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'variables3'
|
||||
path = 'variables/variables3.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'variables4'
|
||||
path = 'variables/variables4.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'variables5'
|
||||
path = 'variables/variables5.rs'
|
||||
|
||||
[[bin]]
|
||||
name = 'variables6'
|
||||
path = 'variables/variables6.rs'
|
||||
@ -6,12 +6,10 @@
|
||||
// check clippy's suggestions from the output to solve the exercise.
|
||||
// Execute `rustlings hint clippy1` for hints :)
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
fn main() {
|
||||
let x = 1.2331f64;
|
||||
let y = 1.2332f64;
|
||||
if y != x {
|
||||
if (y - x).abs() > f64::MIN {
|
||||
println!("Success!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
// clippy2.rs
|
||||
// Make me compile! Execute `rustlings hint clippy2` for hints :)
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
fn main() {
|
||||
let mut res = 42;
|
||||
let option = Some(12);
|
||||
for x in option {
|
||||
if let Some(x) = option {
|
||||
res += x;
|
||||
}
|
||||
println!("{}", res);
|
||||
|
||||
@ -11,15 +11,16 @@
|
||||
// Execute the command `rustlings hint hashmap1` if you need
|
||||
// hints.
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn fruit_basket() -> HashMap<String, u32> {
|
||||
let mut basket = // TODO: declare your hash map here.
|
||||
let mut basket = HashMap::new();
|
||||
|
||||
// Two bananas are already given for you :)
|
||||
basket.insert(String::from("banana"), 2);
|
||||
basket.insert(String::from("apple"), 100);
|
||||
basket.insert(String::from("orange"),1);
|
||||
|
||||
// TODO: Put more fruits in your basket here.
|
||||
|
||||
|
||||
@ -12,8 +12,6 @@
|
||||
// Execute the command `rustlings hint hashmap2` if you need
|
||||
// hints.
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Hash, PartialEq, Eq)]
|
||||
@ -38,6 +36,9 @@ fn fruit_basket(basket: &mut HashMap<Fruit, u32>) {
|
||||
// TODO: Put new fruits if not already present. Note that you
|
||||
// are not allowed to put any type of fruit that's already
|
||||
// present!
|
||||
if !basket.contains_key(&fruit) {
|
||||
basket.insert(fruit, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,11 +4,10 @@
|
||||
// Make me compile and pass the test!
|
||||
// Execute the command `rustlings hint vec1` if you need hints.
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
fn array_and_vec() -> ([i32; 4], Vec<i32>) {
|
||||
let a = [10, 20, 30, 40]; // a plain array
|
||||
let v = // TODO: declare your vector here with the macro for vectors
|
||||
let v: Vec<i32> = a.into();
|
||||
|
||||
(a, v)
|
||||
}
|
||||
|
||||
@ -7,12 +7,9 @@
|
||||
// Execute the command `rustlings hint vec2` if you need
|
||||
// hints.
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
fn vec_loop(mut v: Vec<i32>) -> Vec<i32> {
|
||||
for i in v.iter_mut() {
|
||||
// TODO: Fill this up so that each element in the Vec `v` is
|
||||
// multiplied by 2.
|
||||
*i *= 2;
|
||||
}
|
||||
|
||||
// At this point, `v` should be equal to [4, 8, 12, 16, 20].
|
||||
|
||||
@ -2,17 +2,15 @@
|
||||
// Read more about them at https://doc.rust-lang.org/std/convert/trait.AsRef.html
|
||||
// and https://doc.rust-lang.org/std/convert/trait.AsMut.html, respectively.
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
// Obtain the number of bytes (not characters) in the given argument
|
||||
// Add the AsRef trait appropriately as a trait bound
|
||||
fn byte_counter<T>(arg: T) -> usize {
|
||||
fn byte_counter<T: AsRef<str>>(arg: T) -> usize {
|
||||
arg.as_ref().as_bytes().len()
|
||||
}
|
||||
|
||||
// Obtain the number of characters (not bytes) in the given argument
|
||||
// Add the AsRef trait appropriately as a trait bound
|
||||
fn char_counter<T>(arg: T) -> usize {
|
||||
fn char_counter<T: AsRef<str>>(arg: T) -> usize {
|
||||
arg.as_ref().chars().count()
|
||||
}
|
||||
|
||||
|
||||
@ -33,10 +33,37 @@ impl Default for Person {
|
||||
// If while parsing the age, something goes wrong, then return the default of Person
|
||||
// Otherwise, then return an instantiated Person object with the results
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
impl From<&str> for Person {
|
||||
fn from(s: &str) -> Person {
|
||||
if s.len() == 0 {
|
||||
return Person::default();
|
||||
} else {
|
||||
let mut parts = s.split(',');
|
||||
let try_name = match &parts.next() {
|
||||
Some(name) => {
|
||||
if name.len() > 0 {
|
||||
name.to_string()
|
||||
} else {
|
||||
return Person::default();
|
||||
}
|
||||
}
|
||||
None => return Person::default(),
|
||||
};
|
||||
let try_age = match &parts.next() {
|
||||
Some(age) => match age.parse::<usize>() {
|
||||
Ok(age) => age,
|
||||
Err(_) => return Person::default(),
|
||||
},
|
||||
None => return Person::default(),
|
||||
};
|
||||
if parts.next().is_some() {
|
||||
return Person::default();
|
||||
}
|
||||
Person {
|
||||
name: try_name,
|
||||
age: try_age,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,15 @@ struct Person {
|
||||
age: usize,
|
||||
}
|
||||
|
||||
// I AM NOT DONE
|
||||
#[derive(Debug)]
|
||||
struct NameAndAgeNeeded;
|
||||
|
||||
impl std::fmt::Display for NameAndAgeNeeded {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Name and Age are Needed")
|
||||
}
|
||||
}
|
||||
impl error::Error for NameAndAgeNeeded {}
|
||||
|
||||
// Steps:
|
||||
// 1. If the length of the provided string is 0, an error should be returned
|
||||
@ -26,6 +34,35 @@ struct Person {
|
||||
impl FromStr for Person {
|
||||
type Err = Box<dyn error::Error>;
|
||||
fn from_str(s: &str) -> Result<Person, Self::Err> {
|
||||
if !s.contains(",") || s.len() == 0 {
|
||||
return Err(NameAndAgeNeeded.into());
|
||||
} else {
|
||||
let mut parts = s.split(",");
|
||||
let try_name = match &parts.next() {
|
||||
Some(name) => {
|
||||
if name.len() > 0 {
|
||||
name.to_string()
|
||||
} else {
|
||||
return Err(NameAndAgeNeeded.into());
|
||||
}
|
||||
}
|
||||
None => return Err(NameAndAgeNeeded.into()),
|
||||
};
|
||||
let try_age = match &parts.next() {
|
||||
Some(age) => match age.parse::<usize>() {
|
||||
Ok(age) => age,
|
||||
Err(_) => return Err(NameAndAgeNeeded.into()),
|
||||
},
|
||||
None => return Err(NameAndAgeNeeded.into()),
|
||||
};
|
||||
if parts.next().is_some() {
|
||||
return Err(NameAndAgeNeeded.into());
|
||||
}
|
||||
Ok(Person {
|
||||
name: try_name,
|
||||
age: try_age,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,42 +3,65 @@
|
||||
// instead of the target type itself.
|
||||
// You can read more about it at https://doc.rust-lang.org/std/convert/trait.TryFrom.html
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::error;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug)]
|
||||
struct Color {
|
||||
red: u8,
|
||||
green: u8,
|
||||
blue: u8,
|
||||
}
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
// Your task is to complete this implementation
|
||||
// and return an Ok result of inner type Color.
|
||||
// You need to create an implementation for a tuple of three integers,
|
||||
// an array of three integers and a slice of integers.
|
||||
// You need create implementation for a tuple of three integer,
|
||||
// an array of three integer and slice of integer.
|
||||
//
|
||||
// Note that the implementation for tuple and array will be checked at compile time,
|
||||
// but the slice implementation needs to check the slice length!
|
||||
// Also note that correct RGB color values must be integers in the 0..=255 range.
|
||||
// Note, that implementation for tuple and array will be checked at compile-time,
|
||||
// but slice implementation need check slice length!
|
||||
// Also note, that chunk of correct rgb color must be integer in range 0..=255.
|
||||
|
||||
// Tuple implementation
|
||||
impl TryFrom<(i16, i16, i16)> for Color {
|
||||
type Error = Box<dyn error::Error>;
|
||||
fn try_from(tuple: (i16, i16, i16)) -> Result<Self, Self::Error> {}
|
||||
type Error = String;
|
||||
fn try_from(tuple: (i16, i16, i16)) -> Result<Self, Self::Error> {
|
||||
let red = u8::try_from(tuple.0).expect("Could not convert red to u8");
|
||||
let green = u8::try_from(tuple.1).unwrap();
|
||||
let blue = u8::try_from(tuple.2).unwrap();
|
||||
|
||||
Ok(Color { red, green, blue })
|
||||
}
|
||||
}
|
||||
|
||||
// Array implementation
|
||||
impl TryFrom<[i16; 3]> for Color {
|
||||
type Error = Box<dyn error::Error>;
|
||||
fn try_from(arr: [i16; 3]) -> Result<Self, Self::Error> {}
|
||||
type Error = String;
|
||||
fn try_from(arr: [i16; 3]) -> Result<Self, Self::Error> {
|
||||
let red = u8::try_from(arr[0]).expect("Could not convert red to u8.");
|
||||
let green = u8::try_from(arr[1]).expect("Could not convert green to u8.");
|
||||
let blue = u8::try_from(arr[2]).expect("Could not convert blue to u8");
|
||||
|
||||
Ok(Color { red, green, blue })
|
||||
}
|
||||
}
|
||||
|
||||
// Slice implementation
|
||||
impl TryFrom<&[i16]> for Color {
|
||||
type Error = Box<dyn error::Error>;
|
||||
fn try_from(slice: &[i16]) -> Result<Self, Self::Error> {}
|
||||
type Error = String;
|
||||
fn try_from(slice: &[i16]) -> Result<Self, Self::Error> {
|
||||
if slice.len() > 3 {
|
||||
return Err("Invalid slice length.".to_string());
|
||||
}
|
||||
|
||||
if let [red, green, blue] = slice {
|
||||
return Ok(Color {
|
||||
red: u8::try_from(*red).expect("Could not convert red color."),
|
||||
green: u8::try_from(*green).expect("Could not convert green color."),
|
||||
blue: u8::try_from(*blue).expect("Could not convert green color."),
|
||||
});
|
||||
}
|
||||
|
||||
Err("Invalid".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@ -64,95 +87,65 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_tuple_out_of_range_positive() {
|
||||
assert!(Color::try_from((256, 1000, 10000)).is_err());
|
||||
let _ = Color::try_from((256, 1000, 10000)).unwrap();
|
||||
}
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_tuple_out_of_range_negative() {
|
||||
assert!(Color::try_from((-1, -10, -256)).is_err());
|
||||
}
|
||||
#[test]
|
||||
fn test_tuple_sum() {
|
||||
assert!(Color::try_from((-1, 255, 255)).is_err());
|
||||
let _ = Color::try_from((-1, -10, -256)).unwrap();
|
||||
}
|
||||
#[test]
|
||||
fn test_tuple_correct() {
|
||||
let c: Result<Color, _> = (183, 65, 14).try_into();
|
||||
assert!(c.is_ok());
|
||||
assert_eq!(
|
||||
c.unwrap(),
|
||||
Color {
|
||||
red: 183,
|
||||
green: 65,
|
||||
blue: 14
|
||||
}
|
||||
);
|
||||
let c: Color = (183, 65, 14).try_into().unwrap();
|
||||
assert_eq!(c.red, 183);
|
||||
assert_eq!(c.green, 65);
|
||||
assert_eq!(c.blue, 14);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_array_out_of_range_positive() {
|
||||
let c: Result<Color, _> = [1000, 10000, 256].try_into();
|
||||
assert!(c.is_err());
|
||||
let _: Color = [1000, 10000, 256].try_into().unwrap();
|
||||
}
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_array_out_of_range_negative() {
|
||||
let c: Result<Color, _> = [-10, -256, -1].try_into();
|
||||
assert!(c.is_err());
|
||||
}
|
||||
#[test]
|
||||
fn test_array_sum() {
|
||||
let c: Result<Color, _> = [-1, 255, 255].try_into();
|
||||
assert!(c.is_err());
|
||||
let _: Color = [-10, -256, -1].try_into().unwrap();
|
||||
}
|
||||
#[test]
|
||||
fn test_array_correct() {
|
||||
let c: Result<Color, _> = [183, 65, 14].try_into();
|
||||
assert!(c.is_ok());
|
||||
assert_eq!(
|
||||
c.unwrap(),
|
||||
Color {
|
||||
red: 183,
|
||||
green: 65,
|
||||
blue: 14
|
||||
}
|
||||
);
|
||||
let c: Color = [183, 65, 14].try_into().unwrap();
|
||||
assert_eq!(c.red, 183);
|
||||
assert_eq!(c.green, 65);
|
||||
assert_eq!(c.blue, 14);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_slice_out_of_range_positive() {
|
||||
let arr = [10000, 256, 1000];
|
||||
assert!(Color::try_from(&arr[..]).is_err());
|
||||
let _ = Color::try_from(&arr[..]).unwrap();
|
||||
}
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_slice_out_of_range_negative() {
|
||||
let arr = [-256, -1, -10];
|
||||
assert!(Color::try_from(&arr[..]).is_err());
|
||||
}
|
||||
#[test]
|
||||
fn test_slice_sum() {
|
||||
let arr = [-1, 255, 255];
|
||||
assert!(Color::try_from(&arr[..]).is_err());
|
||||
let _ = Color::try_from(&arr[..]).unwrap();
|
||||
}
|
||||
#[test]
|
||||
fn test_slice_correct() {
|
||||
let v = vec![183, 65, 14];
|
||||
let c: Result<Color, _> = Color::try_from(&v[..]);
|
||||
assert!(c.is_ok());
|
||||
assert_eq!(
|
||||
c.unwrap(),
|
||||
Color {
|
||||
red: 183,
|
||||
green: 65,
|
||||
blue: 14
|
||||
}
|
||||
);
|
||||
let c = Color::try_from(&v[..]).unwrap();
|
||||
assert_eq!(c.red, 183);
|
||||
assert_eq!(c.green, 65);
|
||||
assert_eq!(c.blue, 14);
|
||||
}
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_slice_excess_length() {
|
||||
let v = vec![0, 0, 0, 0];
|
||||
assert!(Color::try_from(&v[..]).is_err());
|
||||
}
|
||||
#[test]
|
||||
fn test_slice_insufficient_length() {
|
||||
let v = vec![0, 0];
|
||||
assert!(Color::try_from(&v[..]).is_err());
|
||||
let _ = Color::try_from(&v[..]).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,11 +5,9 @@
|
||||
// The goal is to make sure that the division does not fail to compile
|
||||
// and returns the proper type.
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
fn average(values: &[f64]) -> f64 {
|
||||
let total = values.iter().fold(0.0, |a, b| a + b);
|
||||
total / values.len()
|
||||
total / values.len() as f64
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
@ -17,27 +17,23 @@
|
||||
//
|
||||
// Execute `rustlings hint errorsn` for hints :)
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
|
||||
fn main() {}
|
||||
|
||||
// PositiveNonzeroInteger is a struct defined below the tests.
|
||||
fn read_and_validate(
|
||||
b: &mut dyn io::BufRead,
|
||||
) -> Result<PositiveNonzeroInteger, Box<dyn error::Error>> {
|
||||
let mut line = String::new();
|
||||
b.read_line(&mut line);
|
||||
let num: i64 = line.trim().parse();
|
||||
let answer = PositiveNonzeroInteger::new(num);
|
||||
answer
|
||||
b.read_line(&mut line)?;
|
||||
let num: i64 = line.trim().parse()?;
|
||||
let answer = PositiveNonzeroInteger::new(num)?;
|
||||
Ok(answer)
|
||||
}
|
||||
|
||||
//
|
||||
// Nothing below this needs to be modified
|
||||
//
|
||||
|
||||
// This is a test helper function that turns a &str into a BufReader.
|
||||
fn test_with_str(s: &str) -> Result<PositiveNonzeroInteger, Box<dyn error::Error>> {
|
||||
let mut b = io::BufReader::new(s.as_bytes());
|
||||
@ -108,12 +104,15 @@ enum CreationError {
|
||||
|
||||
impl fmt::Display for CreationError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let description = match *self {
|
||||
CreationError::Negative => "Number is negative",
|
||||
CreationError::Zero => "Number is zero",
|
||||
};
|
||||
f.write_str(description)
|
||||
f.write_str((self as &error::Error).description())
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for CreationError {}
|
||||
impl error::Error for CreationError {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
CreationError::Negative => "Negative",
|
||||
CreationError::Zero => "Zero",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// result1.rs
|
||||
// Make this test pass! Execute `rustlings hint result1` for hints :)
|
||||
|
||||
// I AM NOT DONE
|
||||
fn main() {}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct PositiveNonzeroInteger(u64);
|
||||
@ -14,7 +14,13 @@ enum CreationError {
|
||||
|
||||
impl PositiveNonzeroInteger {
|
||||
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
|
||||
if value > 0 {
|
||||
Ok(PositiveNonzeroInteger(value as u64))
|
||||
} else if value < 0 {
|
||||
Err(CreationError::Negative)
|
||||
} else {
|
||||
Err(CreationError::Zero)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
// This shopping list program isn't compiling!
|
||||
// Use your knowledge of generics to fix it.
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
fn main() {
|
||||
let mut shopping_list: Vec<?> = Vec::new();
|
||||
let mut shopping_list: Vec<&str> = Vec::new();
|
||||
shopping_list.push("milk");
|
||||
}
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
// This powerful wrapper provides the ability to store a positive integer value.
|
||||
// Rewrite it using generics so that it supports wrapping ANY type.
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
struct Wrapper {
|
||||
value: u32,
|
||||
struct Wrapper<T> {
|
||||
value: T,
|
||||
}
|
||||
|
||||
impl Wrapper {
|
||||
pub fn new(value: u32) -> Self {
|
||||
impl<T> Wrapper<T> {
|
||||
pub fn new(value: T) -> Self {
|
||||
Wrapper { value }
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,18 +10,33 @@
|
||||
|
||||
// Execute 'rustlings hint generics3' for hints!
|
||||
|
||||
// I AM NOT DONE
|
||||
fn main() {}
|
||||
|
||||
pub struct ReportCard {
|
||||
pub grade: f32,
|
||||
pub student_name: String,
|
||||
pub student_age: u8,
|
||||
pub alpha: bool,
|
||||
}
|
||||
|
||||
impl ReportCard {
|
||||
pub fn get_alpha(&self) -> String {
|
||||
if self.grade > 4.0 {
|
||||
format!("A+")
|
||||
} else {
|
||||
format!("B")
|
||||
}
|
||||
}
|
||||
pub fn print(&self) -> String {
|
||||
format!("{} ({}) - achieved a grade of {}",
|
||||
&self.student_name, &self.student_age, &self.grade)
|
||||
let grade = if self.alpha {
|
||||
self.get_alpha()
|
||||
} else {
|
||||
self.grade.to_string()
|
||||
};
|
||||
format!(
|
||||
"{} ({}) - achieved a grade of {}",
|
||||
&self.student_name, &self.student_age, grade
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +50,7 @@ mod tests {
|
||||
grade: 2.1,
|
||||
student_name: "Tom Wriggle".to_string(),
|
||||
student_age: 12,
|
||||
alpha: false,
|
||||
};
|
||||
assert_eq!(
|
||||
report_card.print(),
|
||||
@ -46,9 +62,10 @@ mod tests {
|
||||
fn generate_alphabetic_report_card() {
|
||||
// TODO: Make sure to change the grade here after you finish the exercise.
|
||||
let report_card = ReportCard {
|
||||
grade: 2.1,
|
||||
grade: 4.1,
|
||||
student_name: "Gary Plotter".to_string(),
|
||||
student_age: 11,
|
||||
alpha: true,
|
||||
};
|
||||
assert_eq!(
|
||||
report_card.print(),
|
||||
|
||||
@ -1,23 +1,19 @@
|
||||
// option1.rs
|
||||
// Make me compile! Execute `rustlings hint option1` for hints
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
// you can modify anything EXCEPT for this function's sig
|
||||
fn print_number(maybe_number: Option<u16>) {
|
||||
println!("printing: {}", maybe_number.unwrap());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
print_number(13);
|
||||
print_number(99);
|
||||
print_number(Some(13));
|
||||
print_number(Some(99));
|
||||
|
||||
let mut numbers: [Option<u16>; 5];
|
||||
let mut numbers: [Option<u16>; 5] = [Some(0); 5];
|
||||
for iter in 0..5 {
|
||||
let number_to_add: u16 = {
|
||||
((iter * 1235) + 2) / (4 * 16)
|
||||
};
|
||||
let number_to_add: u16 = { ((iter * 1235) + 2) / (4 * 16) };
|
||||
|
||||
numbers[iter as usize] = number_to_add;
|
||||
numbers[iter as usize] = Some(number_to_add);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,16 +1,14 @@
|
||||
// option2.rs
|
||||
// Make me compile! Execute `rustlings hint option2` for hints
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
fn main() {
|
||||
let optional_word = Some(String::from("rustlings"));
|
||||
// TODO: Make this an if let statement whose value is "Some" type
|
||||
word = optional_word {
|
||||
if let Some(word) = optional_word {
|
||||
println!("The word is: {}", word);
|
||||
} else {
|
||||
println!("The optional word doesn't contain anything");
|
||||
}
|
||||
};
|
||||
|
||||
let mut optional_integers_vec: Vec<Option<i8>> = Vec::new();
|
||||
for x in 1..10 {
|
||||
@ -19,7 +17,7 @@ fn main() {
|
||||
|
||||
// TODO: make this a while let statement - remember that vector.pop also adds another layer of Option<T>
|
||||
// You can stack `Option<T>`'s into while let and if let
|
||||
integer = optional_integers_vec.pop() {
|
||||
println!("current value: {}", integer);
|
||||
while let Some(integer) = optional_integers_vec.pop() {
|
||||
println!("current value: {}", integer.unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,25 +12,22 @@
|
||||
// Because we are using threads, our values need to be thread-safe. Therefore,
|
||||
// we are using Arc. We need to make a change in each of the two TODOs.
|
||||
|
||||
|
||||
// Make this code compile by filling in a value for `shared_numbers` where the
|
||||
// first TODO comment is, and create an initial binding for `child_numbers`
|
||||
// where the second TODO comment is. Try not to create any copies of the `numbers` Vec!
|
||||
// Execute `rustlings hint arc1` for hints :)
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
#![forbid(unused_imports)] // Do not change this, (or the next) line.
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
fn main() {
|
||||
let numbers: Vec<_> = (0..100u32).collect();
|
||||
let shared_numbers = // TODO
|
||||
let shared_numbers = Arc::new(numbers);
|
||||
let mut joinhandles = Vec::new();
|
||||
|
||||
for offset in 0..8 {
|
||||
let child_numbers = // TODO
|
||||
let child_numbers = Arc::clone(&shared_numbers);
|
||||
joinhandles.push(thread::spawn(move || {
|
||||
let mut i = offset;
|
||||
let mut sum = 0;
|
||||
|
||||
@ -16,11 +16,9 @@
|
||||
//
|
||||
// Execute `rustlings hint box1` for hints :)
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum List {
|
||||
Cons(i32, List),
|
||||
Cons(i32, Box<List>),
|
||||
Nil,
|
||||
}
|
||||
|
||||
@ -33,11 +31,11 @@ fn main() {
|
||||
}
|
||||
|
||||
pub fn create_empty_list() -> List {
|
||||
unimplemented!()
|
||||
List::Nil
|
||||
}
|
||||
|
||||
pub fn create_non_empty_list() -> List {
|
||||
unimplemented!()
|
||||
List::Cons(5, Box::new(List::Nil))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -8,17 +8,15 @@
|
||||
//
|
||||
// Execute `rustlings hint iterators1` for hints :D
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
fn main () {
|
||||
fn main() {
|
||||
let my_fav_fruits = vec!["banana", "custard apple", "avocado", "peach", "raspberry"];
|
||||
|
||||
let mut my_iterable_fav_fruits = ???; // TODO: Step 1
|
||||
let mut my_iterable_fav_fruits = my_fav_fruits.into_iter(); // TODO: Step 1
|
||||
|
||||
assert_eq!(my_iterable_fav_fruits.next(), Some(&"banana"));
|
||||
assert_eq!(my_iterable_fav_fruits.next(), ???); // TODO: Step 2
|
||||
assert_eq!(my_iterable_fav_fruits.next(), Some(&"avocado"));
|
||||
assert_eq!(my_iterable_fav_fruits.next(), ???); // TODO: Step 2.1
|
||||
assert_eq!(my_iterable_fav_fruits.next(), Some(&"raspberry"));
|
||||
assert_eq!(my_iterable_fav_fruits.next(), ???); // TODO: Step 3
|
||||
assert_eq!(my_iterable_fav_fruits.next(), Some("banana"));
|
||||
assert_eq!(my_iterable_fav_fruits.next(), Some("custard apple")); // TODO: Step 2
|
||||
assert_eq!(my_iterable_fav_fruits.next(), Some("avocado"));
|
||||
assert_eq!(my_iterable_fav_fruits.next(), Some("peach")); // TODO: Step 2.1
|
||||
assert_eq!(my_iterable_fav_fruits.next(), Some("raspberry"));
|
||||
assert_eq!(my_iterable_fav_fruits.next(), None); // TODO: Step 3
|
||||
}
|
||||
|
||||
@ -3,16 +3,16 @@
|
||||
// can offer. Follow the steps to complete the exercise.
|
||||
// As always, there are hints if you execute `rustlings hint iterators2`!
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
// Step 1.
|
||||
// Complete the `capitalize_first` function.
|
||||
// "hello" -> "Hello"
|
||||
fn main() {}
|
||||
|
||||
pub fn capitalize_first(input: &str) -> String {
|
||||
let mut c = input.chars();
|
||||
match c.next() {
|
||||
None => String::new(),
|
||||
Some(first) => ???,
|
||||
Some(last) => last.to_string().to_uppercase() + c.as_str(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,11 @@ pub fn capitalize_first(input: &str) -> String {
|
||||
// Return a vector of strings.
|
||||
// ["hello", "world"] -> ["Hello", "World"]
|
||||
pub fn capitalize_words_vector(words: &[&str]) -> Vec<String> {
|
||||
vec![]
|
||||
let mut final_words = vec![];
|
||||
for word in words {
|
||||
final_words.push(capitalize_first(word));
|
||||
}
|
||||
final_words
|
||||
}
|
||||
|
||||
// Step 3.
|
||||
@ -29,7 +33,11 @@ pub fn capitalize_words_vector(words: &[&str]) -> Vec<String> {
|
||||
// Return a single string.
|
||||
// ["hello", " ", "world"] -> "Hello World"
|
||||
pub fn capitalize_words_string(words: &[&str]) -> String {
|
||||
String::new()
|
||||
let mut return_string = String::new();
|
||||
for word in words {
|
||||
return_string += &capitalize_first(word);
|
||||
}
|
||||
return_string
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
// list_of_results functions.
|
||||
// Execute `rustlings hint iterators3` to get some hints!
|
||||
|
||||
// I AM NOT DONE
|
||||
pub fn main() {}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum DivisionError {
|
||||
@ -22,20 +22,37 @@ pub struct NotDivisibleError {
|
||||
|
||||
// Calculate `a` divided by `b` if `a` is evenly divisible by `b`.
|
||||
// Otherwise, return a suitable error.
|
||||
pub fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {}
|
||||
pub fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {
|
||||
if b == 0 {
|
||||
Err(DivisionError::DivideByZero)
|
||||
} else if a % b == 0 {
|
||||
Ok(a / b)
|
||||
} else {
|
||||
Err(DivisionError::NotDivisible(NotDivisibleError {
|
||||
dividend: a,
|
||||
divisor: b,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
// Complete the function and return a value of the correct type so the test passes.
|
||||
// Desired output: Ok([1, 11, 1426, 3])
|
||||
fn result_with_list() -> () {
|
||||
// 2. Get the remaining tests to pass by completing the result_with_list and
|
||||
fn result_with_list() -> Result<Vec<i32>, DivisionError> {
|
||||
let numbers = vec![27, 297, 38502, 81];
|
||||
let division_results = numbers.into_iter().map(|n| divide(n, 27));
|
||||
let division_results = numbers
|
||||
.into_iter()
|
||||
.map(|n| divide(n, 27))
|
||||
.collect::<Result<Vec<_>, _>>();
|
||||
division_results
|
||||
}
|
||||
|
||||
// Complete the function and return a value of the correct type so the test passes.
|
||||
// Desired output: [Ok(1), Ok(11), Ok(1426), Ok(3)]
|
||||
fn list_of_results() -> () {
|
||||
fn list_of_results() -> Vec<Result<i32, DivisionError>> {
|
||||
let numbers = vec![27, 297, 38502, 81];
|
||||
let division_results = numbers.into_iter().map(|n| divide(n, 27));
|
||||
division_results.collect::<Vec<Result<_, _>>>()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// iterators4.rs
|
||||
|
||||
// I AM NOT DONE
|
||||
fn main() {}
|
||||
|
||||
pub fn factorial(num: u64) -> u64 {
|
||||
// Complete this function to return the factorial of num
|
||||
@ -12,6 +12,8 @@ pub fn factorial(num: u64) -> u64 {
|
||||
// For an extra challenge, don't use:
|
||||
// - recursion
|
||||
// Execute `rustlings hint iterators4` for hints.
|
||||
|
||||
(2..=num).fold(1, |acc, x| acc * x)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
//
|
||||
// Make the code compile and the tests pass.
|
||||
|
||||
// I AM NOT DONE
|
||||
fn main() {}
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
@ -36,6 +36,7 @@ fn count_for(map: &HashMap<String, Progress>, value: Progress) -> usize {
|
||||
fn count_iterator(map: &HashMap<String, Progress>, value: Progress) -> usize {
|
||||
// map is a hashmap with String keys and Progress values.
|
||||
// map = { "variables1": Complete, "from_str": None, ... }
|
||||
map.values().filter(|val| **val == value).count()
|
||||
}
|
||||
|
||||
fn count_collection_for(collection: &[HashMap<String, Progress>], value: Progress) -> usize {
|
||||
@ -54,6 +55,10 @@ fn count_collection_iterator(collection: &[HashMap<String, Progress>], value: Pr
|
||||
// collection is a slice of hashmaps.
|
||||
// collection = [{ "variables1": Complete, "from_str": None, ... },
|
||||
// { "variables2": Complete, ... }, ... ]
|
||||
collection
|
||||
.iter()
|
||||
.map(|map| map.values().filter(|val| **val == value).count())
|
||||
.sum()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
// Make the code compile and the tests pass!
|
||||
// If you have issues execute `rustlings hint structs3`
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Package {
|
||||
sender_country: String,
|
||||
@ -15,7 +14,6 @@ struct Package {
|
||||
impl Package {
|
||||
fn new(sender_country: String, recipient_country: String, weight_in_grams: i32) -> Package {
|
||||
if weight_in_grams <= 0 {
|
||||
// Something goes here...
|
||||
panic!("crash and burn");
|
||||
} else {
|
||||
return Package {
|
||||
@ -27,12 +25,13 @@ impl Package {
|
||||
}
|
||||
|
||||
fn is_international(&self) -> bool {
|
||||
// Something goes here...
|
||||
true
|
||||
if self.sender_country != self.recipient_country {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn get_fees(&self, cents_per_gram: i32) -> i32 {
|
||||
// Something goes here...
|
||||
cents_per_gram * self.weight_in_grams
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
// we expect to get when we call `is_even(5)`.
|
||||
// Execute `rustlings hint tests3` for hints :)
|
||||
|
||||
|
||||
pub fn is_even(num: i32) -> bool {
|
||||
num % 2 == 0
|
||||
}
|
||||
@ -21,4 +20,5 @@ mod tests {
|
||||
#[test]
|
||||
fn is_false_when_even() {
|
||||
assert!(!is_even(5));
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,9 +6,7 @@
|
||||
// of "waiting..." and the program ends without timing out when running,
|
||||
// you've got it :)
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
@ -17,15 +15,15 @@ struct JobStatus {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let status = Arc::new(JobStatus { jobs_completed: 0 });
|
||||
let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 }));
|
||||
let status_shared = status.clone();
|
||||
thread::spawn(move || {
|
||||
for _ in 0..10 {
|
||||
thread::sleep(Duration::from_millis(250));
|
||||
status_shared.jobs_completed += 1;
|
||||
status_shared.lock().unwrap().jobs_completed += 1;
|
||||
}
|
||||
});
|
||||
while status.jobs_completed < 10 {
|
||||
while status.lock().unwrap().jobs_completed < 10 {
|
||||
println!("waiting... ");
|
||||
thread::sleep(Duration::from_millis(500));
|
||||
}
|
||||
|
||||
@ -8,14 +8,14 @@
|
||||
// which appends "Bar" to any object
|
||||
// implementing this trait.
|
||||
|
||||
// I AM NOT DONE
|
||||
|
||||
trait AppendBar {
|
||||
fn append_bar(self) -> Self;
|
||||
}
|
||||
|
||||
impl AppendBar for String {
|
||||
//Add your code here
|
||||
fn append_bar(self) -> String {
|
||||
format!("{}{}", self, "Bar")
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
@ -10,13 +10,23 @@
|
||||
// No boiler plate code this time,
|
||||
// you can do this!
|
||||
|
||||
// I AM NOT DONE
|
||||
fn main() {}
|
||||
|
||||
trait AppendBar {
|
||||
fn append_bar(self) -> Self;
|
||||
}
|
||||
|
||||
//TODO: Add your code here
|
||||
impl AppendBar for Vec<String> {
|
||||
fn append_bar(self) -> Self {
|
||||
let mut new_vec = Vec::new();
|
||||
for item in self {
|
||||
new_vec.push(format!("{}", item));
|
||||
new_vec.push(format!("{}", String::from("Bar")));
|
||||
}
|
||||
new_vec
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user