Skip to content

Commit ed689eb

Browse files
committed
✨ (concept) Add new concept exercise cars-assemble
This is inspired by the same in csharp track. Provides a gentle introduction to variable assignment, if-statements and numbers.
1 parent 796f2ca commit ed689eb

File tree

11 files changed

+489
-0
lines changed

11 files changed

+489
-0
lines changed

config.json

+15
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@
3535
},
3636
"exercises": {
3737
"concept": [
38+
{
39+
"slug": "cars-assemble",
40+
"uuid": "1d0e6e2c-c319-48bc-8626-7b3c98473f42",
41+
"name": "Cars Assemble",
42+
"difficulty": 1,
43+
"concepts": [
44+
"if-statements",
45+
"assignment",
46+
"numbers"
47+
],
48+
"prerequisites": [
49+
"booleans"
50+
],
51+
"status": "wip"
52+
},
3853
{
3954
"slug": "lucians-luscious-lasagna",
4055
"uuid": "29a2d3bd-eec8-454d-9dba-4b2d7d071925",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Hints
2+
3+
## General
4+
5+
- [Rust book][rust-book-data-types] on Integers and Floating point numbers.
6+
7+
## 1. Calculate the success rate
8+
9+
- Determining the success rate can be done through a [conditional statement][if-statement].
10+
11+
## 2. Calculate the production rate per second
12+
13+
- Use `.into()` to convert `i32` to `f64`.
14+
- Use the `success_rate()` method you wrote earlier to determine the success rate.
15+
- Rust does not allow for multiplication to be applied to two different number
16+
types (such as an `i32` and a `f64`). Both must be of the same type.
17+
- Numbers can be compared using the built-in comparision and equality operators.
18+
Checkout [full list of operators][operators-list] supported by Rust.
19+
## 3. Calculate the number of working items produced per second
20+
21+
- Use `.into()` to convert `i32` to `f64`.
22+
- Rounding a float to a certain precision (here 1 decimal places) can be done using:
23+
```rust
24+
let my_float = 3.166;
25+
let rounded = (my_float * 10.0).round() / 10.0;
26+
// => 3.2
27+
```
28+
Read more on this [StackOverflow answer][stackoverflow-rounding].
29+
30+
[if-statement]: https://doc.rust-lang.org/rust-by-example/flow_control/if_else.html#ifelse
31+
[stackoverflow-rounding]: https://stackoverflow.com/a/28656825
32+
[operators-list]:https://doc.rust-lang.org/book/appendix-02-operators.html#operators
33+
[rust-book-data-types]:
34+
https://doc.rust-lang.org/book/ch03-02-data-types.html#integer-types
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Instructions
2+
3+
In this exercise you'll be writing code to analyze the production of an assembly line in a car factory.
4+
The assembly line's speed can range from `0` (off) to `10` (maximum).
5+
6+
At its lowest speed (`1`), `221` cars are produced each hour. The production increases linearly with the speed.
7+
So with the speed set to `4`, it should produce `4 * 221 = 884` cars per hour.
8+
However, higher speeds increase the likelihood that faulty cars are produced, which then have to be discarded.
9+
10+
You have three tasks.
11+
12+
## 1. Calculate the success rate
13+
14+
Implement the `success_rate()` function to calculate the ratio of an item being
15+
created without error for a given speed.
16+
The following table shows how speed influences the success rate:
17+
18+
- `0`: 0% success rate.
19+
- `1` to `4`: 100% success rate.
20+
- `5` to `8`: 90% success rate.
21+
- `9`: 80% success rate.
22+
- `10`: 77% success rate.
23+
24+
```rust
25+
success_rate(10)
26+
// => 0.77
27+
```
28+
29+
Note that the value returned is a `f64`.
30+
31+
## 2. Calculate the production rate per hour
32+
33+
Implement the `production_rate_per_hour()` function to calculate the assembly line's production rate per hour, taking into account its success rate:
34+
35+
```rust
36+
production_rate_per_hour(6)
37+
// => 1193.4
38+
```
39+
40+
Note that the value returned is a `f64`.
41+
42+
## 3. Calculate the number of working items produced per minute
43+
44+
Implement the `working_items_per_minute()` function to calculate how many working cars are produced per minute:
45+
46+
```rust
47+
working_items_per_minute(6)
48+
// => 19
49+
```
50+
51+
Note that the value returned is an `i32`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
# Introduction
2+
3+
## Numbers
4+
5+
There are two different types of numbers in Rust:
6+
7+
- Integers: numbers with no digits behind the decimal separator (whole numbers). Examples are `-6`, `0`, `1`, `25`, `976` and `500000`.
8+
- Floating-point numbers: numbers with zero or more digits behind the decimal separator. Examples are `-2.4`, `0.1`, `3.14`, `16.984025` and `1024.0`.
9+
10+
The two default numeric types in Rust are `i32` and `f64`. An `i32` is a 32-bit integer and a `f64` is a 64-bit floating-point number.
11+
12+
Arithmetic is done using the standard arithmetic operators. Numbers can be
13+
compared using the standard numeric comparison operators and the equality (`==`)
14+
and inequality (`!=`) operators.
15+
16+
## Assignment
17+
18+
The following syntax can be used to define a variable and assign a value to it.
19+
20+
```rust
21+
let my_variable = 5;
22+
```
23+
24+
The above defines a variable with value 5 which automatically makes its type as
25+
`i32`. The value of this variable cannot be changed.
26+
In Rust, `snake_case` is used to define the name of a variable.
27+
28+
To create a variable that can be assigned a different value one can use `mut`
29+
keyword:
30+
31+
```rust
32+
let mut my_variable = 5;
33+
my_variable = 10;
34+
```
35+
36+
In Rust, integers and floats are different types hence you cannot assign a
37+
float to an integer variable and vice-versa. Not even if the values seem equal:
38+
39+
```rust
40+
let my_int = 5;
41+
let my_float = my_int; // => panic
42+
43+
let my_float2 = 5.0;
44+
let my_int2 = my_float2; // => panic
45+
```
46+
47+
### Constants
48+
Like immutable variables, *constants* are values that are bound to a name and
49+
are not allowed to change, but there are a few differences between constants
50+
and variables.
51+
52+
- First, you aren’t allowed to use `mut` with constants.
53+
- Constants aren’t just immutable by default—they’re always immutable.
54+
- You declare constants using the `const` keyword instead of the `let` keyword, and the type of the value *must* be annotated.
55+
- Constants can be declared in any scope, including the global scope, which makes them useful for values that many parts of code need to know about.
56+
- The last difference is that constants may be set only to a constant expression, not the result of a value that could only be computed at runtime.
57+
58+
Here’s an example of a constant declaration:
59+
60+
```rust
61+
const SECONDS_IN_A_MINUTE: u32 = 60;
62+
```
63+
64+
In Rust, constants are defined using `CAPITAL_SNAKE_CASE`.
65+
66+
### Rust requires explicit conversion between types
67+
68+
Using the `.into()` method:
69+
70+
```rust
71+
let my_int = 50;
72+
let my_float: f64 = my_int.into(); // works as expected
73+
```
74+
75+
Note that this requires specifying the variable type explicitly.
76+
77+
As an `i32` has less precision than a `f64`, converting from an `i32` to a `f64` is safe and lossless. However, converting from a `f64` to an `i32` could mean losing data.
78+
79+
## Numeric Operators
80+
81+
Rust supports various operators on integers and floats.
82+
83+
Take a look at the following table that illustrates how each operator behaves with integers and floats.
84+
85+
| Symbol | Integer | Floating Point |
86+
|--------|-------------------------|----------------|
87+
| `+` | Addition | Addition |
88+
| `-` | Subtraction | Subtraction |
89+
| `*` | Multiplication | Multiplication |
90+
| `/` | Division* | Division |
91+
| `%` | Remainder** | Remainder |
92+
93+
\* Integer division rounds towards zero.
94+
95+
\*\* Rust uses a remainder defined with [truncating division].
96+
Given `remainder = dividend % divisor`, the remainder will have the same sign as the dividend.
97+
98+
Note that both operands of an operator must be of same type.
99+
e.g. For `+` operator, an integer cannot be added to a float and vice-versa.
100+
101+
Following example demonstrates usage for these operators.
102+
103+
```rust
104+
let result_1 = 3 + 6;
105+
// => 9
106+
let result_2 = 5.5 - 1.25;
107+
// => 4.25
108+
let result_3 = -5 * 14;
109+
// => -70
110+
let result_4 = 14 / 3;
111+
// => 4
112+
let result_5 = 100 % 7;
113+
// => 2
114+
```
115+
116+
## If Statements
117+
118+
In this exercise you must conditionally execute logic. The most common way to do this in Rust is by using an `if/else` statement:
119+
120+
`if` expressions start with the keyword `if`, followed by a condition. In this
121+
case, the condition checks whether or not the variable `number` has a value less
122+
than `5`.
123+
124+
125+
```rust
126+
let number = 3;
127+
128+
if number < 5 {
129+
println!("condition was true");
130+
} else {
131+
println!("condition was false");
132+
}
133+
```
134+
135+
Optionally, we can also include an `else` expression, which we chose to do here,
136+
to give the program an alternative block of code to execute should the condition
137+
evaluate to `false`.
138+
139+
If you don’t provide an `else` expression and the condition is `false`, the program will just skip the `if` block and move on to the next bit of code.
140+
141+
The condition of an `if` statement must be of type `bool`. Rust has no concept of
142+
_truthy_ values.
143+
144+
```rust
145+
let number = 3;
146+
147+
if number {
148+
println!("number was three");
149+
}
150+
```
151+
152+
The `if` condition evaluates to a value of `3` this time, and Rust throws an
153+
error:
154+
155+
```txt
156+
|
157+
4 | if number {
158+
| ^^^^^^ expected `bool`, found integer
159+
160+
For more information about this error, try `rustc --explain E0308`.
161+
error: could not compile `branches` due to previous error
162+
```
163+
164+
You can use multiple conditions by combining `if` and `else` in an `else if` expression. For example:
165+
166+
```rust
167+
let x = 6;
168+
169+
if x == 5 {
170+
// Execute logic if x equals 5
171+
} else if x > 7 {
172+
// Execute logic if x greater than 7
173+
} else {
174+
// Execute logic in all other cases
175+
}
176+
```
177+
178+
179+
[truncating division]:
180+
https://en.wikipedia.org/wiki/Modulo_operation#Variants_of_the_definition
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Generated by Cargo
2+
# will have compiled files and executables
3+
/target/
4+
**/*.rs.bk
5+
6+
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7+
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8+
Cargo.lock
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"blurb": "Learn about numbers by analyzing the production of an assembly line.",
3+
"authors": [
4+
"devkabiir"
5+
],
6+
"contributors": [],
7+
"files": {
8+
"solution": [
9+
"src/lib.rs",
10+
"Cargo.toml"
11+
],
12+
"test": [
13+
"tests/cars-assemble.rs"
14+
],
15+
"exemplar": [
16+
".meta/exemplar.rs"
17+
]
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Design
2+
3+
## Learning objectives
4+
5+
- Know of the existence of the two default number types, `i32` and `f64`.
6+
- Understand that an `i32` represents whole numbers, and a `f64` represents floating-point numbers.
7+
- Know of basic operators such as multiplication, comparison and equality.
8+
- Know how to convert from one numeric type to another.
9+
- Know how to conditionally execute code using an `if` statement.
10+
11+
## Out of scope
12+
13+
- Any other numeric types besides `i32` and `f64` (so no `float`, `byte`, etc.).
14+
- Parsing a `string` to an `i32` or `f64`.
15+
- Converting an `i32` or `f64` to a `string`.
16+
17+
## Concepts
18+
19+
- `integers`: know about `i32` and `f64` types
20+
- `if-statements`: know how to conditionally execute code using an `if` statement.
21+
- `math-operators`: know the math operators; know about precedence; know the role of parentheses
22+
- `assignment`: know the syntax and behavior of assignment in OO languages
23+
24+
## Prerequisites
25+
26+
- `booleans`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
const PRODUCTION_RATE_PER_HOUR_FOR_DEFAULT_SPEED: i32 = 221;
2+
3+
pub fn production_rate_per_hour(speed: i32) -> f64 {
4+
let result = production_rate_per_hour_for_speed(speed) * success_rate(speed);
5+
6+
round_to_1_decimal(result)
7+
}
8+
9+
fn round_to_1_decimal(input: f64) -> f64 {
10+
(input * 10.0).round() / 10.0
11+
}
12+
13+
fn production_rate_per_hour_for_speed(speed: i32) -> f64 {
14+
(PRODUCTION_RATE_PER_HOUR_FOR_DEFAULT_SPEED * speed).into()
15+
}
16+
17+
pub fn working_items_per_minute(speed: i32) -> i32 {
18+
(production_rate_per_hour(speed) / 60.0).into()
19+
}
20+
21+
pub fn success_rate(speed: i32) -> f64 {
22+
if speed == 10 {
23+
0.77
24+
} else if speed == 9 {
25+
0.8
26+
} else if speed >= 5 {
27+
0.9
28+
} else if speed <= 0 {
29+
0.0
30+
} else {
31+
1.0
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[package]
2+
edition = "2021"
3+
name = "cars_assemble"
4+
version = "1.0.0"
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
pub fn production_rate_per_hour(_speed: i32) -> f32 {
2+
unimplemented!("Implement production_rate_per_hour")
3+
}
4+
5+
pub fn working_items_per_minute(_speed: i32) -> i32 {
6+
unimplemented!("Implement working_items_per_minute")
7+
}
8+
9+
pub fn success_rate(_speed: i32) -> f32 {
10+
unimplemented!("Implement success_rate")
11+
}

0 commit comments

Comments
 (0)