Compare commits

..

13 commits

Author SHA1 Message Date
mo8it 3d540ed946 modules3 solution 2024-06-22 13:35:54 +02:00
mo8it 98cd00de63 modules2 solution 2024-06-22 13:24:06 +02:00
mo8it ecbe9b7324 modules1 solution 2024-06-22 13:12:39 +02:00
mo8it 879f0cd5c6 strings4 solution 2024-06-22 12:51:21 +02:00
mo8it 613ec23f84 strings 3 solution 2024-06-22 12:22:24 +02:00
mo8it f574905b8e strings2 solution 2024-06-22 12:14:04 +02:00
mo8it bd63ece47c string1 solution 2024-06-22 12:05:28 +02:00
mo8it 2901d85662 enums3 solution 2024-06-21 23:18:25 +02:00
mo8it 020711fa97 enums3 solution 2024-06-21 23:05:40 +02:00
mo8it a2dfbd86da enums1 solution 2024-06-21 23:00:38 +02:00
mo8it d6fd251a73 structs3 solution 2024-06-21 22:54:00 +02:00
mo8it 1264510fc0 structs2 solution 2024-06-21 22:31:06 +02:00
mo8it ef842d3a94 structs1 solution 2024-06-21 22:22:37 +02:00
27 changed files with 594 additions and 133 deletions

View file

@ -1,13 +1,12 @@
// Address all the TODOs to make the tests pass!
struct ColorClassicStruct {
// TODO: Something goes here
struct ColorRegularStruct {
// TODO: Add the fields that the test `regular_structs` expects.
// What types should the fields have? What are the minimum and maximum values for RGB colors?
}
struct ColorTupleStruct(/* TODO: Something goes here */);
struct ColorTupleStruct(/* TODO: Add the fields that the test `tuple_structs` expects */);
#[derive(Debug)]
struct UnitLikeStruct;
struct UnitStruct;
fn main() {
// You can optionally experiment here.
@ -18,8 +17,8 @@ mod tests {
use super::*;
#[test]
fn classic_c_structs() {
// TODO: Instantiate a classic c struct!
fn regular_structs() {
// TODO: Instantiate a regular struct.
// let green =
assert_eq!(green.red, 0);
@ -29,7 +28,7 @@ mod tests {
#[test]
fn tuple_structs() {
// TODO: Instantiate a tuple struct!
// TODO: Instantiate a tuple struct.
// let green =
assert_eq!(green.0, 0);
@ -39,10 +38,10 @@ mod tests {
#[test]
fn unit_structs() {
// TODO: Instantiate a unit-like struct!
// let unit_like_struct =
let message = format!("{:?}s are fun!", unit_like_struct);
// TODO: Instantiate a unit struct.
// let unit_struct =
let message = format!("{unit_struct:?}s are fun!");
assert_eq!(message, "UnitLikeStructs are fun!");
assert_eq!(message, "UnitStructs are fun!");
}
}

View file

@ -1,5 +1,3 @@
// Address all the TODOs to make the tests pass!
#[derive(Debug)]
struct Order {
name: String,
@ -34,8 +32,10 @@ mod tests {
#[test]
fn your_order() {
let order_template = create_order_template();
// TODO: Create your own order using the update syntax and template above!
// let your_order =
assert_eq!(your_order.name, "Hacker in Rust");
assert_eq!(your_order.year, order_template.year);
assert_eq!(your_order.made_by_phone, order_template.made_by_phone);

View file

@ -1,6 +1,5 @@
// Structs contain data, but can also have logic. In this exercise we have
// defined the Package struct and we want to test some logic attached to it.
// Make the code compile and the tests pass!
// defined the `Package` struct and we want to test some logic attached to it.
#[derive(Debug)]
struct Package {
@ -10,26 +9,28 @@ struct Package {
}
impl Package {
fn new(sender_country: String, recipient_country: String, weight_in_grams: u32) -> Package {
fn new(sender_country: String, recipient_country: String, weight_in_grams: u32) -> Self {
if weight_in_grams < 10 {
// This is not how you should handle errors in Rust,
// but we will learn about error handling later.
panic!("Can not ship a package with weight below 10 grams.")
} else {
Package {
// This isn't how you should handle errors in Rust, but we will
// learn about error handling later.
panic!("Can't ship a package with weight below 10 grams");
}
Self {
sender_country,
recipient_country,
weight_in_grams,
}
}
// TODO: Add the correct return type to the function signature.
fn is_international(&self) {
// TODO: Read the tests that use this method to find out when a package is concidered international.
}
fn is_international(&self) -> ??? {
// Something goes here...
}
fn get_fees(&self, cents_per_gram: u32) -> ??? {
// Something goes here...
// TODO: Add the correct return type to the function signature.
fn get_fees(&self, cents_per_gram: u32) {
// TODO: Calculate the package's fees.
}
}

View file

@ -1,6 +1,6 @@
#[derive(Debug)]
enum Message {
// TODO: define a few types of messages as used below
// TODO: Define a few types of messages as used below.
}
fn main() {

View file

@ -1,6 +1,6 @@
#[derive(Debug)]
enum Message {
// TODO: define the different variants used below
// TODO: Define the different variants used below.
}
impl Message {

View file

@ -1,7 +1,5 @@
// Address all the TODOs to make the tests pass!
enum Message {
// TODO: implement the message variant types based on their usage below
// TODO: Implement the message variant types based on their usage below.
}
struct Point {
@ -26,17 +24,17 @@ impl State {
}
fn echo(&mut self, s: String) {
self.message = s
self.message = s;
}
fn move_position(&mut self, p: Point) {
self.position = p;
fn move_position(&mut self, point: Point) {
self.position = point;
}
fn process(&mut self, message: Message) {
// TODO: create a match expression to process the different message variants
// TODO: Create a match expression to process the different message variants.
// Remember: When passing a tuple as a function argument, you'll need extra parentheses:
// fn function((t, u, p, l, e))
// e.g. `foo((t, u, p, l, e))`
}
}
@ -54,8 +52,9 @@ mod tests {
quit: false,
position: Point { x: 0, y: 0 },
color: (0, 0, 0),
message: "hello world".to_string(),
message: String::from("hello world"),
};
state.process(Message::ChangeColor(255, 0, 255));
state.process(Message::Echo(String::from("Hello world!")));
state.process(Message::Move(Point { x: 10, y: 15 }));
@ -64,7 +63,7 @@ mod tests {
assert_eq!(state.color, (255, 0, 255));
assert_eq!(state.position.x, 10);
assert_eq!(state.position.y, 15);
assert_eq!(state.quit, true);
assert!(state.quit);
assert_eq!(state.message, "Hello world!");
}
}

View file

@ -1,10 +1,9 @@
// Make me compile without changing the function signature!
fn main() {
let answer = current_favorite_color();
println!("My current favorite color is {}", answer);
}
// TODO: Fix the compiler error without changing the function signature.
fn current_favorite_color() -> String {
"blue"
}
fn main() {
let answer = current_favorite_color();
println!("My current favorite color is {answer}");
}

View file

@ -1,14 +1,14 @@
// Make me compile without changing the function signature!
// TODO: Fix the compiler error in the `main` function without changing this function.
fn is_a_color_word(attempt: &str) -> bool {
attempt == "green" || attempt == "blue" || attempt == "red"
}
fn main() {
let word = String::from("green"); // Try not changing this line :)
let word = String::from("green"); // Don't change this line.
if is_a_color_word(word) {
println!("That is a color word I know!");
} else {
println!("That is not a color word I know.");
}
}
fn is_a_color_word(attempt: &str) -> bool {
attempt == "green" || attempt == "blue" || attempt == "red"
}

View file

@ -1,16 +1,13 @@
fn trim_me(input: &str) -> String {
// TODO: Remove whitespace from both ends of a string!
???
fn trim_me(input: &str) -> &str {
// TODO: Remove whitespace from both ends of a string.
}
fn compose_me(input: &str) -> String {
// TODO: Add " world!" to the string! There are multiple ways to do this!
???
// TODO: Add " world!" to the string! There are multiple ways to do this.
}
fn replace_me(input: &str) -> String {
// TODO: Replace "cars" in the string with "balloons"!
???
// TODO: Replace "cars" in the string with "balloons".
}
fn main() {
@ -36,7 +33,13 @@ mod tests {
#[test]
fn replace_a_string() {
assert_eq!(replace_me("I think cars are cool"), "I think balloons are cool");
assert_eq!(replace_me("I love to look at cars"), "I love to look at balloons");
assert_eq!(
replace_me("I think cars are cool"),
"I think balloons are cool",
);
assert_eq!(
replace_me("I love to look at cars"),
"I love to look at balloons",
);
}
}

View file

@ -1,24 +1,36 @@
// Ok, here are a bunch of values - some are `String`s, some are `&str`s. Your
// task is to call one of these two functions on each value depending on what
// you think each value is. That is, add either `string_slice` or `string`
// before the parentheses on each line. If you're right, it will compile!
// Calls of this function should be replaced with calls of `string_slice` or `string`.
fn placeholder() {}
fn string_slice(arg: &str) {
println!("{}", arg);
println!("{arg}");
}
fn string(arg: String) {
println!("{}", arg);
println!("{arg}");
}
// TODO: Here are a bunch of values - some are `String`, some are `&str`.
// Your task is to replace `placeholder(…)` with either `string_slice(…)`
// or `string(…)` depending on what you think each value is.
fn main() {
???("blue");
???("red".to_string());
???(String::from("hi"));
???("rust is fun!".to_owned());
???("nice weather".into());
???(format!("Interpolation {}", "Station"));
???(&String::from("abc")[0..1]);
???(" hello there ".trim());
???("Happy Monday!".to_string().replace("Mon", "Tues"));
???("mY sHiFt KeY iS sTiCkY".to_lowercase());
placeholder("blue");
placeholder("red".to_string());
placeholder(String::from("hi"));
placeholder("rust is fun!".to_owned());
placeholder("nice weather".into());
placeholder(format!("Interpolation {}", "Station"));
// WARNING: This is byte indexing, not character indexing.
// Character indexing can be done using `s.chars().nth(INDEX)`.
placeholder(&String::from("abc")[0..1]);
placeholder(" hello there ".trim());
placeholder("Happy Monday!".replace("Mon", "Tues"));
placeholder("mY sHiFt KeY iS sTiCkY".to_lowercase());
}

View file

@ -1,3 +1,4 @@
// TODO: Fix the compiler error about calling a private function.
mod sausage_factory {
// Don't let anybody outside of this module see this!
fn get_secret_recipe() -> String {

View file

@ -1,20 +1,19 @@
// You can bring module paths into scopes and provide new names for them with
// the 'use' and 'as' keywords. Fix these 'use' statements to make the code
// compile.
// the `use` and `as` keywords.
mod delicious_snacks {
// TODO: Fix these use statements
use self::fruits::PEAR as ???
use self::veggies::CUCUMBER as ???
// TODO: Add the follwing two `use` statements after fixing them.
// use self::fruits::PEAR as ???;
// use self::veggies::CUCUMBER as ???;
mod fruits {
pub const PEAR: &'static str = "Pear";
pub const APPLE: &'static str = "Apple";
pub const PEAR: &str = "Pear";
pub const APPLE: &str = "Apple";
}
mod veggies {
pub const CUCUMBER: &'static str = "Cucumber";
pub const CARROT: &'static str = "Carrot";
pub const CUCUMBER: &str = "Cucumber";
pub const CARROT: &str = "Carrot";
}
}
@ -22,6 +21,6 @@ fn main() {
println!(
"favorite snacks: {} and {}",
delicious_snacks::fruit,
delicious_snacks::veggie
delicious_snacks::veggie,
);
}

View file

@ -1,10 +1,9 @@
// You can use the 'use' keyword to bring module paths from modules from
// anywhere and especially from the Rust standard library into your scope. Bring
// SystemTime and UNIX_EPOCH from the std::time module. Bonus style points if
// you can do it with one line!
// You can use the `use` keyword to bring module paths from modules from
// anywhere and especially from the standard library into your scope.
// TODO: Complete this use statement
use ???
// TODO: Bring `SystemTime` and `UNIX_EPOCH` from the `std::time` module into
// your scope. Bonus style points if you can do it with one line!
// use ???;
fn main() {
match SystemTime::now().duration_since(UNIX_EPOCH) {

View file

@ -402,15 +402,14 @@ hint = """
Rust has more than one type of struct. Three actually, all variants are used to
package related data together.
There are normal (or classic) structs. These are named collections of related
data stored in fields.
There are regular structs. These are named collections of related data stored in
fields.
Tuple structs are basically just named tuples.
Finally, Unit-like structs. These don't have any fields and are useful for
generics.
Finally, unit structs. These don't have any fields and are useful for generics.
In this exercise you need to complete and implement one of each kind.
In this exercise, you need to complete and implement one of each kind.
Read more about structs in The Book:
https://doc.rust-lang.org/book/ch05-01-defining-structs.html"""
@ -422,7 +421,7 @@ Creating instances of structs is easy, all you need to do is assign some values
to its fields.
There are however some shortcuts that can be taken when instantiating structs.
Have a look in The Book, to find out more:
Have a look in The Book to find out more:
https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax"""
[[exercises]]
@ -435,7 +434,7 @@ the places it goes through right?
For `get_fees`: This method takes an additional argument, is there a field in
the `Package` struct that this relates to?
Have a look in The Book, to find out more about method implementations:
Have a look in The Book to find out more about method implementations:
https://doc.rust-lang.org/book/ch05-03-method-syntax.html"""
# ENUMS
@ -452,18 +451,18 @@ dir = "08_enums"
test = false
hint = """
You can create enumerations that have different variants with different types
such as no data, anonymous structs, a single string, tuples, ...etc"""
such as no data, anonymous structs, a single string, tuples, etc."""
[[exercises]]
name = "enums3"
dir = "08_enums"
hint = """
As a first step, you can define enums to compile this code without errors.
As a first step, define enums to compile the code without errors.
And then create a match expression in `process()`.
Then, create a match expression in `process()`.
Note that you need to deconstruct some message variants in the match expression
to get value in the variant."""
to get the variant's values."""
# STRINGS
@ -487,7 +486,7 @@ dir = "09_strings"
test = false
hint = """
Yes, it would be really easy to fix this by just changing the value bound to
`word` to be a string slice instead of a `String`, wouldn't it?? There is a way
`word` to be a string slice instead of a `String`, wouldn't it? There is a way
to add one character to the `if` statement, though, that will coerce the
`String` into a string slice.
@ -500,7 +499,8 @@ https://doc.rust-lang.org/stable/book/ch15-02-deref.html#implicit-deref-coercion
name = "strings3"
dir = "09_strings"
hint = """
There's tons of useful standard library functions for strings. Let's try and use some of them:
There are many useful standard library functions for strings. Let's try and use
some of them:
https://doc.rust-lang.org/std/string/struct.String.html#method.trim
For the `compose_me` method: You can either use the `format!` macro, or convert
@ -510,7 +510,15 @@ the string slice into an owned string, which you can then freely extend."""
name = "strings4"
dir = "09_strings"
test = false
hint = "No hints this time ;)"
hint = """
Replace `placeholder` with either `string` or `string_slice` in the `main` function.
Example:
`placeholder("blue");`
should become
`string_slice("blue");`
because "blue" is `&str`, not `String`.
"""
# MODULES
@ -519,21 +527,21 @@ name = "modules1"
dir = "10_modules"
test = false
hint = """
Everything is private in Rust by default-- but there's a keyword we can use
to make something public! The compiler error should point to the thing that
needs to be public."""
Everything is private in Rust by default. But there's a keyword we can use
to make something public!"""
[[exercises]]
name = "modules2"
dir = "10_modules"
test = false
hint = """
The delicious_snacks module is trying to present an external interface that is
different than its internal structure (the `fruits` and `veggies` modules and
associated constants). Complete the `use` statements to fit the uses in main and
find the one keyword missing for both constants.
The `delicious_snacks` module is trying to present an external interface that
is different than its internal structure (the `fruits` and `veggies` modules
and associated constants). Complete the `use` statements to fit the uses in
`main` and find the one keyword missing for both constants.
Learn more at https://doc.rust-lang.org/book/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#re-exporting-names-with-pub-use"""
Learn more in The Book:
https://doc.rust-lang.org/book/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#re-exporting-names-with-pub-use"""
[[exercises]]
name = "modules3"
@ -542,7 +550,7 @@ test = false
hint = """
`UNIX_EPOCH` and `SystemTime` are declared in the `std::time` module. Add a
`use` statement for these two to bring them into scope. You can use nested
paths or the glob operator to bring these two in using only one line."""
paths to bring these two in using only one line."""
# HASHMAPS

View file

@ -1 +1,49 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
struct ColorRegularStruct {
red: u8,
green: u8,
blue: u8,
}
struct ColorTupleStruct(u8, u8, u8);
#[derive(Debug)]
struct UnitStruct;
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn regular_structs() {
let green = ColorRegularStruct {
red: 0,
green: 255,
blue: 0,
};
assert_eq!(green.red, 0);
assert_eq!(green.green, 255);
assert_eq!(green.blue, 0);
}
#[test]
fn tuple_structs() {
let green = ColorTupleStruct(0, 255, 0);
assert_eq!(green.0, 0);
assert_eq!(green.1, 255);
assert_eq!(green.2, 0);
}
#[test]
fn unit_structs() {
let unit_struct = UnitStruct;
let message = format!("{unit_struct:?}s are fun!");
assert_eq!(message, "UnitStructs are fun!");
}
}

View file

@ -1 +1,51 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
#[derive(Debug)]
struct Order {
name: String,
year: u32,
made_by_phone: bool,
made_by_mobile: bool,
made_by_email: bool,
item_number: u32,
count: u32,
}
fn create_order_template() -> Order {
Order {
name: String::from("Bob"),
year: 2019,
made_by_phone: false,
made_by_mobile: false,
made_by_email: true,
item_number: 123,
count: 0,
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn your_order() {
let order_template = create_order_template();
let your_order = Order {
name: String::from("Hacker in Rust"),
count: 1,
// Struct update syntax
..order_template
};
assert_eq!(your_order.name, "Hacker in Rust");
assert_eq!(your_order.year, order_template.year);
assert_eq!(your_order.made_by_phone, order_template.made_by_phone);
assert_eq!(your_order.made_by_mobile, order_template.made_by_mobile);
assert_eq!(your_order.made_by_email, order_template.made_by_email);
assert_eq!(your_order.item_number, order_template.item_number);
assert_eq!(your_order.count, 1);
}
}

View file

@ -1 +1,83 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
#[derive(Debug)]
struct Package {
sender_country: String,
recipient_country: String,
weight_in_grams: u32,
}
impl Package {
fn new(sender_country: String, recipient_country: String, weight_in_grams: u32) -> Self {
if weight_in_grams < 10 {
// This isn't how you should handle errors in Rust, but we will
// learn about error handling later.
panic!("Can't ship a package with weight below 10 grams");
}
Self {
sender_country,
recipient_country,
weight_in_grams,
}
}
fn is_international(&self) -> bool {
// ^^^^^^^ added
self.sender_country != self.recipient_country
}
fn get_fees(&self, cents_per_gram: u32) -> u32 {
// ^^^^^^ added
self.weight_in_grams * cents_per_gram
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic]
fn fail_creating_weightless_package() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Austria");
Package::new(sender_country, recipient_country, 5);
}
#[test]
fn create_international_package() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Russia");
let package = Package::new(sender_country, recipient_country, 1200);
assert!(package.is_international());
}
#[test]
fn create_local_package() {
let sender_country = String::from("Canada");
let recipient_country = sender_country.clone();
let package = Package::new(sender_country, recipient_country, 1200);
assert!(!package.is_international());
}
#[test]
fn calculate_transport_fees() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Spain");
let cents_per_gram = 3;
let package = Package::new(sender_country, recipient_country, 1500);
assert_eq!(package.get_fees(cents_per_gram), 4500);
assert_eq!(package.get_fees(cents_per_gram * 2), 9000);
}
}

View file

@ -1 +1,14 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
#[derive(Debug)]
enum Message {
Quit,
Echo,
Move,
ChangeColor,
}
fn main() {
println!("{:?}", Message::Quit);
println!("{:?}", Message::Echo);
println!("{:?}", Message::Move);
println!("{:?}", Message::ChangeColor);
}

View file

@ -1 +1,26 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
#[derive(Debug)]
enum Message {
Move { x: i64, y: i64 },
Echo(String),
ChangeColor(u8, u8, u8),
Quit,
}
impl Message {
fn call(&self) {
println!("{:?}", self);
}
}
fn main() {
let messages = [
Message::Move { x: 10, y: 30 },
Message::Echo(String::from("hello world")),
Message::ChangeColor(200, 255, 255),
Message::Quit,
];
for message in &messages {
message.call();
}
}

View file

@ -1 +1,75 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
enum Message {
ChangeColor(u8, u8, u8),
Echo(String),
Move(Point),
Quit,
}
struct Point {
x: u8,
y: u8,
}
struct State {
color: (u8, u8, u8),
position: Point,
quit: bool,
message: String,
}
impl State {
fn change_color(&mut self, color: (u8, u8, u8)) {
self.color = color;
}
fn quit(&mut self) {
self.quit = true;
}
fn echo(&mut self, s: String) {
self.message = s;
}
fn move_position(&mut self, point: Point) {
self.position = point;
}
fn process(&mut self, message: Message) {
match message {
Message::ChangeColor(r, g, b) => self.change_color((r, g, b)),
Message::Echo(s) => self.echo(s),
Message::Move(point) => self.move_position(point),
Message::Quit => self.quit(),
}
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_match_message_call() {
let mut state = State {
quit: false,
position: Point { x: 0, y: 0 },
color: (0, 0, 0),
message: String::from("hello world"),
};
state.process(Message::ChangeColor(255, 0, 255));
state.process(Message::Echo(String::from("Hello world!")));
state.process(Message::Move(Point { x: 10, y: 15 }));
state.process(Message::Quit);
assert_eq!(state.color, (255, 0, 255));
assert_eq!(state.position.x, 10);
assert_eq!(state.position.y, 15);
assert!(state.quit);
assert_eq!(state.message, "Hello world!");
}
}

View file

@ -1 +1,9 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
fn current_favorite_color() -> String {
// Equivalent to `String::from("blue")`
"blue".to_string()
}
fn main() {
let answer = current_favorite_color();
println!("My current favorite color is {answer}");
}

View file

@ -1 +1,15 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
fn is_a_color_word(attempt: &str) -> bool {
attempt == "green" || attempt == "blue" || attempt == "red"
}
fn main() {
let word = String::from("green");
if is_a_color_word(&word) {
// ^ added to have `&String` which is automatically
// coerced to `&str` by the compiler.
println!("That is a color word I know!");
} else {
println!("That is not a color word I know.");
}
}

View file

@ -1 +1,48 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
fn trim_me(input: &str) -> &str {
input.trim()
}
fn compose_me(input: &str) -> String {
// The macro `format!` has the same syntax as `println!`, but it returns a
// string instead of printing it to the terminal.
// Equivalent to `input.to_string() + " world!"`
format!("{input} world!")
}
fn replace_me(input: &str) -> String {
input.replace("cars", "balloons")
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn trim_a_string() {
assert_eq!(trim_me("Hello! "), "Hello!");
assert_eq!(trim_me(" What's up!"), "What's up!");
assert_eq!(trim_me(" Hola! "), "Hola!");
}
#[test]
fn compose_a_string() {
assert_eq!(compose_me("Hello"), "Hello world!");
assert_eq!(compose_me("Goodbye"), "Goodbye world!");
}
#[test]
fn replace_a_string() {
assert_eq!(
replace_me("I think cars are cool"),
"I think balloons are cool",
);
assert_eq!(
replace_me("I love to look at cars"),
"I love to look at balloons",
);
}
}

View file

@ -1 +1,38 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
fn string_slice(arg: &str) {
println!("{arg}");
}
fn string(arg: String) {
println!("{arg}");
}
fn main() {
string_slice("blue");
string("red".to_string());
string(String::from("hi"));
string("rust is fun!".to_owned());
// Here, both answers work.
// `.into()` converts a type into an expected type.
// If it is called where `String` is expected, it will convert `&str` to `String`.
// But if is called where `&str` is expected, then `&str` is kept `&str` since no
// conversion is needed.
string("nice weather".into());
string_slice("nice weather".into());
// ^^^^^^^ the compiler recommends removing the `.into()`
// call because it is a useless conversion.
string(format!("Interpolation {}", "Station"));
// WARNING: This is byte indexing, not character indexing.
// Character indexing can be done using `s.chars().nth(INDEX)`.
string_slice(&String::from("abc")[0..1]);
string_slice(" hello there ".trim());
string("Happy Monday!".replace("Mon", "Tues"));
string("mY sHiFt KeY iS sTiCkY".to_lowercase());
}

View file

@ -1 +1,15 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
mod sausage_factory {
fn get_secret_recipe() -> String {
String::from("Ginger")
}
// Added `pub` before `fn` to make the function accessible outside the module.
pub fn make_sausage() {
get_secret_recipe();
println!("sausage!");
}
}
fn main() {
sausage_factory::make_sausage();
}

View file

@ -1 +1,23 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
mod delicious_snacks {
// Added `pub` and used the expected alias after `as`.
pub use self::fruits::PEAR as fruit;
pub use self::veggies::CUCUMBER as veggie;
mod fruits {
pub const PEAR: &str = "Pear";
pub const APPLE: &str = "Apple";
}
mod veggies {
pub const CUCUMBER: &str = "Cucumber";
pub const CARROT: &str = "Carrot";
}
}
fn main() {
println!(
"favorite snacks: {} and {}",
delicious_snacks::fruit,
delicious_snacks::veggie,
);
}

View file

@ -1 +1,8 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
use std::time::{SystemTime, UNIX_EPOCH};
fn main() {
match SystemTime::now().duration_since(UNIX_EPOCH) {
Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
Err(_) => panic!("SystemTime before UNIX EPOCH!"),
}
}