mirror of
https://github.com/rust-lang/rustlings.git
synced 2024-12-27 00:00:03 +03:00
Compare commits
8 commits
0f4cb94cfe
...
c793416495
Author | SHA1 | Date | |
---|---|---|---|
c793416495 | |||
01343f187b | |||
69021e1497 | |||
08c408aae0 | |||
bf698659b0 | |||
2d5d70693a | |||
a4091ade5c | |||
a7a881809f |
|
@ -5,5 +5,5 @@ compiler. In this section, we'll go through the most important ones.
|
|||
|
||||
## Further information
|
||||
|
||||
- [Data Types](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html)
|
||||
- [The Slice Type](https://doc.rust-lang.org/stable/book/ch04-03-slices.html)
|
||||
- [Data Types](https://doc.rust-lang.org/book/ch03-02-data-types.html)
|
||||
- [The Slice Type](https://doc.rust-lang.org/book/ch04-03-slices.html)
|
||||
|
|
|
@ -12,6 +12,6 @@ the other useful data structure, hash maps, later.
|
|||
|
||||
## Further information
|
||||
|
||||
- [Storing Lists of Values with Vectors](https://doc.rust-lang.org/stable/book/ch08-01-vectors.html)
|
||||
- [Storing Lists of Values with Vectors](https://doc.rust-lang.org/book/ch08-01-vectors.html)
|
||||
- [`iter_mut`](https://doc.rust-lang.org/std/primitive.slice.html#method.iter_mut)
|
||||
- [`map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map)
|
||||
|
|
|
@ -14,7 +14,7 @@ Option types are very common in Rust code, as they have a number of uses:
|
|||
|
||||
## Further Information
|
||||
|
||||
- [Option Enum Format](https://doc.rust-lang.org/stable/book/ch10-01-syntax.html#in-enum-definitions)
|
||||
- [Option Enum Format](https://doc.rust-lang.org/book/ch10-01-syntax.html#in-enum-definitions)
|
||||
- [Option Module Documentation](https://doc.rust-lang.org/std/option/)
|
||||
- [Option Enum Documentation](https://doc.rust-lang.org/std/option/enum.Option.html)
|
||||
- [if let](https://doc.rust-lang.org/rust-by-example/flow_control/if_let.html)
|
||||
|
|
|
@ -19,6 +19,7 @@ fn main() {
|
|||
let mut tokens = 100;
|
||||
let pretend_user_input = "8";
|
||||
|
||||
// Don't change this line.
|
||||
let cost = total_cost(pretend_user_input)?;
|
||||
|
||||
if cost > tokens {
|
||||
|
|
|
@ -7,5 +7,5 @@ The simplest and most common use of generics is for type parameters.
|
|||
|
||||
## Further information
|
||||
|
||||
- [Generic Data Types](https://doc.rust-lang.org/stable/book/ch10-01-syntax.html)
|
||||
- [Generic Data Types](https://doc.rust-lang.org/book/ch10-01-syntax.html)
|
||||
- [Bounds](https://doc.rust-lang.org/rust-by-example/generics/bounds.html)
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum DivisionError {
|
||||
// Example: 42 / 0
|
||||
DivideByZero,
|
||||
// Only case for `i64`: `i64::MIN / -1` because the result is `i64::MAX + 1`
|
||||
IntegerOverflow,
|
||||
// Example: 5 / 2 = 2.5
|
||||
NotDivisible,
|
||||
}
|
||||
|
||||
// TODO: Calculate `a` divided by `b` if `a` is evenly divisible by `b`.
|
||||
// Otherwise, return a suitable error.
|
||||
fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {
|
||||
fn divide(a: i64, b: i64) -> Result<i64, DivisionError> {
|
||||
todo!();
|
||||
}
|
||||
|
||||
|
@ -42,6 +46,11 @@ mod tests {
|
|||
assert_eq!(divide(81, 0), Err(DivisionError::DivideByZero));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_integer_overflow() {
|
||||
assert_eq!(divide(i64::MIN, -1), Err(DivisionError::IntegerOverflow));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_divisible() {
|
||||
assert_eq!(divide(81, 6), Err(DivisionError::NotDivisible));
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
fn factorial(num: u64) -> u64 {
|
||||
// TODO: Complete this function to return the factorial of `num`.
|
||||
// TODO: Complete this function to return the factorial of `num` which is
|
||||
// defined as `1 * 2 * 3 * … * num`.
|
||||
// https://en.wikipedia.org/wiki/Factorial
|
||||
//
|
||||
// Do not use:
|
||||
// - early returns (using the `return` keyword explicitly)
|
||||
// Try not to use:
|
||||
|
|
|
@ -309,7 +309,7 @@ In Rust, there are two ways to define a Vector.
|
|||
inside the square brackets. This way is simpler when you exactly know
|
||||
the initial values.
|
||||
|
||||
Check this chapter: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html
|
||||
Check this chapter: https://doc.rust-lang.org/book/ch08-01-vectors.html
|
||||
of the Rust book to learn more."""
|
||||
|
||||
[[exercises]]
|
||||
|
@ -378,7 +378,7 @@ dir = "06_move_semantics"
|
|||
test = false
|
||||
hint = """
|
||||
To find the answer, you can consult the book section "References and Borrowing":
|
||||
https://doc.rust-lang.org/stable/book/ch04-02-references-and-borrowing.html
|
||||
https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html
|
||||
|
||||
The first problem is that `get_char` is taking ownership of the string. So
|
||||
`data` is moved and can't be used for `string_uppercase`. `data` is moved to
|
||||
|
@ -416,7 +416,7 @@ 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:
|
||||
https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax"""
|
||||
https://doc.rust-lang.org/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax"""
|
||||
|
||||
[[exercises]]
|
||||
name = "structs3"
|
||||
|
@ -487,7 +487,7 @@ to add one character to the `if` statement, though, that will coerce the
|
|||
Side note: If you're interested in learning about how this kind of reference
|
||||
conversion works, you can jump ahead in the book and read this part in the
|
||||
smart pointers chapter:
|
||||
https://doc.rust-lang.org/stable/book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods"""
|
||||
https://doc.rust-lang.org/book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods"""
|
||||
|
||||
[[exercises]]
|
||||
name = "strings3"
|
||||
|
@ -561,7 +561,7 @@ hint = """
|
|||
Use the `entry()` and `or_insert()` methods of `HashMap` to achieve this.
|
||||
|
||||
Learn more in The Book:
|
||||
https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value"""
|
||||
https://doc.rust-lang.org/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value"""
|
||||
|
||||
[[exercises]]
|
||||
name = "hashmaps3"
|
||||
|
@ -572,7 +572,7 @@ Hint 1: Use the `entry()` and `or_insert()` (or `or_insert_with()`) methods of
|
|||
exist in the table yet.
|
||||
|
||||
Learn more in The Book:
|
||||
https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value
|
||||
https://doc.rust-lang.org/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value
|
||||
|
||||
Hint 2: If there is already an entry for a given key, the value returned by
|
||||
`entry()` can be updated based on the existing value.
|
||||
|
@ -585,7 +585,7 @@ https://doc.rust-lang.org/book/ch08-03-hash-maps.html#updating-a-value-based-on-
|
|||
[[exercises]]
|
||||
name = "quiz2"
|
||||
dir = "quizzes"
|
||||
hint = "No hints this time ;)"
|
||||
hint = "The `+` operator can concatenate a `String` with a `&str`."
|
||||
|
||||
# OPTIONS
|
||||
|
||||
|
@ -739,7 +739,7 @@ name = "generics2"
|
|||
dir = "14_generics"
|
||||
hint = """
|
||||
Related section in The Book:
|
||||
https://doc.rust-lang.org/stable/book/ch10-01-syntax.html#in-method-definitions"""
|
||||
https://doc.rust-lang.org/book/ch10-01-syntax.html#in-method-definitions"""
|
||||
|
||||
# TRAITS
|
||||
|
||||
|
@ -748,7 +748,9 @@ name = "traits1"
|
|||
dir = "15_traits"
|
||||
hint = """
|
||||
More about traits in The Book:
|
||||
https://doc.rust-lang.org/book/ch10-02-traits.html"""
|
||||
https://doc.rust-lang.org/book/ch10-02-traits.html
|
||||
|
||||
The `+` operator can concatenate a `String` with a `&str`."""
|
||||
|
||||
[[exercises]]
|
||||
name = "traits2"
|
||||
|
@ -869,7 +871,7 @@ We expect the method `Rectangle::new` to panic for negative values.
|
|||
To handle that, you need to add a special attribute to the test function.
|
||||
|
||||
You can refer to the docs:
|
||||
https://doc.rust-lang.org/stable/book/ch11-01-writing-tests.html#checking-for-panics-with-should_panic"""
|
||||
https://doc.rust-lang.org/book/ch11-01-writing-tests.html#checking-for-panics-with-should_panic"""
|
||||
|
||||
# STANDARD LIBRARY TYPES
|
||||
|
||||
|
@ -1005,7 +1007,7 @@ thread-local copy of the numbers.
|
|||
This is a simple exercise if you understand the underlying concepts, but if this
|
||||
is too much of a struggle, consider reading through all of Chapter 16 in The
|
||||
Book:
|
||||
https://doc.rust-lang.org/stable/book/ch16-00-concurrency.html"""
|
||||
https://doc.rust-lang.org/book/ch16-00-concurrency.html"""
|
||||
|
||||
[[exercises]]
|
||||
name = "cow1"
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum DivisionError {
|
||||
// Example: 42 / 0
|
||||
DivideByZero,
|
||||
// Only case for `i64`: `i64::MIN / -1` because the result is `i64::MAX + 1`
|
||||
IntegerOverflow,
|
||||
// Example: 5 / 2 = 2.5
|
||||
NotDivisible,
|
||||
}
|
||||
|
||||
|
@ -9,6 +13,10 @@ fn divide(a: i64, b: i64) -> Result<i64, DivisionError> {
|
|||
return Err(DivisionError::DivideByZero);
|
||||
}
|
||||
|
||||
if a == i64::MIN && b == -1 {
|
||||
return Err(DivisionError::IntegerOverflow);
|
||||
}
|
||||
|
||||
if a % b != 0 {
|
||||
return Err(DivisionError::NotDivisible);
|
||||
}
|
||||
|
@ -51,6 +59,11 @@ mod tests {
|
|||
assert_eq!(divide(81, 0), Err(DivisionError::DivideByZero));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_integer_overflow() {
|
||||
assert_eq!(divide(i64::MIN, -1), Err(DivisionError::IntegerOverflow));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_divisible() {
|
||||
assert_eq!(divide(81, 6), Err(DivisionError::NotDivisible));
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// - Append "bar" to the string a specified amount of times
|
||||
//
|
||||
// The exact form of this will be:
|
||||
// - The input is going to be a vector of a 2-length tuple,
|
||||
// - The input is going to be a vector of 2-length tuples,
|
||||
// the first element is the string, the second one is the command.
|
||||
// - The output element is going to be a vector of strings.
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use anyhow::{bail, Context, Result};
|
|||
use app_state::StateFileStatus;
|
||||
use clap::{Parser, Subcommand};
|
||||
use std::{
|
||||
io::{self, BufRead, StdoutLock, Write},
|
||||
io::{self, BufRead, IsTerminal, StdoutLock, Write},
|
||||
path::Path,
|
||||
process::exit,
|
||||
};
|
||||
|
@ -148,6 +148,10 @@ fn main() -> Result<()> {
|
|||
|
||||
match args.command {
|
||||
None => {
|
||||
if !io::stdout().is_terminal() {
|
||||
bail!("Unsupported or missing terminal/TTY");
|
||||
}
|
||||
|
||||
let notify_exercise_names = if args.manual_run {
|
||||
None
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue