Finish Rustlings

This commit is contained in:
Jared Moulton 2021-08-10 23:40:46 -04:00
parent 95b259dfb3
commit 81ead79f01
33 changed files with 648 additions and 196 deletions

70
] Normal file
View 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
View 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
View 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'

View File

@ -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!");
}
}

View File

@ -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);

View File

@ -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.

View File

@ -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);
}
}
}

View File

@ -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)
}

View File

@ -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].

View File

@ -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()
}

View File

@ -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,
}
}
}
}

View File

@ -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,
})
}
}
}

View File

@ -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();
}
}

View File

@ -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() {

View File

@ -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",
}
}
}

View File

@ -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> {
Ok(PositiveNonzeroInteger(value as u64))
if value > 0 {
Ok(PositiveNonzeroInteger(value as u64))
} else if value < 0 {
Err(CreationError::Negative)
} else {
Err(CreationError::Zero)
}
}
}

View File

@ -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");
}

View File

@ -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 }
}
}

View File

@ -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(),

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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;

View File

@ -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)]

View File

@ -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
}

View File

@ -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)]

View File

@ -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)]

View File

@ -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)]

View File

@ -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)]

View File

@ -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
}
}

View File

@ -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));
}
}

View File

@ -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));
}

View File

@ -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() {

View File

@ -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 {