first go at the exercises

This commit is contained in:
Laila van Reenen 2024-10-16 16:25:20 +02:00
parent c2400444a9
commit f022d5c2bb
46 changed files with 397 additions and 70 deletions

27
.rustlings-state.txt Normal file
View File

@ -0,0 +1,27 @@
DON'T EDIT THIS FILE!
vecs1
intro1
intro2
variables1
variables2
variables3
variables4
variables5
variables6
functions1
functions2
functions3
functions4
functions5
if1
if2
if3
quiz1
primitive_types1
primitive_types2
primitive_types3
primitive_types4
primitive_types5
primitive_types6

View File

@ -1,4 +1,4 @@
fn main() { fn main() {
// TODO: Fix the code to print "Hello world!". // TODO: Fix the code to print "Hello world!".
printline!("Hello world!"); println!("Hello world!");
} }

View File

@ -1,6 +1,6 @@
fn main() { fn main() {
// TODO: Add the missing keyword. // TODO: Add the missing keyword.
x = 5; let x = 5;
println!("x has the value {x}"); println!("x has the value {x}");
} }

View File

@ -1,6 +1,6 @@
fn main() { fn main() {
// TODO: Change the line below to fix the compiler error. // TODO: Change the line below to fix the compiler error.
let x; let x = 10;
if x == 10 { if x == 10 {
println!("x is ten!"); println!("x is ten!");

View File

@ -1,6 +1,6 @@
fn main() { fn main() {
// TODO: Change the line below to fix the compiler error. // TODO: Change the line below to fix the compiler error.
let x: i32; let x: i32 = 5;
println!("Number {x}"); println!("Number {x}");
} }

View File

@ -1,6 +1,6 @@
// TODO: Fix the compiler error. // TODO: Fix the compiler error.
fn main() { fn main() {
let x = 3; let mut x = 3;
println!("Number {x}"); println!("Number {x}");
x = 5; // Don't change this line x = 5; // Don't change this line

View File

@ -3,6 +3,6 @@ fn main() {
println!("Spell a number: {}", number); println!("Spell a number: {}", number);
// TODO: Fix the compiler error by changing the line below without renaming the variable. // TODO: Fix the compiler error by changing the line below without renaming the variable.
number = 3; let number = 3;
println!("Number plus two is: {}", number + 2); println!("Number plus two is: {}", number + 2);
} }

View File

@ -1,5 +1,5 @@
// TODO: Change the line below to fix the compiler error. // TODO: Change the line below to fix the compiler error.
const NUMBER = 3; const NUMBER: u32 = 3;
fn main() { fn main() {
println!("Number: {NUMBER}"); println!("Number: {NUMBER}");

View File

@ -1,5 +1,10 @@
// TODO: Add some function with the name `call_me` without arguments or a return value. // TODO: Add some function with the name `call_me` without arguments or a return value.
fn call_me()
{
println!("hoi");
}
fn main() { fn main() {
call_me(); // Don't change this line call_me(); // Don't change this line
} }

View File

@ -1,5 +1,5 @@
// TODO: Add the missing type of the argument `num` after the colon `:`. // TODO: Add the missing type of the argument `num` after the colon `:`.
fn call_me(num:) { fn call_me(num: u32) {
for i in 0..num { for i in 0..num {
println!("Ring! Call number {}", i + 1); println!("Ring! Call number {}", i + 1);
} }

View File

@ -6,5 +6,5 @@ fn call_me(num: u8) {
fn main() { fn main() {
// TODO: Fix the function call. // TODO: Fix the function call.
call_me(); call_me(255);
} }

View File

@ -8,7 +8,7 @@ fn is_even(num: i64) -> bool {
} }
// TODO: Fix the function signature. // TODO: Fix the function signature.
fn sale_price(price: i64) -> { fn sale_price(price: i64) -> i64{
if is_even(price) { if is_even(price) {
price - 10 price - 10
} else { } else {

View File

@ -1,6 +1,6 @@
// TODO: Fix the function body without changing the signature. // TODO: Fix the function body without changing the signature.
fn square(num: i32) -> i32 { fn square(num: i32) -> i32 {
num * num; num * num
} }
fn main() { fn main() {

View File

@ -4,6 +4,12 @@ fn bigger(a: i32, b: i32) -> i32 {
// Do not use: // Do not use:
// - another function call // - another function call
// - additional variables // - additional variables
if a < b {
b
}
else {
a
}
} }
fn main() { fn main() {

View File

@ -2,8 +2,12 @@
fn foo_if_fizz(fizzish: &str) -> &str { fn foo_if_fizz(fizzish: &str) -> &str {
if fizzish == "fizz" { if fizzish == "fizz" {
"foo" "foo"
} else { }
1 else if fizzish == "fuzz" {
"bar"
}
else {
"baz"
} }
} }

View File

@ -3,11 +3,11 @@ fn animal_habitat(animal: &str) -> &str {
let identifier = if animal == "crab" { let identifier = if animal == "crab" {
1 1
} else if animal == "gopher" { } else if animal == "gopher" {
2.0 2
} else if animal == "snake" { } else if animal == "snake" {
3 3
} else { } else {
"Unknown" 4
}; };
// Don't change the expression below! // Don't change the expression below!

View File

@ -9,6 +9,7 @@ fn main() {
// TODO: Define a boolean variable with the name `is_evening` before the `if` statement below. // TODO: Define a boolean variable with the name `is_evening` before the `if` statement below.
// The value of the variable should be the negation (opposite) of `is_morning`. // The value of the variable should be the negation (opposite) of `is_morning`.
// let … // let …
let is_evening = !is_morning;
if is_evening { if is_evening {
println!("Good evening!"); println!("Good evening!");
} }

View File

@ -17,6 +17,7 @@ fn main() {
// Try a letter, try a digit (in single quotes), try a special character, try a character // Try a letter, try a digit (in single quotes), try a special character, try a character
// from a different language than your own, try an emoji 😉 // from a different language than your own, try an emoji 😉
// let your_character = ''; // let your_character = '';
let your_character = 'e';
if your_character.is_alphabetic() { if your_character.is_alphabetic() {
println!("Alphabetical!"); println!("Alphabetical!");

View File

@ -1,6 +1,7 @@
fn main() { fn main() {
// TODO: Create an array called `a` with at least 100 elements in it. // TODO: Create an array called `a` with at least 100 elements in it.
// let a = ??? // let a = ???
let a = (1..150).collect::<std::vec::Vec<u8>>();
if a.len() >= 100 { if a.len() >= 100 {
println!("Wow, that's a big array!"); println!("Wow, that's a big array!");

View File

@ -10,6 +10,7 @@ mod tests {
// TODO: Get a slice called `nice_slice` out of the array `a` so that the test passes. // TODO: Get a slice called `nice_slice` out of the array `a` so that the test passes.
// let nice_slice = ??? // let nice_slice = ???
let nice_slice = &a[1..4];
assert_eq!([2, 3, 4], nice_slice); assert_eq!([2, 3, 4], nice_slice);
} }

View File

@ -3,6 +3,8 @@ fn main() {
// TODO: Destructure the `cat` tuple in one statement so that the println works. // TODO: Destructure the `cat` tuple in one statement so that the println works.
// let /* your pattern here */ = cat; // let /* your pattern here */ = cat;
let name = cat.0;
let age = cat.1;
println!("{name} is {age} years old"); println!("{name} is {age} years old");
} }

View File

@ -11,6 +11,7 @@ mod tests {
// TODO: Use a tuple index to access the second element of `numbers` // TODO: Use a tuple index to access the second element of `numbers`
// and assign it to a variable called `second`. // and assign it to a variable called `second`.
// let second = ???; // let second = ???;
let second = numbers.1;
assert_eq!(second, 2, "This is not the 2nd number in the tuple!"); assert_eq!(second, 2, "This is not the 2nd number in the tuple!");
} }

View File

@ -11,6 +11,13 @@
// TODO: Write a function that calculates the price of an order of apples given // TODO: Write a function that calculates the price of an order of apples given
// the quantity bought. // the quantity bought.
// fn calculate_price_of_apples(???) -> ??? { ??? } // fn calculate_price_of_apples(???) -> ??? { ??? }
fn calculate_price_of_apples(apples: u16) -> u16 {
if apples <= 40 {
apples * 2
} else {
apples
}
}
fn main() { fn main() {
// You can optionally experiment here. // You can optionally experiment here.

View File

@ -1,4 +1,5 @@
fn main() { fn main() {
// DON'T EDIT THIS SOLUTION FILE! // Congratulations, you finished the first exercise 🎉
// It will be automatically filled after you finish the exercise. // As an introduction to Rustlings, the first exercise only required
// entering `n` in the terminal to go to the next exercise.
} }

View File

@ -1,4 +1,4 @@
fn main() { fn main() {
// DON'T EDIT THIS SOLUTION FILE! // `println!` instead of `printline!`.
// It will be automatically filled after you finish the exercise. println!("Hello world!");
} }

View File

@ -1,4 +1,6 @@
fn main() { fn main() {
// DON'T EDIT THIS SOLUTION FILE! // Declaring variables requires the `let` keyword.
// It will be automatically filled after you finish the exercise. let x = 5;
println!("x has the value {x}");
} }

View File

@ -1,4 +1,16 @@
fn main() { fn main() {
// DON'T EDIT THIS SOLUTION FILE! // The easiest way to fix the compiler error is to initialize the
// It will be automatically filled after you finish the exercise. // variable `x`. By setting its value to an integer, Rust infers its type
// as `i32` which is the default type for integers.
let x = 42;
// But we can enforce a type different from the default `i32` by adding
// a type annotation:
// let x: u8 = 42;
if x == 10 {
println!("x is ten!");
} else {
println!("x is not ten!");
}
} }

View File

@ -1,4 +1,15 @@
#![allow(clippy::needless_late_init)]
fn main() { fn main() {
// DON'T EDIT THIS SOLUTION FILE! // Reading uninitialized variables isn't allowed in Rust!
// It will be automatically filled after you finish the exercise. // Therefore, we need to assign a value first.
let x: i32 = 42;
println!("Number {x}");
// It is possible to declare a variable and initialize it later.
// But it can't be used before initialization.
let y: i32;
y = 42;
println!("Number {y}");
} }

View File

@ -1,4 +1,9 @@
fn main() { fn main() {
// DON'T EDIT THIS SOLUTION FILE! // In Rust, variables are immutable by default.
// It will be automatically filled after you finish the exercise. // Adding the `mut` keyword after `let` makes the declared variable mutable.
let mut x = 3;
println!("Number {x}");
x = 5;
println!("Number {x}");
} }

View File

@ -1,4 +1,9 @@
fn main() { fn main() {
// DON'T EDIT THIS SOLUTION FILE! let number = "T-H-R-E-E";
// It will be automatically filled after you finish the exercise. println!("Spell a number: {}", number);
// Using variable shadowing
// https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#shadowing
let number = 3;
println!("Number plus two is: {}", number + 2);
} }

View File

@ -1,4 +1,6 @@
// The type of constants must always be annotated.
const NUMBER: u64 = 3;
fn main() { fn main() {
// DON'T EDIT THIS SOLUTION FILE! println!("Number: {NUMBER}");
// It will be automatically filled after you finish the exercise.
} }

View File

@ -1,4 +1,8 @@
fn main() { // Some function with the name `call_me` without arguments or a return value.
// DON'T EDIT THIS SOLUTION FILE! fn call_me() {
// It will be automatically filled after you finish the exercise. println!("Hello world!");
}
fn main() {
call_me();
} }

View File

@ -1,4 +1,11 @@
fn main() { // The type of function arguments must be annotated.
// DON'T EDIT THIS SOLUTION FILE! // Added the type annotation `u64`.
// It will be automatically filled after you finish the exercise. fn call_me(num: u64) {
for i in 0..num {
println!("Ring! Call number {}", i + 1);
}
}
fn main() {
call_me(3);
} }

View File

@ -1,4 +1,10 @@
fn main() { fn call_me(num: u8) {
// DON'T EDIT THIS SOLUTION FILE! for i in 0..num {
// It will be automatically filled after you finish the exercise. println!("Ring! Call number {}", i + 1);
}
}
fn main() {
// `call_me` expects an argument.
call_me(5);
} }

View File

@ -1,4 +1,17 @@
fn main() { fn is_even(num: i64) -> bool {
// DON'T EDIT THIS SOLUTION FILE! num % 2 == 0
// It will be automatically filled after you finish the exercise. }
// The return type must always be annotated.
fn sale_price(price: i64) -> i64 {
if is_even(price) {
price - 10
} else {
price - 3
}
}
fn main() {
let original_price = 51;
println!("Your sale price is {}", sale_price(original_price));
} }

View File

@ -1,4 +1,9 @@
fn main() { fn square(num: i32) -> i32 {
// DON'T EDIT THIS SOLUTION FILE! // Removed the semicolon `;` at the end of the line below to implicitly return the result.
// It will be automatically filled after you finish the exercise. num * num
}
fn main() {
let answer = square(3);
println!("The square of 3 is {answer}");
} }

View File

@ -1,4 +1,32 @@
fn main() { fn bigger(a: i32, b: i32) -> i32 {
// DON'T EDIT THIS SOLUTION FILE! if a > b {
// It will be automatically filled after you finish the exercise. a
} else {
b
}
}
fn main() {
// You can optionally experiment here.
}
// Don't mind this for now :)
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ten_is_bigger_than_eight() {
assert_eq!(10, bigger(10, 8));
}
#[test]
fn fortytwo_is_bigger_than_thirtytwo() {
assert_eq!(42, bigger(32, 42));
}
#[test]
fn equal_numbers() {
assert_eq!(42, bigger(42, 42));
}
} }

View File

@ -1,4 +1,33 @@
fn main() { fn foo_if_fizz(fizzish: &str) -> &str {
// DON'T EDIT THIS SOLUTION FILE! if fizzish == "fizz" {
// It will be automatically filled after you finish the exercise. "foo"
} else if fizzish == "fuzz" {
"bar"
} else {
"baz"
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn foo_for_fizz() {
assert_eq!(foo_if_fizz("fizz"), "foo");
}
#[test]
fn bar_for_fuzz() {
assert_eq!(foo_if_fizz("fuzz"), "bar");
}
#[test]
fn default_to_baz() {
assert_eq!(foo_if_fizz("literally anything"), "baz");
}
} }

View File

@ -1,4 +1,53 @@
fn main() { fn animal_habitat(animal: &str) -> &str {
// DON'T EDIT THIS SOLUTION FILE! let identifier = if animal == "crab" {
// It will be automatically filled after you finish the exercise. 1
} else if animal == "gopher" {
2
} else if animal == "snake" {
3
} else {
// Any unused identifier.
4
};
// Instead of such an identifier, you would use an enum in Rust.
// But we didn't get into enums yet.
if identifier == 1 {
"Beach"
} else if identifier == 2 {
"Burrow"
} else if identifier == 3 {
"Desert"
} else {
"Unknown"
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn gopher_lives_in_burrow() {
assert_eq!(animal_habitat("gopher"), "Burrow")
}
#[test]
fn snake_lives_in_desert() {
assert_eq!(animal_habitat("snake"), "Desert")
}
#[test]
fn crab_lives_on_beach() {
assert_eq!(animal_habitat("crab"), "Beach")
}
#[test]
fn unknown_animal() {
assert_eq!(animal_habitat("dinosaur"), "Unknown")
}
} }

View File

@ -1,4 +1,11 @@
fn main() { fn main() {
// DON'T EDIT THIS SOLUTION FILE! let is_morning = true;
// It will be automatically filled after you finish the exercise. if is_morning {
println!("Good morning!");
}
let is_evening = !is_morning;
if is_evening {
println!("Good evening!");
}
} }

View File

@ -1,4 +1,21 @@
fn main() { fn main() {
// DON'T EDIT THIS SOLUTION FILE! let my_first_initial = 'C';
// It will be automatically filled after you finish the exercise. if my_first_initial.is_alphabetic() {
println!("Alphabetical!");
} else if my_first_initial.is_numeric() {
println!("Numerical!");
} else {
println!("Neither alphabetic nor numeric!");
}
// Example with an emoji.
let your_character = '🦀';
if your_character.is_alphabetic() {
println!("Alphabetical!");
} else if your_character.is_numeric() {
println!("Numerical!");
} else {
println!("Neither alphabetic nor numeric!");
}
} }

View File

@ -1,4 +1,11 @@
fn main() { fn main() {
// DON'T EDIT THIS SOLUTION FILE! // An array with 100 elements of the value 42.
// It will be automatically filled after you finish the exercise. let a = [42; 100];
if a.len() >= 100 {
println!("Wow, that's a big array!");
} else {
println!("Meh, I eat arrays like that for breakfast.");
panic!("Array not big enough, more elements needed");
}
} }

View File

@ -1,4 +1,23 @@
fn main() { fn main() {
// DON'T EDIT THIS SOLUTION FILE! // You can optionally experiment here.
// It will be automatically filled after you finish the exercise. }
#[cfg(test)]
mod tests {
#[test]
fn slice_out_of_array() {
let a = [1, 2, 3, 4, 5];
// 0 1 2 3 4 <- indices
// -------
// |
// +--- slice
// Note that the upper index 4 is excluded.
let nice_slice = &a[1..4];
assert_eq!([2, 3, 4], nice_slice);
// The upper index can be included by using the syntax `..=` (with `=` sign)
let nice_slice = &a[1..=3];
assert_eq!([2, 3, 4], nice_slice);
}
} }

View File

@ -1,4 +1,8 @@
fn main() { fn main() {
// DON'T EDIT THIS SOLUTION FILE! let cat = ("Furry McFurson", 3.5);
// It will be automatically filled after you finish the exercise.
// Destructuring the tuple.
let (name, age) = cat;
println!("{name} is {age} years old");
} }

View File

@ -1,4 +1,16 @@
fn main() { fn main() {
// DON'T EDIT THIS SOLUTION FILE! // You can optionally experiment here.
// It will be automatically filled after you finish the exercise. }
#[cfg(test)]
mod tests {
#[test]
fn indexing_tuple() {
let numbers = (1, 2, 3);
// Tuple indexing syntax.
let second = numbers.1;
assert_eq!(second, 2, "This is not the 2nd number in the tuple!");
}
} }

View File

@ -1,4 +1,30 @@
fn main() { // Mary is buying apples. The price of an apple is calculated as follows:
// DON'T EDIT THIS SOLUTION FILE! // - An apple costs 2 rustbucks.
// It will be automatically filled after you finish the exercise. // - However, if Mary buys more than 40 apples, the price of each apple in the
// entire order is reduced to only 1 rustbuck!
fn calculate_price_of_apples(n_apples: u64) -> u64 {
if n_apples > 40 {
n_apples
} else {
2 * n_apples
}
}
fn main() {
// You can optionally experiment here.
}
// Don't change the tests!
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn verify_test() {
assert_eq!(calculate_price_of_apples(35), 70);
assert_eq!(calculate_price_of_apples(40), 80);
assert_eq!(calculate_price_of_apples(41), 41);
assert_eq!(calculate_price_of_apples(65), 65);
}
} }