mirror of
https://github.com/ArthurDanjou/exercism-rust.git
synced 2026-01-14 12:14:35 +01:00
Initial commit
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Project exclude paths
|
||||||
|
/low-power-embedded-game/target/
|
||||||
|
/magazine-cutout/target/
|
||||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/rust.iml" filepath="$PROJECT_DIR$/.idea/rust.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
85
.idea/rust.iml
generated
Normal file
85
.idea/rust.iml
generated
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="CPP_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/clock/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/clock/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/low-power-embedded-game/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/low-power-embedded-game/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/poker/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/poker/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/resistor-color/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/resistor-color/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/short-fibonacci/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/short-fibonacci/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/sublist/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/sublist/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/anagram/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/anagram/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/gigasecond/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/gigasecond/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/reverse-string/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/reverse-string/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/space-age/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/space-age/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/armstrong-numbers/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/armstrong-numbers/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/magazine-cutout/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/magazine-cutout/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/minesweeper/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/minesweeper/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/beer-song/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/beer-song/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/high-scores/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/high-scores/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/all-your-base/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/all-your-base/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/bob/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/bob/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/grade-school/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/grade-school/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/leap/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/leap/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/paasio/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/paasio/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/parallel-letter-frequency/benches" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/parallel-letter-frequency/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/parallel-letter-frequency/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/proverb/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/proverb/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/robot-simulator/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/robot-simulator/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/scrabble-score/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/scrabble-score/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/tournament/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/tournament/tests" isTestSource="true" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/sublist/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/poker/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/clock/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/resistor-color/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/short-fibonacci/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/low-power-embedded-game/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/reverse-string/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/gigasecond/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/anagram/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/space-age/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/minesweeper/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/magazine-cutout/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/armstrong-numbers/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/beer-song/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/high-scores/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/paasio/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/proverb/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/robot-simulator/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/bob/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/leap/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/grade-school/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/tournament/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/scrabble-score/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/all-your-base/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/parallel-letter-frequency/target" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
36
all-your-base/.exercism/config.json
Normal file
36
all-your-base/.exercism/config.json
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"blurb": "Convert a number, represented as a sequence of digits in one base, to any other base.",
|
||||||
|
"authors": [
|
||||||
|
"jonasbb"
|
||||||
|
],
|
||||||
|
"contributors": [
|
||||||
|
"CGMossa",
|
||||||
|
"coriolinus",
|
||||||
|
"cwhakes",
|
||||||
|
"efx",
|
||||||
|
"ErikSchierboom",
|
||||||
|
"IanWhitney",
|
||||||
|
"lutostag",
|
||||||
|
"mkantor",
|
||||||
|
"navossoc",
|
||||||
|
"nfiles",
|
||||||
|
"pedantic79",
|
||||||
|
"petertseng",
|
||||||
|
"rofrol",
|
||||||
|
"stringparser",
|
||||||
|
"xakon",
|
||||||
|
"ZapAnton"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"src/lib.rs",
|
||||||
|
"Cargo.toml"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/all-your-base.rs"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.rs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
1
all-your-base/.exercism/metadata.json
Normal file
1
all-your-base/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"track":"rust","exercise":"all-your-base","id":"22568dbd27034998a766c1e5833e585d","url":"https://exercism.org/tracks/rust/exercises/all-your-base","handle":"ArthurDanjou","is_requester":true,"auto_approve":false}
|
||||||
8
all-your-base/.gitignore
vendored
Normal file
8
all-your-base/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
/target/
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
|
||||||
|
Cargo.lock
|
||||||
4
all-your-base/Cargo.toml
Normal file
4
all-your-base/Cargo.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[package]
|
||||||
|
edition = "2021"
|
||||||
|
name = "allyourbase"
|
||||||
|
version = "1.0.0"
|
||||||
85
all-your-base/HELP.md
Normal file
85
all-your-base/HELP.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test
|
||||||
|
```
|
||||||
|
|
||||||
|
All but the first test have been ignored. After you get the first test to
|
||||||
|
pass, open the tests source file which is located in the `tests` directory
|
||||||
|
and remove the `#[ignore]` flag from the next test and get the tests to pass
|
||||||
|
again. Each separate test is a function with `#[test]` flag above it.
|
||||||
|
Continue, until you pass every test.
|
||||||
|
|
||||||
|
If you wish to run _only ignored_ tests without editing the tests source file, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are using Rust 1.51 or later, you can run _all_ tests with
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --include-ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a specific test, for example `some_test`, you can use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test
|
||||||
|
```
|
||||||
|
|
||||||
|
If the specific test is ignored, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about Rust tests refer to the online [test documentation][rust-tests].
|
||||||
|
|
||||||
|
[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit src/lib.rs Cargo.toml` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Rust track's documentation](https://exercism.org/docs/tracks/rust)
|
||||||
|
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
## Rust Installation
|
||||||
|
|
||||||
|
Refer to the [exercism help page][help-page] for Rust installation and learning
|
||||||
|
resources.
|
||||||
|
|
||||||
|
## Submitting the solution
|
||||||
|
|
||||||
|
Generally you should submit all files in which you implemented your solution (`src/lib.rs` in most cases). If you are using any external crates, please consider submitting the `Cargo.toml` file. This will make the review process faster and clearer.
|
||||||
|
|
||||||
|
## Feedback, Issues, Pull Requests
|
||||||
|
|
||||||
|
The GitHub [track repository][github] is the home for all of the Rust exercises. If you have feedback about an exercise, or want to help implement new exercises, head over there and create an issue. Members of the rust track team are happy to help!
|
||||||
|
|
||||||
|
If you want to know more about Exercism, take a look at the [contribution guide].
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
||||||
|
[help-page]: https://exercism.org/tracks/rust/learning
|
||||||
|
[github]: https://github.com/exercism/rust
|
||||||
|
[contribution guide]: https://exercism.org/docs/community/contributors
|
||||||
62
all-your-base/README.md
Normal file
62
all-your-base/README.md
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# All Your Base
|
||||||
|
|
||||||
|
Welcome to All Your Base on Exercism's Rust Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Convert a number, represented as a sequence of digits in one base, to any other base.
|
||||||
|
|
||||||
|
Implement general base conversion. Given a number in base **a**,
|
||||||
|
represented as a sequence of digits, convert it to base **b**.
|
||||||
|
|
||||||
|
## Note
|
||||||
|
|
||||||
|
- Try to implement the conversion yourself.
|
||||||
|
Do not use something else to perform the conversion for you.
|
||||||
|
|
||||||
|
## About [Positional Notation](https://en.wikipedia.org/wiki/Positional_notation)
|
||||||
|
|
||||||
|
In positional notation, a number in base **b** can be understood as a linear
|
||||||
|
combination of powers of **b**.
|
||||||
|
|
||||||
|
The number 42, *in base 10*, means:
|
||||||
|
|
||||||
|
(4 * 10^1) + (2 * 10^0)
|
||||||
|
|
||||||
|
The number 101010, *in base 2*, means:
|
||||||
|
|
||||||
|
(1 * 2^5) + (0 * 2^4) + (1 * 2^3) + (0 * 2^2) + (1 * 2^1) + (0 * 2^0)
|
||||||
|
|
||||||
|
The number 1120, *in base 3*, means:
|
||||||
|
|
||||||
|
(1 * 3^3) + (1 * 3^2) + (2 * 3^1) + (0 * 3^0)
|
||||||
|
|
||||||
|
I think you got the idea!
|
||||||
|
|
||||||
|
*Yes. Those three numbers above are exactly the same. Congratulations!*
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @jonasbb
|
||||||
|
|
||||||
|
### Contributed to by
|
||||||
|
|
||||||
|
- @CGMossa
|
||||||
|
- @coriolinus
|
||||||
|
- @cwhakes
|
||||||
|
- @efx
|
||||||
|
- @ErikSchierboom
|
||||||
|
- @IanWhitney
|
||||||
|
- @lutostag
|
||||||
|
- @mkantor
|
||||||
|
- @navossoc
|
||||||
|
- @nfiles
|
||||||
|
- @pedantic79
|
||||||
|
- @petertseng
|
||||||
|
- @rofrol
|
||||||
|
- @stringparser
|
||||||
|
- @xakon
|
||||||
|
- @ZapAnton
|
||||||
68
all-your-base/src/lib.rs
Normal file
68
all-your-base/src/lib.rs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub enum Error {
|
||||||
|
InvalidInputBase,
|
||||||
|
InvalidOutputBase,
|
||||||
|
InvalidDigit(u32),
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Convert a number between two bases.
|
||||||
|
///
|
||||||
|
/// A number is any slice of digits.
|
||||||
|
/// A digit is any unsigned integer (e.g. u8, u16, u32, u64, or usize).
|
||||||
|
/// Bases are specified as unsigned integers.
|
||||||
|
///
|
||||||
|
/// Return an `Err(.)` if the conversion is impossible.
|
||||||
|
/// The tests do not test for specific values inside the `Err(.)`.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// You are allowed to change the function signature as long as all test still pass.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// Input
|
||||||
|
/// number: &[4, 2]
|
||||||
|
/// from_base: 10
|
||||||
|
/// to_base: 2
|
||||||
|
/// Result
|
||||||
|
/// Ok(vec![1, 0, 1, 0, 1, 0])
|
||||||
|
///
|
||||||
|
/// The example corresponds to converting the number 42 from decimal
|
||||||
|
/// which is equivalent to 101010 in binary.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Notes:
|
||||||
|
/// * The empty slice ( "[]" ) is equal to the number 0.
|
||||||
|
/// * Never output leading 0 digits, unless the input number is 0, in which the output must be `[0]`.
|
||||||
|
/// However, your function must be able to process input with leading 0 digits.
|
||||||
|
///
|
||||||
|
pub fn convert(number: &[u32], from_base: u32, to_base: u32) -> Result<Vec<u32>, Error> {
|
||||||
|
if from_base < 2 {
|
||||||
|
return Err(Error::InvalidInputBase);
|
||||||
|
}
|
||||||
|
if to_base < 2 {
|
||||||
|
return Err(Error::InvalidOutputBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut value: u32 = 0;
|
||||||
|
for &n in number.iter() {
|
||||||
|
if n >= from_base {
|
||||||
|
return Err(Error::InvalidDigit(n))
|
||||||
|
} else {
|
||||||
|
value = value * from_base + n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut result = Vec::new();
|
||||||
|
while value != 0 {
|
||||||
|
result.push(value % to_base);
|
||||||
|
value /= to_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.is_empty() {
|
||||||
|
result.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.reverse();
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
216
all-your-base/tests/all-your-base.rs
Normal file
216
all-your-base/tests/all-your-base.rs
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
use allyourbase as ayb;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn single_bit_one_to_decimal() {
|
||||||
|
let input_base = 2;
|
||||||
|
let input_digits = &[1];
|
||||||
|
let output_base = 10;
|
||||||
|
let output_digits = vec![1];
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Ok(output_digits)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn binary_to_single_decimal() {
|
||||||
|
let input_base = 2;
|
||||||
|
let input_digits = &[1, 0, 1];
|
||||||
|
let output_base = 10;
|
||||||
|
let output_digits = vec![5];
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Ok(output_digits)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn single_decimal_to_binary() {
|
||||||
|
let input_base = 10;
|
||||||
|
let input_digits = &[5];
|
||||||
|
let output_base = 2;
|
||||||
|
let output_digits = vec![1, 0, 1];
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Ok(output_digits)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn binary_to_multiple_decimal() {
|
||||||
|
let input_base = 2;
|
||||||
|
let input_digits = &[1, 0, 1, 0, 1, 0];
|
||||||
|
let output_base = 10;
|
||||||
|
let output_digits = vec![4, 2];
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Ok(output_digits)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn decimal_to_binary() {
|
||||||
|
let input_base = 10;
|
||||||
|
let input_digits = &[4, 2];
|
||||||
|
let output_base = 2;
|
||||||
|
let output_digits = vec![1, 0, 1, 0, 1, 0];
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Ok(output_digits)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn trinary_to_hexadecimal() {
|
||||||
|
let input_base = 3;
|
||||||
|
let input_digits = &[1, 1, 2, 0];
|
||||||
|
let output_base = 16;
|
||||||
|
let output_digits = vec![2, 10];
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Ok(output_digits)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn hexadecimal_to_trinary() {
|
||||||
|
let input_base = 16;
|
||||||
|
let input_digits = &[2, 10];
|
||||||
|
let output_base = 3;
|
||||||
|
let output_digits = vec![1, 1, 2, 0];
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Ok(output_digits)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn fifteen_bit_integer() {
|
||||||
|
let input_base = 97;
|
||||||
|
let input_digits = &[3, 46, 60];
|
||||||
|
let output_base = 73;
|
||||||
|
let output_digits = vec![6, 10, 45];
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Ok(output_digits)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn empty_list() {
|
||||||
|
let input_base = 2;
|
||||||
|
let input_digits = &[];
|
||||||
|
let output_base = 10;
|
||||||
|
let output_digits = vec![0];
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Ok(output_digits)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn single_zero() {
|
||||||
|
let input_base = 10;
|
||||||
|
let input_digits = &[0];
|
||||||
|
let output_base = 2;
|
||||||
|
let output_digits = vec![0];
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Ok(output_digits)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn multiple_zeros() {
|
||||||
|
let input_base = 10;
|
||||||
|
let input_digits = &[0, 0, 0];
|
||||||
|
let output_base = 2;
|
||||||
|
let output_digits = vec![0];
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Ok(output_digits)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn leading_zeros() {
|
||||||
|
let input_base = 7;
|
||||||
|
let input_digits = &[0, 6, 0];
|
||||||
|
let output_base = 10;
|
||||||
|
let output_digits = vec![4, 2];
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Ok(output_digits)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn invalid_positive_digit() {
|
||||||
|
let input_base = 2;
|
||||||
|
let input_digits = &[1, 2, 1, 0, 1, 0];
|
||||||
|
let output_base = 10;
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Err(ayb::Error::InvalidDigit(2))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn input_base_is_one() {
|
||||||
|
let input_base = 1;
|
||||||
|
let input_digits = &[];
|
||||||
|
let output_base = 10;
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Err(ayb::Error::InvalidInputBase)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn output_base_is_one() {
|
||||||
|
let input_base = 2;
|
||||||
|
let input_digits = &[1, 0, 1, 0, 1, 0];
|
||||||
|
let output_base = 1;
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Err(ayb::Error::InvalidOutputBase)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn input_base_is_zero() {
|
||||||
|
let input_base = 0;
|
||||||
|
let input_digits = &[];
|
||||||
|
let output_base = 10;
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Err(ayb::Error::InvalidInputBase)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn output_base_is_zero() {
|
||||||
|
let input_base = 10;
|
||||||
|
let input_digits = &[7];
|
||||||
|
let output_base = 0;
|
||||||
|
assert_eq!(
|
||||||
|
ayb::convert(input_digits, input_base, output_base),
|
||||||
|
Err(ayb::Error::InvalidOutputBase)
|
||||||
|
);
|
||||||
|
}
|
||||||
47
anagram/.exercism/config.json
Normal file
47
anagram/.exercism/config.json
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"blurb": "Given a word and a list of possible anagrams, select the correct sublist.",
|
||||||
|
"authors": [
|
||||||
|
"EduardoBautista"
|
||||||
|
],
|
||||||
|
"contributors": [
|
||||||
|
"andrewclarkson",
|
||||||
|
"ashleygwilliams",
|
||||||
|
"bobahop",
|
||||||
|
"chancancode",
|
||||||
|
"ClashTheBunny",
|
||||||
|
"coriolinus",
|
||||||
|
"cwhakes",
|
||||||
|
"Dimkar3000",
|
||||||
|
"EduardoBautista",
|
||||||
|
"efx",
|
||||||
|
"ErikSchierboom",
|
||||||
|
"gris",
|
||||||
|
"IanWhitney",
|
||||||
|
"kytrinyx",
|
||||||
|
"lutostag",
|
||||||
|
"mkantor",
|
||||||
|
"nfiles",
|
||||||
|
"petertseng",
|
||||||
|
"pminten",
|
||||||
|
"quartsize",
|
||||||
|
"rofrol",
|
||||||
|
"stevejb71",
|
||||||
|
"stringparser",
|
||||||
|
"xakon",
|
||||||
|
"ZapAnton"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"src/lib.rs",
|
||||||
|
"Cargo.toml"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/anagram.rs"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.rs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"source": "Inspired by the Extreme Startup game",
|
||||||
|
"source_url": "https://github.com/rchatley/extreme_startup"
|
||||||
|
}
|
||||||
1
anagram/.exercism/metadata.json
Normal file
1
anagram/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"track":"rust","exercise":"anagram","id":"5abb5b06fa2749eb88cee51e987ac255","url":"https://exercism.org/tracks/rust/exercises/anagram","handle":"ArthurDanjou","is_requester":true,"auto_approve":false}
|
||||||
8
anagram/.gitignore
vendored
Normal file
8
anagram/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
/target/
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
|
||||||
|
Cargo.lock
|
||||||
4
anagram/Cargo.toml
Normal file
4
anagram/Cargo.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[package]
|
||||||
|
edition = "2021"
|
||||||
|
name = "anagram"
|
||||||
|
version = "0.0.0"
|
||||||
85
anagram/HELP.md
Normal file
85
anagram/HELP.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test
|
||||||
|
```
|
||||||
|
|
||||||
|
All but the first test have been ignored. After you get the first test to
|
||||||
|
pass, open the tests source file which is located in the `tests` directory
|
||||||
|
and remove the `#[ignore]` flag from the next test and get the tests to pass
|
||||||
|
again. Each separate test is a function with `#[test]` flag above it.
|
||||||
|
Continue, until you pass every test.
|
||||||
|
|
||||||
|
If you wish to run _only ignored_ tests without editing the tests source file, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are using Rust 1.51 or later, you can run _all_ tests with
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --include-ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a specific test, for example `some_test`, you can use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test
|
||||||
|
```
|
||||||
|
|
||||||
|
If the specific test is ignored, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about Rust tests refer to the online [test documentation][rust-tests].
|
||||||
|
|
||||||
|
[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit src/lib.rs Cargo.toml` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Rust track's documentation](https://exercism.org/docs/tracks/rust)
|
||||||
|
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
## Rust Installation
|
||||||
|
|
||||||
|
Refer to the [exercism help page][help-page] for Rust installation and learning
|
||||||
|
resources.
|
||||||
|
|
||||||
|
## Submitting the solution
|
||||||
|
|
||||||
|
Generally you should submit all files in which you implemented your solution (`src/lib.rs` in most cases). If you are using any external crates, please consider submitting the `Cargo.toml` file. This will make the review process faster and clearer.
|
||||||
|
|
||||||
|
## Feedback, Issues, Pull Requests
|
||||||
|
|
||||||
|
The GitHub [track repository][github] is the home for all of the Rust exercises. If you have feedback about an exercise, or want to help implement new exercises, head over there and create an issue. Members of the rust track team are happy to help!
|
||||||
|
|
||||||
|
If you want to know more about Exercism, take a look at the [contribution guide].
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
||||||
|
[help-page]: https://exercism.org/tracks/rust/learning
|
||||||
|
[github]: https://github.com/exercism/rust
|
||||||
|
[contribution guide]: https://exercism.org/docs/community/contributors
|
||||||
61
anagram/README.md
Normal file
61
anagram/README.md
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# Anagram
|
||||||
|
|
||||||
|
Welcome to Anagram on Exercism's Rust Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
An anagram is a rearrangement of letters to form a new word.
|
||||||
|
Given a word and a list of candidates, select the sublist of anagrams of the given word.
|
||||||
|
|
||||||
|
Given `"listen"` and a list of candidates like `"enlists" "google"
|
||||||
|
"inlets" "banana"` the program should return a list containing
|
||||||
|
`"inlets"`.
|
||||||
|
|
||||||
|
The solution is case insensitive, which means `"WOrd"` is the same as `"word"` or `"woRd"`. It may help to take a peek at the [std library](https://doc.rust-lang.org/std/primitive.char.html) for functions that can convert between them.
|
||||||
|
|
||||||
|
The solution cannot contain the input word. A word is always an anagram of itself, which means it is not an interesting result. Given `"hello"` and the list `["hello", "olleh"]` the answer is `["olleh"]`.
|
||||||
|
|
||||||
|
You are going to have to adjust the function signature provided in the stub in order for the lifetimes to work out properly. This is intentional: what's there demonstrates the basics of lifetime syntax, and what's missing teaches how to interpret lifetime-related compiler errors.
|
||||||
|
|
||||||
|
Try to limit case changes. Case changes are expensive in terms of time, so it's faster to minimize them.
|
||||||
|
|
||||||
|
If sorting, consider [sort_unstable](https://doc.rust-lang.org/std/primitive.slice.html#method.sort_unstable) which is typically faster than stable sorting. When applicable, unstable sorting is preferred because it is generally faster than stable sorting and it doesn't allocate auxiliary memory.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @EduardoBautista
|
||||||
|
|
||||||
|
### Contributed to by
|
||||||
|
|
||||||
|
- @andrewclarkson
|
||||||
|
- @ashleygwilliams
|
||||||
|
- @bobahop
|
||||||
|
- @chancancode
|
||||||
|
- @ClashTheBunny
|
||||||
|
- @coriolinus
|
||||||
|
- @cwhakes
|
||||||
|
- @Dimkar3000
|
||||||
|
- @EduardoBautista
|
||||||
|
- @efx
|
||||||
|
- @ErikSchierboom
|
||||||
|
- @gris
|
||||||
|
- @IanWhitney
|
||||||
|
- @kytrinyx
|
||||||
|
- @lutostag
|
||||||
|
- @mkantor
|
||||||
|
- @nfiles
|
||||||
|
- @petertseng
|
||||||
|
- @pminten
|
||||||
|
- @quartsize
|
||||||
|
- @rofrol
|
||||||
|
- @stevejb71
|
||||||
|
- @stringparser
|
||||||
|
- @xakon
|
||||||
|
- @ZapAnton
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
Inspired by the Extreme Startup game - https://github.com/rchatley/extreme_startup
|
||||||
25
anagram/src/lib.rs
Normal file
25
anagram/src/lib.rs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
pub fn anagrams_for<'a>(word: &str, possible_anagrams: &[&'a str]) -> HashSet<&'a str> {
|
||||||
|
let to_lowercase_s = |c: char| {
|
||||||
|
if !c.is_lowercase() {
|
||||||
|
c.to_lowercase().to_string()
|
||||||
|
} else {
|
||||||
|
c.to_string()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let lw: Vec<_> = word.chars().map(to_lowercase_s).collect();
|
||||||
|
let mut sc: Vec<_> = word.chars().map(to_lowercase_s).collect();
|
||||||
|
sc.sort_unstable();
|
||||||
|
|
||||||
|
let result = possible_anagrams.iter()
|
||||||
|
.filter(|w| {
|
||||||
|
let mut sci: Vec<_> = w.chars().map(to_lowercase_s).collect();
|
||||||
|
let same_word = lw == sci;
|
||||||
|
sci.sort_unstable();
|
||||||
|
sci == sc && !same_word
|
||||||
|
}).map(|&w| w);
|
||||||
|
|
||||||
|
HashSet::from_iter(result)
|
||||||
|
}
|
||||||
186
anagram/tests/anagram.rs
Normal file
186
anagram/tests/anagram.rs
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
fn process_anagram_case(word: &str, inputs: &[&str], expected: &[&str]) {
|
||||||
|
let result = anagram::anagrams_for(word, inputs);
|
||||||
|
|
||||||
|
let expected: HashSet<&str> = expected.iter().cloned().collect();
|
||||||
|
|
||||||
|
assert_eq!(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_no_matches() {
|
||||||
|
let word = "diaper";
|
||||||
|
|
||||||
|
let inputs = ["hello", "world", "zombies", "pants"];
|
||||||
|
|
||||||
|
let outputs = vec![];
|
||||||
|
|
||||||
|
process_anagram_case(word, &inputs, &outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_detect_simple_anagram() {
|
||||||
|
let word = "ant";
|
||||||
|
|
||||||
|
let inputs = ["tan", "stand", "at"];
|
||||||
|
|
||||||
|
let outputs = vec!["tan"];
|
||||||
|
|
||||||
|
process_anagram_case(word, &inputs, &outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_does_not_confuse_different_duplicates() {
|
||||||
|
let word = "galea";
|
||||||
|
|
||||||
|
let inputs = ["eagle"];
|
||||||
|
|
||||||
|
let outputs = vec![];
|
||||||
|
|
||||||
|
process_anagram_case(word, &inputs, &outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_eliminate_anagram_subsets() {
|
||||||
|
let word = "good";
|
||||||
|
|
||||||
|
let inputs = ["dog", "goody"];
|
||||||
|
|
||||||
|
let outputs = vec![];
|
||||||
|
|
||||||
|
process_anagram_case(word, &inputs, &outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_detect_anagram() {
|
||||||
|
let word = "listen";
|
||||||
|
|
||||||
|
let inputs = ["enlists", "google", "inlets", "banana"];
|
||||||
|
|
||||||
|
let outputs = vec!["inlets"];
|
||||||
|
|
||||||
|
process_anagram_case(word, &inputs, &outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_multiple_anagrams() {
|
||||||
|
let word = "allergy";
|
||||||
|
|
||||||
|
let inputs = [
|
||||||
|
"gallery",
|
||||||
|
"ballerina",
|
||||||
|
"regally",
|
||||||
|
"clergy",
|
||||||
|
"largely",
|
||||||
|
"leading",
|
||||||
|
];
|
||||||
|
|
||||||
|
let outputs = vec!["gallery", "regally", "largely"];
|
||||||
|
|
||||||
|
process_anagram_case(word, &inputs, &outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_case_insensitive_anagrams() {
|
||||||
|
let word = "Orchestra";
|
||||||
|
|
||||||
|
let inputs = ["cashregister", "Carthorse", "radishes"];
|
||||||
|
|
||||||
|
let outputs = vec!["Carthorse"];
|
||||||
|
|
||||||
|
process_anagram_case(word, &inputs, &outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_unicode_anagrams() {
|
||||||
|
let word = "ΑΒΓ";
|
||||||
|
|
||||||
|
// These words don't make sense, they're just greek letters cobbled together.
|
||||||
|
let inputs = ["ΒΓΑ", "ΒΓΔ", "γβα"];
|
||||||
|
|
||||||
|
let outputs = vec!["ΒΓΑ", "γβα"];
|
||||||
|
|
||||||
|
process_anagram_case(word, &inputs, &outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_misleading_unicode_anagrams() {
|
||||||
|
// Despite what a human might think these words contain different letters, the input uses Greek
|
||||||
|
// A and B while the list of potential anagrams uses Latin A and B.
|
||||||
|
let word = "ΑΒΓ";
|
||||||
|
|
||||||
|
let inputs = ["ABΓ"];
|
||||||
|
|
||||||
|
let outputs = vec![];
|
||||||
|
|
||||||
|
process_anagram_case(word, &inputs, &outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_does_not_detect_a_word_as_its_own_anagram() {
|
||||||
|
let word = "banana";
|
||||||
|
|
||||||
|
let inputs = ["banana"];
|
||||||
|
|
||||||
|
let outputs = vec![];
|
||||||
|
|
||||||
|
process_anagram_case(word, &inputs, &outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_does_not_detect_a_differently_cased_word_as_its_own_anagram() {
|
||||||
|
let word = "banana";
|
||||||
|
|
||||||
|
let inputs = ["bAnana"];
|
||||||
|
|
||||||
|
let outputs = vec![];
|
||||||
|
|
||||||
|
process_anagram_case(word, &inputs, &outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_does_not_detect_a_differently_cased_unicode_word_as_its_own_anagram() {
|
||||||
|
let word = "ΑΒΓ";
|
||||||
|
|
||||||
|
let inputs = ["ΑΒγ"];
|
||||||
|
|
||||||
|
let outputs = vec![];
|
||||||
|
|
||||||
|
process_anagram_case(word, &inputs, &outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_same_bytes_different_chars() {
|
||||||
|
let word = "a⬂"; // 61 E2 AC 82
|
||||||
|
|
||||||
|
let inputs = ["€a"]; // E2 82 AC 61
|
||||||
|
|
||||||
|
let outputs = vec![];
|
||||||
|
|
||||||
|
process_anagram_case(word, &inputs, &outputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_different_words_but_same_ascii_sum() {
|
||||||
|
let word = "bc";
|
||||||
|
|
||||||
|
let inputs = ["ad"];
|
||||||
|
|
||||||
|
let outputs = vec![];
|
||||||
|
|
||||||
|
process_anagram_case(word, &inputs, &outputs);
|
||||||
|
}
|
||||||
36
armstrong-numbers/.exercism/config.json
Normal file
36
armstrong-numbers/.exercism/config.json
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"blurb": "Determine if a number is an Armstrong number",
|
||||||
|
"authors": [
|
||||||
|
"shingtaklam1324"
|
||||||
|
],
|
||||||
|
"contributors": [
|
||||||
|
"AndrewKvalheim",
|
||||||
|
"coriolinus",
|
||||||
|
"cwhakes",
|
||||||
|
"eddyp",
|
||||||
|
"efx",
|
||||||
|
"ErikSchierboom",
|
||||||
|
"lutostag",
|
||||||
|
"ocstl",
|
||||||
|
"petertseng",
|
||||||
|
"rofrol",
|
||||||
|
"sputnick1124",
|
||||||
|
"stringparser",
|
||||||
|
"xakon",
|
||||||
|
"ZapAnton"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"src/lib.rs",
|
||||||
|
"Cargo.toml"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/armstrong-numbers.rs"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.rs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"source": "Wikipedia",
|
||||||
|
"source_url": "https://en.wikipedia.org/wiki/Narcissistic_number"
|
||||||
|
}
|
||||||
1
armstrong-numbers/.exercism/metadata.json
Normal file
1
armstrong-numbers/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"track":"rust","exercise":"armstrong-numbers","id":"a40568d0bf3448af81f78f78a233cb45","url":"https://exercism.org/tracks/rust/exercises/armstrong-numbers","handle":"ArthurDanjou","is_requester":true,"auto_approve":false}
|
||||||
8
armstrong-numbers/.gitignore
vendored
Normal file
8
armstrong-numbers/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
/target/
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
|
||||||
|
Cargo.lock
|
||||||
4
armstrong-numbers/Cargo.toml
Normal file
4
armstrong-numbers/Cargo.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[package]
|
||||||
|
edition = "2021"
|
||||||
|
name = "armstrong_numbers"
|
||||||
|
version = "1.1.0"
|
||||||
85
armstrong-numbers/HELP.md
Normal file
85
armstrong-numbers/HELP.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test
|
||||||
|
```
|
||||||
|
|
||||||
|
All but the first test have been ignored. After you get the first test to
|
||||||
|
pass, open the tests source file which is located in the `tests` directory
|
||||||
|
and remove the `#[ignore]` flag from the next test and get the tests to pass
|
||||||
|
again. Each separate test is a function with `#[test]` flag above it.
|
||||||
|
Continue, until you pass every test.
|
||||||
|
|
||||||
|
If you wish to run _only ignored_ tests without editing the tests source file, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are using Rust 1.51 or later, you can run _all_ tests with
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --include-ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a specific test, for example `some_test`, you can use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test
|
||||||
|
```
|
||||||
|
|
||||||
|
If the specific test is ignored, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about Rust tests refer to the online [test documentation][rust-tests].
|
||||||
|
|
||||||
|
[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit src/lib.rs Cargo.toml` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Rust track's documentation](https://exercism.org/docs/tracks/rust)
|
||||||
|
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
## Rust Installation
|
||||||
|
|
||||||
|
Refer to the [exercism help page][help-page] for Rust installation and learning
|
||||||
|
resources.
|
||||||
|
|
||||||
|
## Submitting the solution
|
||||||
|
|
||||||
|
Generally you should submit all files in which you implemented your solution (`src/lib.rs` in most cases). If you are using any external crates, please consider submitting the `Cargo.toml` file. This will make the review process faster and clearer.
|
||||||
|
|
||||||
|
## Feedback, Issues, Pull Requests
|
||||||
|
|
||||||
|
The GitHub [track repository][github] is the home for all of the Rust exercises. If you have feedback about an exercise, or want to help implement new exercises, head over there and create an issue. Members of the rust track team are happy to help!
|
||||||
|
|
||||||
|
If you want to know more about Exercism, take a look at the [contribution guide].
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
||||||
|
[help-page]: https://exercism.org/tracks/rust/learning
|
||||||
|
[github]: https://github.com/exercism/rust
|
||||||
|
[contribution guide]: https://exercism.org/docs/community/contributors
|
||||||
44
armstrong-numbers/README.md
Normal file
44
armstrong-numbers/README.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# Armstrong Numbers
|
||||||
|
|
||||||
|
Welcome to Armstrong Numbers on Exercism's Rust Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
An [Armstrong number](https://en.wikipedia.org/wiki/Narcissistic_number) is a number that is the sum of its own digits each raised to the power of the number of digits.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
- 9 is an Armstrong number, because `9 = 9^1 = 9`
|
||||||
|
- 10 is *not* an Armstrong number, because `10 != 1^2 + 0^2 = 1`
|
||||||
|
- 153 is an Armstrong number, because: `153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153`
|
||||||
|
- 154 is *not* an Armstrong number, because: `154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190`
|
||||||
|
|
||||||
|
Write some code to determine whether a number is an Armstrong number.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @shingtaklam1324
|
||||||
|
|
||||||
|
### Contributed to by
|
||||||
|
|
||||||
|
- @AndrewKvalheim
|
||||||
|
- @coriolinus
|
||||||
|
- @cwhakes
|
||||||
|
- @eddyp
|
||||||
|
- @efx
|
||||||
|
- @ErikSchierboom
|
||||||
|
- @lutostag
|
||||||
|
- @ocstl
|
||||||
|
- @petertseng
|
||||||
|
- @rofrol
|
||||||
|
- @sputnick1124
|
||||||
|
- @stringparser
|
||||||
|
- @xakon
|
||||||
|
- @ZapAnton
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
Wikipedia - https://en.wikipedia.org/wiki/Narcissistic_number
|
||||||
8
armstrong-numbers/src/lib.rs
Normal file
8
armstrong-numbers/src/lib.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
pub fn is_armstrong_number(num: u32) -> bool {
|
||||||
|
num == num
|
||||||
|
.to_string()
|
||||||
|
.chars()
|
||||||
|
.map(|c| c.to_digit(10).unwrap())
|
||||||
|
.map(|d| d.pow(num.to_string().len() as u32))
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
54
armstrong-numbers/tests/armstrong-numbers.rs
Normal file
54
armstrong-numbers/tests/armstrong-numbers.rs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
use armstrong_numbers::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_zero_is_an_armstrong_number() {
|
||||||
|
assert!(is_armstrong_number(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_single_digit_numbers_are_armstrong_numbers() {
|
||||||
|
assert!(is_armstrong_number(5))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_there_are_no_2_digit_armstrong_numbers() {
|
||||||
|
assert!(!is_armstrong_number(10))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_three_digit_armstrong_number() {
|
||||||
|
assert!(is_armstrong_number(153))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_three_digit_non_armstrong_number() {
|
||||||
|
assert!(!is_armstrong_number(100))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_four_digit_armstrong_number() {
|
||||||
|
assert!(is_armstrong_number(9474))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_four_digit_non_armstrong_number() {
|
||||||
|
assert!(!is_armstrong_number(9475))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_seven_digit_armstrong_number() {
|
||||||
|
assert!(is_armstrong_number(9_926_315))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_seven_digit_non_armstrong_number() {
|
||||||
|
assert!(!is_armstrong_number(9_926_316))
|
||||||
|
}
|
||||||
44
beer-song/.exercism/config.json
Normal file
44
beer-song/.exercism/config.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"blurb": "Produce the lyrics to that beloved classic, that field-trip favorite: 99 Bottles of Beer on the Wall.",
|
||||||
|
"authors": [
|
||||||
|
"EduardoBautista"
|
||||||
|
],
|
||||||
|
"contributors": [
|
||||||
|
"andrewclarkson",
|
||||||
|
"ashleygwilliams",
|
||||||
|
"coriolinus",
|
||||||
|
"cwhakes",
|
||||||
|
"EduardoBautista",
|
||||||
|
"efx",
|
||||||
|
"ErikSchierboom",
|
||||||
|
"IanWhitney",
|
||||||
|
"kytrinyx",
|
||||||
|
"leoyvens",
|
||||||
|
"lutostag",
|
||||||
|
"mkantor",
|
||||||
|
"murlakatamenka",
|
||||||
|
"navossoc",
|
||||||
|
"nfiles",
|
||||||
|
"petertseng",
|
||||||
|
"pminten",
|
||||||
|
"razielgn",
|
||||||
|
"rofrol",
|
||||||
|
"stringparser",
|
||||||
|
"xakon",
|
||||||
|
"ZapAnton"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"src/lib.rs",
|
||||||
|
"Cargo.toml"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/beer-song.rs"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.rs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"source": "Learn to Program by Chris Pine",
|
||||||
|
"source_url": "http://pine.fm/LearnToProgram/?Chapter=06"
|
||||||
|
}
|
||||||
1
beer-song/.exercism/metadata.json
Normal file
1
beer-song/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"track":"rust","exercise":"beer-song","id":"73cb4eea0081401d9672503aa42beb65","url":"https://exercism.org/tracks/rust/exercises/beer-song","handle":"ArthurDanjou","is_requester":true,"auto_approve":false}
|
||||||
8
beer-song/.gitignore
vendored
Normal file
8
beer-song/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
/target/
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
|
||||||
|
Cargo.lock
|
||||||
4
beer-song/Cargo.toml
Normal file
4
beer-song/Cargo.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[package]
|
||||||
|
edition = "2021"
|
||||||
|
name = "beer-song"
|
||||||
|
version = "0.0.0"
|
||||||
85
beer-song/HELP.md
Normal file
85
beer-song/HELP.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test
|
||||||
|
```
|
||||||
|
|
||||||
|
All but the first test have been ignored. After you get the first test to
|
||||||
|
pass, open the tests source file which is located in the `tests` directory
|
||||||
|
and remove the `#[ignore]` flag from the next test and get the tests to pass
|
||||||
|
again. Each separate test is a function with `#[test]` flag above it.
|
||||||
|
Continue, until you pass every test.
|
||||||
|
|
||||||
|
If you wish to run _only ignored_ tests without editing the tests source file, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are using Rust 1.51 or later, you can run _all_ tests with
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --include-ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a specific test, for example `some_test`, you can use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test
|
||||||
|
```
|
||||||
|
|
||||||
|
If the specific test is ignored, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about Rust tests refer to the online [test documentation][rust-tests].
|
||||||
|
|
||||||
|
[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit src/lib.rs Cargo.toml` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Rust track's documentation](https://exercism.org/docs/tracks/rust)
|
||||||
|
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
## Rust Installation
|
||||||
|
|
||||||
|
Refer to the [exercism help page][help-page] for Rust installation and learning
|
||||||
|
resources.
|
||||||
|
|
||||||
|
## Submitting the solution
|
||||||
|
|
||||||
|
Generally you should submit all files in which you implemented your solution (`src/lib.rs` in most cases). If you are using any external crates, please consider submitting the `Cargo.toml` file. This will make the review process faster and clearer.
|
||||||
|
|
||||||
|
## Feedback, Issues, Pull Requests
|
||||||
|
|
||||||
|
The GitHub [track repository][github] is the home for all of the Rust exercises. If you have feedback about an exercise, or want to help implement new exercises, head over there and create an issue. Members of the rust track team are happy to help!
|
||||||
|
|
||||||
|
If you want to know more about Exercism, take a look at the [contribution guide].
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
||||||
|
[help-page]: https://exercism.org/tracks/rust/learning
|
||||||
|
[github]: https://github.com/exercism/rust
|
||||||
|
[contribution guide]: https://exercism.org/docs/community/contributors
|
||||||
361
beer-song/README.md
Normal file
361
beer-song/README.md
Normal file
@@ -0,0 +1,361 @@
|
|||||||
|
# Beer Song
|
||||||
|
|
||||||
|
Welcome to Beer Song on Exercism's Rust Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Recite the lyrics to that beloved classic, that field-trip favorite: 99 Bottles of Beer on the Wall.
|
||||||
|
|
||||||
|
Note that not all verses are identical.
|
||||||
|
|
||||||
|
```text
|
||||||
|
99 bottles of beer on the wall, 99 bottles of beer.
|
||||||
|
Take one down and pass it around, 98 bottles of beer on the wall.
|
||||||
|
|
||||||
|
98 bottles of beer on the wall, 98 bottles of beer.
|
||||||
|
Take one down and pass it around, 97 bottles of beer on the wall.
|
||||||
|
|
||||||
|
97 bottles of beer on the wall, 97 bottles of beer.
|
||||||
|
Take one down and pass it around, 96 bottles of beer on the wall.
|
||||||
|
|
||||||
|
96 bottles of beer on the wall, 96 bottles of beer.
|
||||||
|
Take one down and pass it around, 95 bottles of beer on the wall.
|
||||||
|
|
||||||
|
95 bottles of beer on the wall, 95 bottles of beer.
|
||||||
|
Take one down and pass it around, 94 bottles of beer on the wall.
|
||||||
|
|
||||||
|
94 bottles of beer on the wall, 94 bottles of beer.
|
||||||
|
Take one down and pass it around, 93 bottles of beer on the wall.
|
||||||
|
|
||||||
|
93 bottles of beer on the wall, 93 bottles of beer.
|
||||||
|
Take one down and pass it around, 92 bottles of beer on the wall.
|
||||||
|
|
||||||
|
92 bottles of beer on the wall, 92 bottles of beer.
|
||||||
|
Take one down and pass it around, 91 bottles of beer on the wall.
|
||||||
|
|
||||||
|
91 bottles of beer on the wall, 91 bottles of beer.
|
||||||
|
Take one down and pass it around, 90 bottles of beer on the wall.
|
||||||
|
|
||||||
|
90 bottles of beer on the wall, 90 bottles of beer.
|
||||||
|
Take one down and pass it around, 89 bottles of beer on the wall.
|
||||||
|
|
||||||
|
89 bottles of beer on the wall, 89 bottles of beer.
|
||||||
|
Take one down and pass it around, 88 bottles of beer on the wall.
|
||||||
|
|
||||||
|
88 bottles of beer on the wall, 88 bottles of beer.
|
||||||
|
Take one down and pass it around, 87 bottles of beer on the wall.
|
||||||
|
|
||||||
|
87 bottles of beer on the wall, 87 bottles of beer.
|
||||||
|
Take one down and pass it around, 86 bottles of beer on the wall.
|
||||||
|
|
||||||
|
86 bottles of beer on the wall, 86 bottles of beer.
|
||||||
|
Take one down and pass it around, 85 bottles of beer on the wall.
|
||||||
|
|
||||||
|
85 bottles of beer on the wall, 85 bottles of beer.
|
||||||
|
Take one down and pass it around, 84 bottles of beer on the wall.
|
||||||
|
|
||||||
|
84 bottles of beer on the wall, 84 bottles of beer.
|
||||||
|
Take one down and pass it around, 83 bottles of beer on the wall.
|
||||||
|
|
||||||
|
83 bottles of beer on the wall, 83 bottles of beer.
|
||||||
|
Take one down and pass it around, 82 bottles of beer on the wall.
|
||||||
|
|
||||||
|
82 bottles of beer on the wall, 82 bottles of beer.
|
||||||
|
Take one down and pass it around, 81 bottles of beer on the wall.
|
||||||
|
|
||||||
|
81 bottles of beer on the wall, 81 bottles of beer.
|
||||||
|
Take one down and pass it around, 80 bottles of beer on the wall.
|
||||||
|
|
||||||
|
80 bottles of beer on the wall, 80 bottles of beer.
|
||||||
|
Take one down and pass it around, 79 bottles of beer on the wall.
|
||||||
|
|
||||||
|
79 bottles of beer on the wall, 79 bottles of beer.
|
||||||
|
Take one down and pass it around, 78 bottles of beer on the wall.
|
||||||
|
|
||||||
|
78 bottles of beer on the wall, 78 bottles of beer.
|
||||||
|
Take one down and pass it around, 77 bottles of beer on the wall.
|
||||||
|
|
||||||
|
77 bottles of beer on the wall, 77 bottles of beer.
|
||||||
|
Take one down and pass it around, 76 bottles of beer on the wall.
|
||||||
|
|
||||||
|
76 bottles of beer on the wall, 76 bottles of beer.
|
||||||
|
Take one down and pass it around, 75 bottles of beer on the wall.
|
||||||
|
|
||||||
|
75 bottles of beer on the wall, 75 bottles of beer.
|
||||||
|
Take one down and pass it around, 74 bottles of beer on the wall.
|
||||||
|
|
||||||
|
74 bottles of beer on the wall, 74 bottles of beer.
|
||||||
|
Take one down and pass it around, 73 bottles of beer on the wall.
|
||||||
|
|
||||||
|
73 bottles of beer on the wall, 73 bottles of beer.
|
||||||
|
Take one down and pass it around, 72 bottles of beer on the wall.
|
||||||
|
|
||||||
|
72 bottles of beer on the wall, 72 bottles of beer.
|
||||||
|
Take one down and pass it around, 71 bottles of beer on the wall.
|
||||||
|
|
||||||
|
71 bottles of beer on the wall, 71 bottles of beer.
|
||||||
|
Take one down and pass it around, 70 bottles of beer on the wall.
|
||||||
|
|
||||||
|
70 bottles of beer on the wall, 70 bottles of beer.
|
||||||
|
Take one down and pass it around, 69 bottles of beer on the wall.
|
||||||
|
|
||||||
|
69 bottles of beer on the wall, 69 bottles of beer.
|
||||||
|
Take one down and pass it around, 68 bottles of beer on the wall.
|
||||||
|
|
||||||
|
68 bottles of beer on the wall, 68 bottles of beer.
|
||||||
|
Take one down and pass it around, 67 bottles of beer on the wall.
|
||||||
|
|
||||||
|
67 bottles of beer on the wall, 67 bottles of beer.
|
||||||
|
Take one down and pass it around, 66 bottles of beer on the wall.
|
||||||
|
|
||||||
|
66 bottles of beer on the wall, 66 bottles of beer.
|
||||||
|
Take one down and pass it around, 65 bottles of beer on the wall.
|
||||||
|
|
||||||
|
65 bottles of beer on the wall, 65 bottles of beer.
|
||||||
|
Take one down and pass it around, 64 bottles of beer on the wall.
|
||||||
|
|
||||||
|
64 bottles of beer on the wall, 64 bottles of beer.
|
||||||
|
Take one down and pass it around, 63 bottles of beer on the wall.
|
||||||
|
|
||||||
|
63 bottles of beer on the wall, 63 bottles of beer.
|
||||||
|
Take one down and pass it around, 62 bottles of beer on the wall.
|
||||||
|
|
||||||
|
62 bottles of beer on the wall, 62 bottles of beer.
|
||||||
|
Take one down and pass it around, 61 bottles of beer on the wall.
|
||||||
|
|
||||||
|
61 bottles of beer on the wall, 61 bottles of beer.
|
||||||
|
Take one down and pass it around, 60 bottles of beer on the wall.
|
||||||
|
|
||||||
|
60 bottles of beer on the wall, 60 bottles of beer.
|
||||||
|
Take one down and pass it around, 59 bottles of beer on the wall.
|
||||||
|
|
||||||
|
59 bottles of beer on the wall, 59 bottles of beer.
|
||||||
|
Take one down and pass it around, 58 bottles of beer on the wall.
|
||||||
|
|
||||||
|
58 bottles of beer on the wall, 58 bottles of beer.
|
||||||
|
Take one down and pass it around, 57 bottles of beer on the wall.
|
||||||
|
|
||||||
|
57 bottles of beer on the wall, 57 bottles of beer.
|
||||||
|
Take one down and pass it around, 56 bottles of beer on the wall.
|
||||||
|
|
||||||
|
56 bottles of beer on the wall, 56 bottles of beer.
|
||||||
|
Take one down and pass it around, 55 bottles of beer on the wall.
|
||||||
|
|
||||||
|
55 bottles of beer on the wall, 55 bottles of beer.
|
||||||
|
Take one down and pass it around, 54 bottles of beer on the wall.
|
||||||
|
|
||||||
|
54 bottles of beer on the wall, 54 bottles of beer.
|
||||||
|
Take one down and pass it around, 53 bottles of beer on the wall.
|
||||||
|
|
||||||
|
53 bottles of beer on the wall, 53 bottles of beer.
|
||||||
|
Take one down and pass it around, 52 bottles of beer on the wall.
|
||||||
|
|
||||||
|
52 bottles of beer on the wall, 52 bottles of beer.
|
||||||
|
Take one down and pass it around, 51 bottles of beer on the wall.
|
||||||
|
|
||||||
|
51 bottles of beer on the wall, 51 bottles of beer.
|
||||||
|
Take one down and pass it around, 50 bottles of beer on the wall.
|
||||||
|
|
||||||
|
50 bottles of beer on the wall, 50 bottles of beer.
|
||||||
|
Take one down and pass it around, 49 bottles of beer on the wall.
|
||||||
|
|
||||||
|
49 bottles of beer on the wall, 49 bottles of beer.
|
||||||
|
Take one down and pass it around, 48 bottles of beer on the wall.
|
||||||
|
|
||||||
|
48 bottles of beer on the wall, 48 bottles of beer.
|
||||||
|
Take one down and pass it around, 47 bottles of beer on the wall.
|
||||||
|
|
||||||
|
47 bottles of beer on the wall, 47 bottles of beer.
|
||||||
|
Take one down and pass it around, 46 bottles of beer on the wall.
|
||||||
|
|
||||||
|
46 bottles of beer on the wall, 46 bottles of beer.
|
||||||
|
Take one down and pass it around, 45 bottles of beer on the wall.
|
||||||
|
|
||||||
|
45 bottles of beer on the wall, 45 bottles of beer.
|
||||||
|
Take one down and pass it around, 44 bottles of beer on the wall.
|
||||||
|
|
||||||
|
44 bottles of beer on the wall, 44 bottles of beer.
|
||||||
|
Take one down and pass it around, 43 bottles of beer on the wall.
|
||||||
|
|
||||||
|
43 bottles of beer on the wall, 43 bottles of beer.
|
||||||
|
Take one down and pass it around, 42 bottles of beer on the wall.
|
||||||
|
|
||||||
|
42 bottles of beer on the wall, 42 bottles of beer.
|
||||||
|
Take one down and pass it around, 41 bottles of beer on the wall.
|
||||||
|
|
||||||
|
41 bottles of beer on the wall, 41 bottles of beer.
|
||||||
|
Take one down and pass it around, 40 bottles of beer on the wall.
|
||||||
|
|
||||||
|
40 bottles of beer on the wall, 40 bottles of beer.
|
||||||
|
Take one down and pass it around, 39 bottles of beer on the wall.
|
||||||
|
|
||||||
|
39 bottles of beer on the wall, 39 bottles of beer.
|
||||||
|
Take one down and pass it around, 38 bottles of beer on the wall.
|
||||||
|
|
||||||
|
38 bottles of beer on the wall, 38 bottles of beer.
|
||||||
|
Take one down and pass it around, 37 bottles of beer on the wall.
|
||||||
|
|
||||||
|
37 bottles of beer on the wall, 37 bottles of beer.
|
||||||
|
Take one down and pass it around, 36 bottles of beer on the wall.
|
||||||
|
|
||||||
|
36 bottles of beer on the wall, 36 bottles of beer.
|
||||||
|
Take one down and pass it around, 35 bottles of beer on the wall.
|
||||||
|
|
||||||
|
35 bottles of beer on the wall, 35 bottles of beer.
|
||||||
|
Take one down and pass it around, 34 bottles of beer on the wall.
|
||||||
|
|
||||||
|
34 bottles of beer on the wall, 34 bottles of beer.
|
||||||
|
Take one down and pass it around, 33 bottles of beer on the wall.
|
||||||
|
|
||||||
|
33 bottles of beer on the wall, 33 bottles of beer.
|
||||||
|
Take one down and pass it around, 32 bottles of beer on the wall.
|
||||||
|
|
||||||
|
32 bottles of beer on the wall, 32 bottles of beer.
|
||||||
|
Take one down and pass it around, 31 bottles of beer on the wall.
|
||||||
|
|
||||||
|
31 bottles of beer on the wall, 31 bottles of beer.
|
||||||
|
Take one down and pass it around, 30 bottles of beer on the wall.
|
||||||
|
|
||||||
|
30 bottles of beer on the wall, 30 bottles of beer.
|
||||||
|
Take one down and pass it around, 29 bottles of beer on the wall.
|
||||||
|
|
||||||
|
29 bottles of beer on the wall, 29 bottles of beer.
|
||||||
|
Take one down and pass it around, 28 bottles of beer on the wall.
|
||||||
|
|
||||||
|
28 bottles of beer on the wall, 28 bottles of beer.
|
||||||
|
Take one down and pass it around, 27 bottles of beer on the wall.
|
||||||
|
|
||||||
|
27 bottles of beer on the wall, 27 bottles of beer.
|
||||||
|
Take one down and pass it around, 26 bottles of beer on the wall.
|
||||||
|
|
||||||
|
26 bottles of beer on the wall, 26 bottles of beer.
|
||||||
|
Take one down and pass it around, 25 bottles of beer on the wall.
|
||||||
|
|
||||||
|
25 bottles of beer on the wall, 25 bottles of beer.
|
||||||
|
Take one down and pass it around, 24 bottles of beer on the wall.
|
||||||
|
|
||||||
|
24 bottles of beer on the wall, 24 bottles of beer.
|
||||||
|
Take one down and pass it around, 23 bottles of beer on the wall.
|
||||||
|
|
||||||
|
23 bottles of beer on the wall, 23 bottles of beer.
|
||||||
|
Take one down and pass it around, 22 bottles of beer on the wall.
|
||||||
|
|
||||||
|
22 bottles of beer on the wall, 22 bottles of beer.
|
||||||
|
Take one down and pass it around, 21 bottles of beer on the wall.
|
||||||
|
|
||||||
|
21 bottles of beer on the wall, 21 bottles of beer.
|
||||||
|
Take one down and pass it around, 20 bottles of beer on the wall.
|
||||||
|
|
||||||
|
20 bottles of beer on the wall, 20 bottles of beer.
|
||||||
|
Take one down and pass it around, 19 bottles of beer on the wall.
|
||||||
|
|
||||||
|
19 bottles of beer on the wall, 19 bottles of beer.
|
||||||
|
Take one down and pass it around, 18 bottles of beer on the wall.
|
||||||
|
|
||||||
|
18 bottles of beer on the wall, 18 bottles of beer.
|
||||||
|
Take one down and pass it around, 17 bottles of beer on the wall.
|
||||||
|
|
||||||
|
17 bottles of beer on the wall, 17 bottles of beer.
|
||||||
|
Take one down and pass it around, 16 bottles of beer on the wall.
|
||||||
|
|
||||||
|
16 bottles of beer on the wall, 16 bottles of beer.
|
||||||
|
Take one down and pass it around, 15 bottles of beer on the wall.
|
||||||
|
|
||||||
|
15 bottles of beer on the wall, 15 bottles of beer.
|
||||||
|
Take one down and pass it around, 14 bottles of beer on the wall.
|
||||||
|
|
||||||
|
14 bottles of beer on the wall, 14 bottles of beer.
|
||||||
|
Take one down and pass it around, 13 bottles of beer on the wall.
|
||||||
|
|
||||||
|
13 bottles of beer on the wall, 13 bottles of beer.
|
||||||
|
Take one down and pass it around, 12 bottles of beer on the wall.
|
||||||
|
|
||||||
|
12 bottles of beer on the wall, 12 bottles of beer.
|
||||||
|
Take one down and pass it around, 11 bottles of beer on the wall.
|
||||||
|
|
||||||
|
11 bottles of beer on the wall, 11 bottles of beer.
|
||||||
|
Take one down and pass it around, 10 bottles of beer on the wall.
|
||||||
|
|
||||||
|
10 bottles of beer on the wall, 10 bottles of beer.
|
||||||
|
Take one down and pass it around, 9 bottles of beer on the wall.
|
||||||
|
|
||||||
|
9 bottles of beer on the wall, 9 bottles of beer.
|
||||||
|
Take one down and pass it around, 8 bottles of beer on the wall.
|
||||||
|
|
||||||
|
8 bottles of beer on the wall, 8 bottles of beer.
|
||||||
|
Take one down and pass it around, 7 bottles of beer on the wall.
|
||||||
|
|
||||||
|
7 bottles of beer on the wall, 7 bottles of beer.
|
||||||
|
Take one down and pass it around, 6 bottles of beer on the wall.
|
||||||
|
|
||||||
|
6 bottles of beer on the wall, 6 bottles of beer.
|
||||||
|
Take one down and pass it around, 5 bottles of beer on the wall.
|
||||||
|
|
||||||
|
5 bottles of beer on the wall, 5 bottles of beer.
|
||||||
|
Take one down and pass it around, 4 bottles of beer on the wall.
|
||||||
|
|
||||||
|
4 bottles of beer on the wall, 4 bottles of beer.
|
||||||
|
Take one down and pass it around, 3 bottles of beer on the wall.
|
||||||
|
|
||||||
|
3 bottles of beer on the wall, 3 bottles of beer.
|
||||||
|
Take one down and pass it around, 2 bottles of beer on the wall.
|
||||||
|
|
||||||
|
2 bottles of beer on the wall, 2 bottles of beer.
|
||||||
|
Take one down and pass it around, 1 bottle of beer on the wall.
|
||||||
|
|
||||||
|
1 bottle of beer on the wall, 1 bottle of beer.
|
||||||
|
Take it down and pass it around, no more bottles of beer on the wall.
|
||||||
|
|
||||||
|
No more bottles of beer on the wall, no more bottles of beer.
|
||||||
|
Go to the store and buy some more, 99 bottles of beer on the wall.
|
||||||
|
```
|
||||||
|
|
||||||
|
## For bonus points
|
||||||
|
|
||||||
|
Did you get the tests passing and the code clean? If you want to, these
|
||||||
|
are some additional things you could try:
|
||||||
|
|
||||||
|
* Remove as much duplication as you possibly can.
|
||||||
|
* Optimize for readability, even if it means introducing duplication.
|
||||||
|
* If you've removed all the duplication, do you have a lot of
|
||||||
|
conditionals? Try replacing the conditionals with polymorphism, if it
|
||||||
|
applies in this language. How readable is it?
|
||||||
|
|
||||||
|
Then please share your thoughts in a comment on the submission. Did this
|
||||||
|
experiment make the code better? Worse? Did you learn anything from it?
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @EduardoBautista
|
||||||
|
|
||||||
|
### Contributed to by
|
||||||
|
|
||||||
|
- @andrewclarkson
|
||||||
|
- @ashleygwilliams
|
||||||
|
- @coriolinus
|
||||||
|
- @cwhakes
|
||||||
|
- @EduardoBautista
|
||||||
|
- @efx
|
||||||
|
- @ErikSchierboom
|
||||||
|
- @IanWhitney
|
||||||
|
- @kytrinyx
|
||||||
|
- @leoyvens
|
||||||
|
- @lutostag
|
||||||
|
- @mkantor
|
||||||
|
- @murlakatamenka
|
||||||
|
- @navossoc
|
||||||
|
- @nfiles
|
||||||
|
- @petertseng
|
||||||
|
- @pminten
|
||||||
|
- @razielgn
|
||||||
|
- @rofrol
|
||||||
|
- @stringparser
|
||||||
|
- @xakon
|
||||||
|
- @ZapAnton
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
Learn to Program by Chris Pine - http://pine.fm/LearnToProgram/?Chapter=06
|
||||||
23
beer-song/src/lib.rs
Normal file
23
beer-song/src/lib.rs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
const VERSES: [&str; 3] = [
|
||||||
|
"No more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n",
|
||||||
|
"1 bottle of beer on the wall, 1 bottle of beer.\nTake it down and pass it around, no more bottles of beer on the wall.\n",
|
||||||
|
"2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n"
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn verse(n: u32) -> String {
|
||||||
|
match n {
|
||||||
|
0 => VERSES[0].to_string(),
|
||||||
|
1 => VERSES[1].to_string(),
|
||||||
|
2 => VERSES[2].to_string(),
|
||||||
|
_ => format!("{0} bottles of beer on the wall, {0} bottles of beer.\n\
|
||||||
|
Take one down and pass it around, {1} bottles of beer on the wall.\n", n, n-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sing(start: u32, end: u32) -> String {
|
||||||
|
(end .. start + 1)
|
||||||
|
.rev()
|
||||||
|
.map(|n| verse(n))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n")
|
||||||
|
}
|
||||||
36
beer-song/tests/beer-song.rs
Normal file
36
beer-song/tests/beer-song.rs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
use beer_song as beer;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_verse_0() {
|
||||||
|
assert_eq!(beer::verse(0), "No more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_verse_1() {
|
||||||
|
assert_eq!(beer::verse(1), "1 bottle of beer on the wall, 1 bottle of beer.\nTake it down and pass it around, no more bottles of beer on the wall.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_verse_2() {
|
||||||
|
assert_eq!(beer::verse(2), "2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_verse_8() {
|
||||||
|
assert_eq!(beer::verse(8), "8 bottles of beer on the wall, 8 bottles of beer.\nTake one down and pass it around, 7 bottles of beer on the wall.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_song_8_6() {
|
||||||
|
assert_eq!(beer::sing(8, 6), "8 bottles of beer on the wall, 8 bottles of beer.\nTake one down and pass it around, 7 bottles of beer on the wall.\n\n7 bottles of beer on the wall, 7 bottles of beer.\nTake one down and pass it around, 6 bottles of beer on the wall.\n\n6 bottles of beer on the wall, 6 bottles of beer.\nTake one down and pass it around, 5 bottles of beer on the wall.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_song_3_0() {
|
||||||
|
assert_eq!(beer::sing(3, 0), "3 bottles of beer on the wall, 3 bottles of beer.\nTake one down and pass it around, 2 bottles of beer on the wall.\n\n2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n\n1 bottle of beer on the wall, 1 bottle of beer.\nTake it down and pass it around, no more bottles of beer on the wall.\n\nNo more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n");
|
||||||
|
}
|
||||||
50
bob/.exercism/config.json
Normal file
50
bob/.exercism/config.json
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"blurb": "Bob is a lackadaisical teenager. In conversation, his responses are very limited.",
|
||||||
|
"authors": [
|
||||||
|
"EduardoBautista"
|
||||||
|
],
|
||||||
|
"contributors": [
|
||||||
|
"andrewclarkson",
|
||||||
|
"ashleygwilliams",
|
||||||
|
"austinlyons",
|
||||||
|
"cjmochrie",
|
||||||
|
"cmccandless",
|
||||||
|
"coriolinus",
|
||||||
|
"cwhakes",
|
||||||
|
"EduardoBautista",
|
||||||
|
"efx",
|
||||||
|
"ErikSchierboom",
|
||||||
|
"etrepum",
|
||||||
|
"f3rn0s",
|
||||||
|
"IanWhitney",
|
||||||
|
"kytrinyx",
|
||||||
|
"leoyvens",
|
||||||
|
"lewisclement",
|
||||||
|
"lutostag",
|
||||||
|
"mkantor",
|
||||||
|
"nfiles",
|
||||||
|
"petertseng",
|
||||||
|
"pminten",
|
||||||
|
"rofrol",
|
||||||
|
"rpottsoh",
|
||||||
|
"stefanv",
|
||||||
|
"stringparser",
|
||||||
|
"vvv",
|
||||||
|
"xakon",
|
||||||
|
"ZapAnton"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"src/lib.rs",
|
||||||
|
"Cargo.toml"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/bob.rs"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.rs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"source": "Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial.",
|
||||||
|
"source_url": "http://pine.fm/LearnToProgram/?Chapter=06"
|
||||||
|
}
|
||||||
1
bob/.exercism/metadata.json
Normal file
1
bob/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"track":"rust","exercise":"bob","id":"2ba266860b29447aafa6e7938191d672","url":"https://exercism.org/tracks/rust/exercises/bob","handle":"ArthurDanjou","is_requester":true,"auto_approve":false}
|
||||||
8
bob/.gitignore
vendored
Normal file
8
bob/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
/target/
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
|
||||||
|
Cargo.lock
|
||||||
4
bob/Cargo.toml
Normal file
4
bob/Cargo.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[package]
|
||||||
|
edition = "2021"
|
||||||
|
name = "bob"
|
||||||
|
version = "1.6.0"
|
||||||
85
bob/HELP.md
Normal file
85
bob/HELP.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test
|
||||||
|
```
|
||||||
|
|
||||||
|
All but the first test have been ignored. After you get the first test to
|
||||||
|
pass, open the tests source file which is located in the `tests` directory
|
||||||
|
and remove the `#[ignore]` flag from the next test and get the tests to pass
|
||||||
|
again. Each separate test is a function with `#[test]` flag above it.
|
||||||
|
Continue, until you pass every test.
|
||||||
|
|
||||||
|
If you wish to run _only ignored_ tests without editing the tests source file, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are using Rust 1.51 or later, you can run _all_ tests with
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --include-ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a specific test, for example `some_test`, you can use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test
|
||||||
|
```
|
||||||
|
|
||||||
|
If the specific test is ignored, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about Rust tests refer to the online [test documentation][rust-tests].
|
||||||
|
|
||||||
|
[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit src/lib.rs Cargo.toml` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Rust track's documentation](https://exercism.org/docs/tracks/rust)
|
||||||
|
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
## Rust Installation
|
||||||
|
|
||||||
|
Refer to the [exercism help page][help-page] for Rust installation and learning
|
||||||
|
resources.
|
||||||
|
|
||||||
|
## Submitting the solution
|
||||||
|
|
||||||
|
Generally you should submit all files in which you implemented your solution (`src/lib.rs` in most cases). If you are using any external crates, please consider submitting the `Cargo.toml` file. This will make the review process faster and clearer.
|
||||||
|
|
||||||
|
## Feedback, Issues, Pull Requests
|
||||||
|
|
||||||
|
The GitHub [track repository][github] is the home for all of the Rust exercises. If you have feedback about an exercise, or want to help implement new exercises, head over there and create an issue. Members of the rust track team are happy to help!
|
||||||
|
|
||||||
|
If you want to know more about Exercism, take a look at the [contribution guide].
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
||||||
|
[help-page]: https://exercism.org/tracks/rust/learning
|
||||||
|
[github]: https://github.com/exercism/rust
|
||||||
|
[contribution guide]: https://exercism.org/docs/community/contributors
|
||||||
62
bob/README.md
Normal file
62
bob/README.md
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# Bob
|
||||||
|
|
||||||
|
Welcome to Bob on Exercism's Rust Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
|
||||||
|
|
||||||
|
Bob answers 'Sure.' if you ask him a question, such as "How are you?".
|
||||||
|
|
||||||
|
He answers 'Whoa, chill out!' if you YELL AT HIM (in all capitals).
|
||||||
|
|
||||||
|
He answers 'Calm down, I know what I'm doing!' if you yell a question at him.
|
||||||
|
|
||||||
|
He says 'Fine. Be that way!' if you address him without actually saying
|
||||||
|
anything.
|
||||||
|
|
||||||
|
He answers 'Whatever.' to anything else.
|
||||||
|
|
||||||
|
Bob's conversational partner is a purist when it comes to written communication and always follows normal rules regarding sentence punctuation in English.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @EduardoBautista
|
||||||
|
|
||||||
|
### Contributed to by
|
||||||
|
|
||||||
|
- @andrewclarkson
|
||||||
|
- @ashleygwilliams
|
||||||
|
- @austinlyons
|
||||||
|
- @cjmochrie
|
||||||
|
- @cmccandless
|
||||||
|
- @coriolinus
|
||||||
|
- @cwhakes
|
||||||
|
- @EduardoBautista
|
||||||
|
- @efx
|
||||||
|
- @ErikSchierboom
|
||||||
|
- @etrepum
|
||||||
|
- @f3rn0s
|
||||||
|
- @IanWhitney
|
||||||
|
- @kytrinyx
|
||||||
|
- @leoyvens
|
||||||
|
- @lewisclement
|
||||||
|
- @lutostag
|
||||||
|
- @mkantor
|
||||||
|
- @nfiles
|
||||||
|
- @petertseng
|
||||||
|
- @pminten
|
||||||
|
- @rofrol
|
||||||
|
- @rpottsoh
|
||||||
|
- @stefanv
|
||||||
|
- @stringparser
|
||||||
|
- @vvv
|
||||||
|
- @xakon
|
||||||
|
- @ZapAnton
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. - http://pine.fm/LearnToProgram/?Chapter=06
|
||||||
14
bob/src/lib.rs
Normal file
14
bob/src/lib.rs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
fn is_yelling(message: &str) -> bool {
|
||||||
|
let have_letters: bool = message.chars().filter(|c| c.is_alphabetic()).count() > 0;
|
||||||
|
message.to_uppercase() == message && have_letters
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reply(message: &str) -> &str {
|
||||||
|
match message.trim() {
|
||||||
|
m if m.trim().len() == 0 => "Fine. Be that way!",
|
||||||
|
m if m.ends_with("?") && is_yelling(m) => "Calm down, I know what I'm doing!",
|
||||||
|
m if m.ends_with("?") => "Sure.",
|
||||||
|
m if is_yelling(m) => "Whoa, chill out!",
|
||||||
|
_ => "Whatever."
|
||||||
|
}
|
||||||
|
}
|
||||||
190
bob/tests/bob.rs
Normal file
190
bob/tests/bob.rs
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
fn process_response_case(phrase: &str, expected_response: &str) {
|
||||||
|
assert_eq!(bob::reply(phrase), expected_response);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
/// stating something
|
||||||
|
fn test_stating_something() {
|
||||||
|
process_response_case("Tom-ay-to, tom-aaaah-to.", "Whatever.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// ending with whitespace
|
||||||
|
fn test_ending_with_whitespace() {
|
||||||
|
process_response_case("Okay if like my spacebar quite a bit? ", "Sure.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// shouting numbers
|
||||||
|
fn test_shouting_numbers() {
|
||||||
|
process_response_case("1, 2, 3 GO!", "Whoa, chill out!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// other whitespace
|
||||||
|
fn test_other_whitespace() {
|
||||||
|
process_response_case("\r\r ", "Fine. Be that way!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// shouting with special characters
|
||||||
|
fn test_shouting_with_special_characters() {
|
||||||
|
process_response_case(
|
||||||
|
"ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!",
|
||||||
|
"Whoa, chill out!",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// talking forcefully
|
||||||
|
fn test_talking_forcefully() {
|
||||||
|
process_response_case("Hi there!", "Whatever.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// prattling on
|
||||||
|
fn test_prattling_on() {
|
||||||
|
process_response_case("Wait! Hang on. Are you going to be OK?", "Sure.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// forceful question
|
||||||
|
fn test_forceful_question() {
|
||||||
|
process_response_case("WHAT'S GOING ON?", "Calm down, I know what I'm doing!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// shouting with no exclamation mark
|
||||||
|
fn test_shouting_with_no_exclamation_mark() {
|
||||||
|
process_response_case("I HATE THE DENTIST", "Whoa, chill out!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// asking gibberish
|
||||||
|
fn test_asking_gibberish() {
|
||||||
|
process_response_case("fffbbcbeab?", "Sure.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// question with no letters
|
||||||
|
fn test_question_with_no_letters() {
|
||||||
|
process_response_case("4?", "Sure.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// no letters
|
||||||
|
fn test_no_letters() {
|
||||||
|
process_response_case("1, 2, 3", "Whatever.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// statement containing question mark
|
||||||
|
fn test_statement_containing_question_mark() {
|
||||||
|
process_response_case("Ending with ? means a question.", "Whatever.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//NEW
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// multiple line question
|
||||||
|
fn test_multiple_line_question() {
|
||||||
|
process_response_case(
|
||||||
|
"\rDoes this cryogenic chamber make me look fat?\rNo.",
|
||||||
|
"Whatever.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// non-question ending with whitespace
|
||||||
|
fn test_nonquestion_ending_with_whitespace() {
|
||||||
|
process_response_case(
|
||||||
|
"This is a statement ending with whitespace ",
|
||||||
|
"Whatever.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// shouting
|
||||||
|
fn test_shouting() {
|
||||||
|
process_response_case("WATCH OUT!", "Whoa, chill out!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// non-letters with question
|
||||||
|
fn test_nonletters_with_question() {
|
||||||
|
process_response_case(":) ?", "Sure.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// shouting gibberish
|
||||||
|
fn test_shouting_gibberish() {
|
||||||
|
process_response_case("FCECDFCAAB", "Whoa, chill out!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// asking a question
|
||||||
|
fn test_asking_a_question() {
|
||||||
|
process_response_case("Does this cryogenic chamber make me look fat?", "Sure.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// asking a numeric question
|
||||||
|
fn test_asking_a_numeric_question() {
|
||||||
|
process_response_case("You are, what, like 15?", "Sure.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// silence
|
||||||
|
fn test_silence() {
|
||||||
|
process_response_case("", "Fine. Be that way!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// starting with whitespace
|
||||||
|
fn test_starting_with_whitespace() {
|
||||||
|
process_response_case(" hmmmmmmm...", "Whatever.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// using acronyms in regular speech
|
||||||
|
fn test_using_acronyms_in_regular_speech() {
|
||||||
|
process_response_case(
|
||||||
|
"It's OK if you don't want to go work for NASA.",
|
||||||
|
"Whatever.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// alternate silence
|
||||||
|
fn test_alternate_silence() {
|
||||||
|
process_response_case(" ", "Fine. Be that way!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
/// prolonged silence
|
||||||
|
fn test_prolonged_silence() {
|
||||||
|
process_response_case(" ", "Fine. Be that way!");
|
||||||
|
}
|
||||||
43
clock/.exercism/config.json
Normal file
43
clock/.exercism/config.json
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"blurb": "Implement a clock that handles times without dates.",
|
||||||
|
"authors": [
|
||||||
|
"sacherjj"
|
||||||
|
],
|
||||||
|
"contributors": [
|
||||||
|
"attilahorvath",
|
||||||
|
"coriolinus",
|
||||||
|
"cwhakes",
|
||||||
|
"danieljl",
|
||||||
|
"eddyp",
|
||||||
|
"efx",
|
||||||
|
"ErikSchierboom",
|
||||||
|
"felix91gr",
|
||||||
|
"kunaltyagi",
|
||||||
|
"lutostag",
|
||||||
|
"nfiles",
|
||||||
|
"petertseng",
|
||||||
|
"rofrol",
|
||||||
|
"shaaraddalvi",
|
||||||
|
"stringparser",
|
||||||
|
"tmccombs",
|
||||||
|
"xakon",
|
||||||
|
"ZapAnton"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"src/lib.rs",
|
||||||
|
"Cargo.toml"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/clock.rs"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.rs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"source": "Pairing session with Erin Drummond",
|
||||||
|
"source_url": "https://twitter.com/ebdrummond",
|
||||||
|
"custom": {
|
||||||
|
"allowed-to-not-compile": "Stub doesn't compile because there is no to_string() implementation. This exercise is an introduction to derived and self-implemented traits, therefore adding template for a trait would reduce student learning."
|
||||||
|
}
|
||||||
|
}
|
||||||
1
clock/.exercism/metadata.json
Normal file
1
clock/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"track":"rust","exercise":"clock","id":"bcfb7c3bb06e42a0921d4975f51a864f","url":"https://exercism.org/tracks/rust/exercises/clock","handle":"ArthurDanjou","is_requester":true,"auto_approve":false}
|
||||||
8
clock/.gitignore
vendored
Normal file
8
clock/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
/target/
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
|
||||||
|
Cargo.lock
|
||||||
6
clock/Cargo.toml
Normal file
6
clock/Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
edition = "2021"
|
||||||
|
name = "clock"
|
||||||
|
version = "2.4.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
85
clock/HELP.md
Normal file
85
clock/HELP.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test
|
||||||
|
```
|
||||||
|
|
||||||
|
All but the first test have been ignored. After you get the first test to
|
||||||
|
pass, open the tests source file which is located in the `tests` directory
|
||||||
|
and remove the `#[ignore]` flag from the next test and get the tests to pass
|
||||||
|
again. Each separate test is a function with `#[test]` flag above it.
|
||||||
|
Continue, until you pass every test.
|
||||||
|
|
||||||
|
If you wish to run _only ignored_ tests without editing the tests source file, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are using Rust 1.51 or later, you can run _all_ tests with
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --include-ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a specific test, for example `some_test`, you can use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test
|
||||||
|
```
|
||||||
|
|
||||||
|
If the specific test is ignored, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about Rust tests refer to the online [test documentation][rust-tests].
|
||||||
|
|
||||||
|
[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit src/lib.rs Cargo.toml` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Rust track's documentation](https://exercism.org/docs/tracks/rust)
|
||||||
|
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
## Rust Installation
|
||||||
|
|
||||||
|
Refer to the [exercism help page][help-page] for Rust installation and learning
|
||||||
|
resources.
|
||||||
|
|
||||||
|
## Submitting the solution
|
||||||
|
|
||||||
|
Generally you should submit all files in which you implemented your solution (`src/lib.rs` in most cases). If you are using any external crates, please consider submitting the `Cargo.toml` file. This will make the review process faster and clearer.
|
||||||
|
|
||||||
|
## Feedback, Issues, Pull Requests
|
||||||
|
|
||||||
|
The GitHub [track repository][github] is the home for all of the Rust exercises. If you have feedback about an exercise, or want to help implement new exercises, head over there and create an issue. Members of the rust track team are happy to help!
|
||||||
|
|
||||||
|
If you want to know more about Exercism, take a look at the [contribution guide].
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
||||||
|
[help-page]: https://exercism.org/tracks/rust/learning
|
||||||
|
[github]: https://github.com/exercism/rust
|
||||||
|
[contribution guide]: https://exercism.org/docs/community/contributors
|
||||||
57
clock/README.md
Normal file
57
clock/README.md
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# Clock
|
||||||
|
|
||||||
|
Welcome to Clock on Exercism's Rust Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Implement a clock that handles times without dates.
|
||||||
|
|
||||||
|
You should be able to add and subtract minutes to it.
|
||||||
|
|
||||||
|
Two clocks that represent the same time should be equal to each other.
|
||||||
|
|
||||||
|
You will also need to implement `.to_string()` for the `Clock` struct. We will be using this to display the Clock's state. You can either do it via implementing it directly or using the [Display trait](https://doc.rust-lang.org/std/fmt/trait.Display.html).
|
||||||
|
|
||||||
|
Did you implement `.to_string()` for the `Clock` struct?
|
||||||
|
|
||||||
|
If so, try implementing the
|
||||||
|
[Display trait](https://doc.rust-lang.org/std/fmt/trait.Display.html) for `Clock` instead.
|
||||||
|
|
||||||
|
Traits allow for a common way to implement functionality for various types.
|
||||||
|
|
||||||
|
For additional learning, consider how you might implement `String::from` for the `Clock` type.
|
||||||
|
You don't have to actually implement this—it's redundant with `Display`, which is generally the
|
||||||
|
better choice when the destination type is `String`—but it's useful to have a few type-conversion
|
||||||
|
traits in your toolkit.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @sacherjj
|
||||||
|
|
||||||
|
### Contributed to by
|
||||||
|
|
||||||
|
- @attilahorvath
|
||||||
|
- @coriolinus
|
||||||
|
- @cwhakes
|
||||||
|
- @danieljl
|
||||||
|
- @eddyp
|
||||||
|
- @efx
|
||||||
|
- @ErikSchierboom
|
||||||
|
- @felix91gr
|
||||||
|
- @kunaltyagi
|
||||||
|
- @lutostag
|
||||||
|
- @nfiles
|
||||||
|
- @petertseng
|
||||||
|
- @rofrol
|
||||||
|
- @shaaraddalvi
|
||||||
|
- @stringparser
|
||||||
|
- @tmccombs
|
||||||
|
- @xakon
|
||||||
|
- @ZapAnton
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
Pairing session with Erin Drummond - https://twitter.com/ebdrummond
|
||||||
39
clock/src/lib.rs
Normal file
39
clock/src/lib.rs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#[derive(Eq, PartialEq, Debug)]
|
||||||
|
pub struct Clock {
|
||||||
|
minutes: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
const MINUTES_IN_AN_HOUR: i32 = 60;
|
||||||
|
const HOURS_IN_A_DAY: i32 = 24;
|
||||||
|
const MINUTES_IN_A_DAY: i32 = HOURS_IN_A_DAY * MINUTES_IN_AN_HOUR;
|
||||||
|
|
||||||
|
impl ToString for Clock {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
format!("{:02}:{:02}", self.hours(), self.minutes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clock {
|
||||||
|
pub fn new(hours: i32, minutes: i32) -> Self {
|
||||||
|
Self {
|
||||||
|
minutes: Self::as_minutes(hours, minutes),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_minutes(&self, minutes: i32) -> Self {
|
||||||
|
Self::new(0, self.minutes + minutes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_minutes(hours: i32, minutes: i32) -> i32 {
|
||||||
|
((hours * MINUTES_IN_AN_HOUR + minutes) % MINUTES_IN_A_DAY + MINUTES_IN_A_DAY)
|
||||||
|
% MINUTES_IN_A_DAY
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hours(&self) -> i32 {
|
||||||
|
self.minutes / MINUTES_IN_AN_HOUR
|
||||||
|
}
|
||||||
|
|
||||||
|
fn minutes(&self) -> i32 {
|
||||||
|
self.minutes % MINUTES_IN_AN_HOUR
|
||||||
|
}
|
||||||
|
}
|
||||||
352
clock/tests/clock.rs
Normal file
352
clock/tests/clock.rs
Normal file
@@ -0,0 +1,352 @@
|
|||||||
|
use clock::Clock;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Clock Creation
|
||||||
|
//
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_on_the_hour() {
|
||||||
|
assert_eq!(Clock::new(8, 0).to_string(), "08:00");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_past_the_hour() {
|
||||||
|
assert_eq!(Clock::new(11, 9).to_string(), "11:09");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_midnight_is_zero_hours() {
|
||||||
|
assert_eq!(Clock::new(24, 0).to_string(), "00:00");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_hour_rolls_over() {
|
||||||
|
assert_eq!(Clock::new(25, 0).to_string(), "01:00");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_hour_rolls_over_continuously() {
|
||||||
|
assert_eq!(Clock::new(100, 0).to_string(), "04:00");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_sixty_minutes_is_next_hour() {
|
||||||
|
assert_eq!(Clock::new(1, 60).to_string(), "02:00");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_minutes_roll_over() {
|
||||||
|
assert_eq!(Clock::new(0, 160).to_string(), "02:40");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_minutes_roll_over_continuously() {
|
||||||
|
assert_eq!(Clock::new(0, 1723).to_string(), "04:43");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_hours_and_minutes_roll_over() {
|
||||||
|
assert_eq!(Clock::new(25, 160).to_string(), "03:40");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_hours_and_minutes_roll_over_continuously() {
|
||||||
|
assert_eq!(Clock::new(201, 3001).to_string(), "11:01");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_hours_and_minutes_roll_over_to_exactly_midnight() {
|
||||||
|
assert_eq!(Clock::new(72, 8640).to_string(), "00:00");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_negative_hour() {
|
||||||
|
assert_eq!(Clock::new(-1, 15).to_string(), "23:15");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_negative_hour_roll_over() {
|
||||||
|
assert_eq!(Clock::new(-25, 00).to_string(), "23:00");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_negative_hour_roll_over_continuously() {
|
||||||
|
assert_eq!(Clock::new(-91, 00).to_string(), "05:00");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_negative_minutes() {
|
||||||
|
assert_eq!(Clock::new(1, -40).to_string(), "00:20");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_negative_minutes_roll_over() {
|
||||||
|
assert_eq!(Clock::new(1, -160).to_string(), "22:20");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_negative_minutes_roll_over_continuously() {
|
||||||
|
assert_eq!(Clock::new(1, -4820).to_string(), "16:40");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_negative_sixty_minutes_is_prev_hour() {
|
||||||
|
assert_eq!(Clock::new(2, -60).to_string(), "01:00");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_negative_one_twenty_minutes_is_two_prev_hours() {
|
||||||
|
assert_eq!(Clock::new(1, -120).to_string(), "23:00");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_negative_hour_and_minutes_both_roll_over() {
|
||||||
|
assert_eq!(Clock::new(-25, -160).to_string(), "20:20");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_negative_hour_and_minutes_both_roll_over_continuously() {
|
||||||
|
assert_eq!(Clock::new(-121, -5810).to_string(), "22:10");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_zero_hour_and_negative_minutes() {
|
||||||
|
assert_eq!(Clock::new(0, -22).to_string(), "23:38");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Clock Math
|
||||||
|
//
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_add_minutes() {
|
||||||
|
let clock = Clock::new(10, 0).add_minutes(3);
|
||||||
|
assert_eq!(clock.to_string(), "10:03");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_add_no_minutes() {
|
||||||
|
let clock = Clock::new(6, 41).add_minutes(0);
|
||||||
|
assert_eq!(clock.to_string(), "06:41");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_add_to_next_hour() {
|
||||||
|
let clock = Clock::new(0, 45).add_minutes(40);
|
||||||
|
assert_eq!(clock.to_string(), "01:25");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_add_more_than_one_hour() {
|
||||||
|
let clock = Clock::new(10, 0).add_minutes(61);
|
||||||
|
assert_eq!(clock.to_string(), "11:01");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_add_more_than_two_hours_with_carry() {
|
||||||
|
let clock = Clock::new(0, 45).add_minutes(160);
|
||||||
|
assert_eq!(clock.to_string(), "03:25");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_add_across_midnight() {
|
||||||
|
let clock = Clock::new(23, 59).add_minutes(2);
|
||||||
|
assert_eq!(clock.to_string(), "00:01");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_add_more_than_one_day() {
|
||||||
|
let clock = Clock::new(5, 32).add_minutes(1500);
|
||||||
|
assert_eq!(clock.to_string(), "06:32");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_add_more_than_two_days() {
|
||||||
|
let clock = Clock::new(1, 1).add_minutes(3500);
|
||||||
|
assert_eq!(clock.to_string(), "11:21");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_subtract_minutes() {
|
||||||
|
let clock = Clock::new(10, 3).add_minutes(-3);
|
||||||
|
assert_eq!(clock.to_string(), "10:00");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_subtract_to_previous_hour() {
|
||||||
|
let clock = Clock::new(10, 3).add_minutes(-30);
|
||||||
|
assert_eq!(clock.to_string(), "09:33");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_subtract_more_than_an_hour() {
|
||||||
|
let clock = Clock::new(10, 3).add_minutes(-70);
|
||||||
|
assert_eq!(clock.to_string(), "08:53");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_subtract_across_midnight() {
|
||||||
|
let clock = Clock::new(0, 3).add_minutes(-4);
|
||||||
|
assert_eq!(clock.to_string(), "23:59");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_subtract_more_than_two_hours() {
|
||||||
|
let clock = Clock::new(0, 0).add_minutes(-160);
|
||||||
|
assert_eq!(clock.to_string(), "21:20");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_subtract_more_than_two_hours_with_borrow() {
|
||||||
|
let clock = Clock::new(6, 15).add_minutes(-160);
|
||||||
|
assert_eq!(clock.to_string(), "03:35");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_subtract_more_than_one_day() {
|
||||||
|
let clock = Clock::new(5, 32).add_minutes(-1500);
|
||||||
|
assert_eq!(clock.to_string(), "04:32");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_subtract_more_than_two_days() {
|
||||||
|
let clock = Clock::new(2, 20).add_minutes(-3000);
|
||||||
|
assert_eq!(clock.to_string(), "00:20");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test Equality
|
||||||
|
//
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_clocks_for_equality() {
|
||||||
|
assert_eq!(Clock::new(15, 37), Clock::new(15, 37));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_clocks_a_minute_apart() {
|
||||||
|
assert_ne!(Clock::new(15, 36), Clock::new(15, 37));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_clocks_an_hour_apart() {
|
||||||
|
assert_ne!(Clock::new(14, 37), Clock::new(15, 37));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_clocks_with_hour_overflow() {
|
||||||
|
assert_eq!(Clock::new(10, 37), Clock::new(34, 37));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_clocks_with_hour_overflow_by_several_days() {
|
||||||
|
assert_eq!(Clock::new(99, 11), Clock::new(3, 11));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_clocks_with_negative_hour() {
|
||||||
|
assert_eq!(Clock::new(-2, 40), Clock::new(22, 40));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_clocks_with_negative_hour_that_wraps() {
|
||||||
|
assert_eq!(Clock::new(-31, 3), Clock::new(17, 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_clocks_with_negative_hour_that_wraps_multiple_times() {
|
||||||
|
assert_eq!(Clock::new(-83, 49), Clock::new(13, 49));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_clocks_with_minutes_overflow() {
|
||||||
|
assert_eq!(Clock::new(0, 1441), Clock::new(0, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_clocks_with_minutes_overflow_by_several_days() {
|
||||||
|
assert_eq!(Clock::new(2, 4322), Clock::new(2, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_clocks_with_negative_minute() {
|
||||||
|
assert_eq!(Clock::new(3, -20), Clock::new(2, 40));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_clocks_with_negative_minute_that_wraps() {
|
||||||
|
assert_eq!(Clock::new(5, -1490), Clock::new(4, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_clocks_with_negative_minute_that_wraps_multiple() {
|
||||||
|
assert_eq!(Clock::new(6, -4305), Clock::new(6, 15));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_clocks_with_negative_hours_and_minutes() {
|
||||||
|
assert_eq!(Clock::new(-12, -268), Clock::new(7, 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_clocks_with_negative_hours_and_minutes_that_wrap() {
|
||||||
|
assert_eq!(Clock::new(-54, -11_513), Clock::new(18, 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_compare_full_clock_and_zeroed_clock() {
|
||||||
|
assert_eq!(Clock::new(24, 0), Clock::new(0, 0));
|
||||||
|
}
|
||||||
45
gigasecond/.exercism/config.json
Normal file
45
gigasecond/.exercism/config.json
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"blurb": "Given a moment, determine the moment that would be after a gigasecond has passed.",
|
||||||
|
"authors": [
|
||||||
|
"IanWhitney"
|
||||||
|
],
|
||||||
|
"contributors": [
|
||||||
|
"andy5995",
|
||||||
|
"ashleygwilliams",
|
||||||
|
"cbzehner",
|
||||||
|
"coriolinus",
|
||||||
|
"cwhakes",
|
||||||
|
"EduardoBautista",
|
||||||
|
"efx",
|
||||||
|
"ErikSchierboom",
|
||||||
|
"houhoulis",
|
||||||
|
"IanWhitney",
|
||||||
|
"janczer",
|
||||||
|
"leoyvens",
|
||||||
|
"lutostag",
|
||||||
|
"mkantor",
|
||||||
|
"nfiles",
|
||||||
|
"NieDzejkob",
|
||||||
|
"ocstl",
|
||||||
|
"petertseng",
|
||||||
|
"rofrol",
|
||||||
|
"sacherjj",
|
||||||
|
"stringparser",
|
||||||
|
"xakon",
|
||||||
|
"ZapAnton"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"src/lib.rs",
|
||||||
|
"Cargo.toml"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/gigasecond.rs"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.rs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"source": "Chapter 9 in Chris Pine's online Learn to Program tutorial.",
|
||||||
|
"source_url": "http://pine.fm/LearnToProgram/?Chapter=09"
|
||||||
|
}
|
||||||
1
gigasecond/.exercism/metadata.json
Normal file
1
gigasecond/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"track":"rust","exercise":"gigasecond","id":"496981dcd7204a27be917dbc863f0a87","url":"https://exercism.org/tracks/rust/exercises/gigasecond","handle":"ArthurDanjou","is_requester":true,"auto_approve":false}
|
||||||
8
gigasecond/.gitignore
vendored
Normal file
8
gigasecond/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
/target/
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
|
||||||
|
Cargo.lock
|
||||||
7
gigasecond/Cargo.toml
Normal file
7
gigasecond/Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[package]
|
||||||
|
edition = "2021"
|
||||||
|
name = "gigasecond"
|
||||||
|
version = "2.0.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
time = "0.3"
|
||||||
85
gigasecond/HELP.md
Normal file
85
gigasecond/HELP.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test
|
||||||
|
```
|
||||||
|
|
||||||
|
All but the first test have been ignored. After you get the first test to
|
||||||
|
pass, open the tests source file which is located in the `tests` directory
|
||||||
|
and remove the `#[ignore]` flag from the next test and get the tests to pass
|
||||||
|
again. Each separate test is a function with `#[test]` flag above it.
|
||||||
|
Continue, until you pass every test.
|
||||||
|
|
||||||
|
If you wish to run _only ignored_ tests without editing the tests source file, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are using Rust 1.51 or later, you can run _all_ tests with
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --include-ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a specific test, for example `some_test`, you can use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test
|
||||||
|
```
|
||||||
|
|
||||||
|
If the specific test is ignored, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about Rust tests refer to the online [test documentation][rust-tests].
|
||||||
|
|
||||||
|
[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit src/lib.rs Cargo.toml` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Rust track's documentation](https://exercism.org/docs/tracks/rust)
|
||||||
|
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
## Rust Installation
|
||||||
|
|
||||||
|
Refer to the [exercism help page][help-page] for Rust installation and learning
|
||||||
|
resources.
|
||||||
|
|
||||||
|
## Submitting the solution
|
||||||
|
|
||||||
|
Generally you should submit all files in which you implemented your solution (`src/lib.rs` in most cases). If you are using any external crates, please consider submitting the `Cargo.toml` file. This will make the review process faster and clearer.
|
||||||
|
|
||||||
|
## Feedback, Issues, Pull Requests
|
||||||
|
|
||||||
|
The GitHub [track repository][github] is the home for all of the Rust exercises. If you have feedback about an exercise, or want to help implement new exercises, head over there and create an issue. Members of the rust track team are happy to help!
|
||||||
|
|
||||||
|
If you want to know more about Exercism, take a look at the [contribution guide].
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
||||||
|
[help-page]: https://exercism.org/tracks/rust/learning
|
||||||
|
[github]: https://github.com/exercism/rust
|
||||||
|
[contribution guide]: https://exercism.org/docs/community/contributors
|
||||||
49
gigasecond/README.md
Normal file
49
gigasecond/README.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# Gigasecond
|
||||||
|
|
||||||
|
Welcome to Gigasecond on Exercism's Rust Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Given a moment, determine the moment that would be after a gigasecond
|
||||||
|
has passed.
|
||||||
|
|
||||||
|
A gigasecond is 10^9 (1,000,000,000) seconds.
|
||||||
|
|
||||||
|
If you're unsure what operations you can perform on `PrimitiveDateTime` take a look at the [time crate](https://docs.rs/time) which is listed as a dependency in the `Cargo.toml` file for this exercise.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @IanWhitney
|
||||||
|
|
||||||
|
### Contributed to by
|
||||||
|
|
||||||
|
- @andy5995
|
||||||
|
- @ashleygwilliams
|
||||||
|
- @cbzehner
|
||||||
|
- @coriolinus
|
||||||
|
- @cwhakes
|
||||||
|
- @EduardoBautista
|
||||||
|
- @efx
|
||||||
|
- @ErikSchierboom
|
||||||
|
- @houhoulis
|
||||||
|
- @IanWhitney
|
||||||
|
- @janczer
|
||||||
|
- @leoyvens
|
||||||
|
- @lutostag
|
||||||
|
- @mkantor
|
||||||
|
- @nfiles
|
||||||
|
- @NieDzejkob
|
||||||
|
- @ocstl
|
||||||
|
- @petertseng
|
||||||
|
- @rofrol
|
||||||
|
- @sacherjj
|
||||||
|
- @stringparser
|
||||||
|
- @xakon
|
||||||
|
- @ZapAnton
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
Chapter 9 in Chris Pine's online Learn to Program tutorial. - http://pine.fm/LearnToProgram/?Chapter=09
|
||||||
7
gigasecond/src/lib.rs
Normal file
7
gigasecond/src/lib.rs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
use time::{Duration, PrimitiveDateTime as DateTime};
|
||||||
|
|
||||||
|
// Returns a DateTime one billion seconds after start.
|
||||||
|
pub fn after(start: DateTime) -> DateTime {
|
||||||
|
// Add 10 seconds to start
|
||||||
|
start + Duration::seconds(1_000_000_000)
|
||||||
|
}
|
||||||
52
gigasecond/tests/gigasecond.rs
Normal file
52
gigasecond/tests/gigasecond.rs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
use time::PrimitiveDateTime as DateTime;
|
||||||
|
|
||||||
|
/// Create a datetime from the given numeric point in time.
|
||||||
|
///
|
||||||
|
/// Panics if any field is invalid.
|
||||||
|
fn dt(year: i32, month: u8, day: u8, hour: u8, minute: u8, second: u8) -> DateTime {
|
||||||
|
use time::{Date, Time};
|
||||||
|
|
||||||
|
DateTime::new(
|
||||||
|
Date::from_calendar_date(year, month.try_into().unwrap(), day).unwrap(),
|
||||||
|
Time::from_hms(hour, minute, second).unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_date() {
|
||||||
|
let start_date = dt(2011, 4, 25, 0, 0, 0);
|
||||||
|
|
||||||
|
assert_eq!(gigasecond::after(start_date), dt(2043, 1, 1, 1, 46, 40));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_another_date() {
|
||||||
|
let start_date = dt(1977, 6, 13, 0, 0, 0);
|
||||||
|
|
||||||
|
assert_eq!(gigasecond::after(start_date), dt(2009, 2, 19, 1, 46, 40));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_third_date() {
|
||||||
|
let start_date = dt(1959, 7, 19, 0, 0, 0);
|
||||||
|
|
||||||
|
assert_eq!(gigasecond::after(start_date), dt(1991, 3, 27, 1, 46, 40));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_datetime() {
|
||||||
|
let start_date = dt(2015, 1, 24, 22, 0, 0);
|
||||||
|
|
||||||
|
assert_eq!(gigasecond::after(start_date), dt(2046, 10, 2, 23, 46, 40));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_another_datetime() {
|
||||||
|
let start_date = dt(2015, 1, 24, 23, 59, 59);
|
||||||
|
|
||||||
|
assert_eq!(gigasecond::after(start_date), dt(2046, 10, 3, 1, 46, 39));
|
||||||
|
}
|
||||||
43
grade-school/.exercism/config.json
Normal file
43
grade-school/.exercism/config.json
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"blurb": "Given students' names along with the grade that they are in, create a roster for the school",
|
||||||
|
"authors": [
|
||||||
|
"EduardoBautista"
|
||||||
|
],
|
||||||
|
"contributors": [
|
||||||
|
"andrewclarkson",
|
||||||
|
"ashleygwilliams",
|
||||||
|
"coriolinus",
|
||||||
|
"cwhakes",
|
||||||
|
"EduardoBautista",
|
||||||
|
"efx",
|
||||||
|
"ErikSchierboom",
|
||||||
|
"ffflorian",
|
||||||
|
"IanWhitney",
|
||||||
|
"kytrinyx",
|
||||||
|
"lpil",
|
||||||
|
"lutostag",
|
||||||
|
"navossoc",
|
||||||
|
"nfiles",
|
||||||
|
"petertseng",
|
||||||
|
"pminten",
|
||||||
|
"rofrol",
|
||||||
|
"stevejb71",
|
||||||
|
"stringparser",
|
||||||
|
"xakon",
|
||||||
|
"ZapAnton"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"src/lib.rs",
|
||||||
|
"Cargo.toml"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/grade-school.rs"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.rs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"source": "A pairing session with Phil Battos at gSchool",
|
||||||
|
"source_url": "http://gschool.it"
|
||||||
|
}
|
||||||
1
grade-school/.exercism/metadata.json
Normal file
1
grade-school/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"track":"rust","exercise":"grade-school","id":"5d0ccb19b5f0468d9f98154f1727365a","url":"https://exercism.org/tracks/rust/exercises/grade-school","handle":"ArthurDanjou","is_requester":true,"auto_approve":false}
|
||||||
8
grade-school/.gitignore
vendored
Normal file
8
grade-school/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
/target/
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
|
||||||
|
Cargo.lock
|
||||||
4
grade-school/Cargo.toml
Normal file
4
grade-school/Cargo.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[package]
|
||||||
|
edition = "2021"
|
||||||
|
name = "grade-school"
|
||||||
|
version = "0.0.0"
|
||||||
85
grade-school/HELP.md
Normal file
85
grade-school/HELP.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test
|
||||||
|
```
|
||||||
|
|
||||||
|
All but the first test have been ignored. After you get the first test to
|
||||||
|
pass, open the tests source file which is located in the `tests` directory
|
||||||
|
and remove the `#[ignore]` flag from the next test and get the tests to pass
|
||||||
|
again. Each separate test is a function with `#[test]` flag above it.
|
||||||
|
Continue, until you pass every test.
|
||||||
|
|
||||||
|
If you wish to run _only ignored_ tests without editing the tests source file, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are using Rust 1.51 or later, you can run _all_ tests with
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --include-ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a specific test, for example `some_test`, you can use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test
|
||||||
|
```
|
||||||
|
|
||||||
|
If the specific test is ignored, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about Rust tests refer to the online [test documentation][rust-tests].
|
||||||
|
|
||||||
|
[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit src/lib.rs Cargo.toml` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Rust track's documentation](https://exercism.org/docs/tracks/rust)
|
||||||
|
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
## Rust Installation
|
||||||
|
|
||||||
|
Refer to the [exercism help page][help-page] for Rust installation and learning
|
||||||
|
resources.
|
||||||
|
|
||||||
|
## Submitting the solution
|
||||||
|
|
||||||
|
Generally you should submit all files in which you implemented your solution (`src/lib.rs` in most cases). If you are using any external crates, please consider submitting the `Cargo.toml` file. This will make the review process faster and clearer.
|
||||||
|
|
||||||
|
## Feedback, Issues, Pull Requests
|
||||||
|
|
||||||
|
The GitHub [track repository][github] is the home for all of the Rust exercises. If you have feedback about an exercise, or want to help implement new exercises, head over there and create an issue. Members of the rust track team are happy to help!
|
||||||
|
|
||||||
|
If you want to know more about Exercism, take a look at the [contribution guide].
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
||||||
|
[help-page]: https://exercism.org/tracks/rust/learning
|
||||||
|
[github]: https://github.com/exercism/rust
|
||||||
|
[contribution guide]: https://exercism.org/docs/community/contributors
|
||||||
77
grade-school/README.md
Normal file
77
grade-school/README.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# Grade School
|
||||||
|
|
||||||
|
Welcome to Grade School on Exercism's Rust Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Given students' names along with the grade that they are in, create a roster
|
||||||
|
for the school.
|
||||||
|
|
||||||
|
In the end, you should be able to:
|
||||||
|
|
||||||
|
- Add a student's name to the roster for a grade
|
||||||
|
- "Add Jim to grade 2."
|
||||||
|
- "OK."
|
||||||
|
- Get a list of all students enrolled in a grade
|
||||||
|
- "Which students are in grade 2?"
|
||||||
|
- "We've only got Jim just now."
|
||||||
|
- Get a sorted list of all students in all grades. Grades should sort
|
||||||
|
as 1, 2, 3, etc., and students within a grade should be sorted
|
||||||
|
alphabetically by name.
|
||||||
|
- "Who all is enrolled in school right now?"
|
||||||
|
- "Let me think. We have
|
||||||
|
Anna, Barb, and Charlie in grade 1,
|
||||||
|
Alex, Peter, and Zoe in grade 2
|
||||||
|
and Jim in grade 5.
|
||||||
|
So the answer is: Anna, Barb, Charlie, Alex, Peter, Zoe and Jim"
|
||||||
|
|
||||||
|
Note that all our students only have one name. (It's a small town, what
|
||||||
|
do you want?)
|
||||||
|
|
||||||
|
## For bonus points
|
||||||
|
|
||||||
|
Did you get the tests passing and the code clean? If you want to, these
|
||||||
|
are some additional things you could try:
|
||||||
|
|
||||||
|
- If you're working in a language with mutable data structures and your
|
||||||
|
implementation allows outside code to mutate the school's internal DB
|
||||||
|
directly, see if you can prevent this. Feel free to introduce additional
|
||||||
|
tests.
|
||||||
|
|
||||||
|
Then please share your thoughts in a comment on the submission. Did this
|
||||||
|
experiment make the code better? Worse? Did you learn anything from it?
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @EduardoBautista
|
||||||
|
|
||||||
|
### Contributed to by
|
||||||
|
|
||||||
|
- @andrewclarkson
|
||||||
|
- @ashleygwilliams
|
||||||
|
- @coriolinus
|
||||||
|
- @cwhakes
|
||||||
|
- @EduardoBautista
|
||||||
|
- @efx
|
||||||
|
- @ErikSchierboom
|
||||||
|
- @ffflorian
|
||||||
|
- @IanWhitney
|
||||||
|
- @kytrinyx
|
||||||
|
- @lpil
|
||||||
|
- @lutostag
|
||||||
|
- @navossoc
|
||||||
|
- @nfiles
|
||||||
|
- @petertseng
|
||||||
|
- @pminten
|
||||||
|
- @rofrol
|
||||||
|
- @stevejb71
|
||||||
|
- @stringparser
|
||||||
|
- @xakon
|
||||||
|
- @ZapAnton
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
A pairing session with Phil Battos at gSchool - http://gschool.it
|
||||||
46
grade-school/src/lib.rs
Normal file
46
grade-school/src/lib.rs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
// This annotation prevents Clippy from warning us that `School` has a
|
||||||
|
// `fn new()` with no arguments, but doesn't implement the `Default` trait.
|
||||||
|
//
|
||||||
|
// Normally, it's good practice to just do what Clippy tells you, but in this
|
||||||
|
// case, we want to keep things relatively simple. The `Default` trait is not the point
|
||||||
|
// of this exercise.
|
||||||
|
#[allow(clippy::new_without_default)]
|
||||||
|
pub struct School {
|
||||||
|
student_grades: HashMap<u32, Vec<String>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl School {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
student_grades: HashMap::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(&mut self, grade: u32, student: &str) {
|
||||||
|
self.student_grades
|
||||||
|
.entry(grade)
|
||||||
|
.or_insert(Vec::new())
|
||||||
|
.push(student.to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn grades(&self) -> Vec<u32> {
|
||||||
|
let mut grades = self.student_grades.keys().cloned().collect::<Vec<u32>>();
|
||||||
|
grades.sort();
|
||||||
|
grades
|
||||||
|
}
|
||||||
|
|
||||||
|
// If `grade` returned a reference, `School` would be forced to keep a `Vec<String>`
|
||||||
|
// internally to lend out. By returning an owned vector of owned `String`s instead,
|
||||||
|
// the internal structure can be completely arbitrary. The tradeoff is that some data
|
||||||
|
// must be copied each time `grade` is called.
|
||||||
|
pub fn grade(&self, grade: u32) -> Vec<String> {
|
||||||
|
let mut students_for_grade = match self.student_grades.get(&grade) {
|
||||||
|
Some(students_grade) => students_grade.to_vec(),
|
||||||
|
None => vec![]
|
||||||
|
};
|
||||||
|
students_for_grade.sort();
|
||||||
|
students_for_grade
|
||||||
|
}
|
||||||
|
}
|
||||||
83
grade-school/tests/grade-school.rs
Normal file
83
grade-school/tests/grade-school.rs
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
use grade_school as school;
|
||||||
|
|
||||||
|
fn to_owned(v: &[&str]) -> Vec<String> {
|
||||||
|
v.iter().map(|s| s.to_string()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_grades_for_empty_school() {
|
||||||
|
let s = school::School::new();
|
||||||
|
assert_eq!(s.grades(), vec![]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_grades_for_one_student() {
|
||||||
|
let mut s = school::School::new();
|
||||||
|
s.add(2, "Aimee");
|
||||||
|
assert_eq!(s.grades(), vec![2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_grades_for_several_students_are_sorted() {
|
||||||
|
let mut s = school::School::new();
|
||||||
|
s.add(2, "Aimee");
|
||||||
|
s.add(7, "Logan");
|
||||||
|
s.add(4, "Blair");
|
||||||
|
assert_eq!(s.grades(), vec![2, 4, 7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_grades_when_several_students_have_the_same_grade() {
|
||||||
|
let mut s = school::School::new();
|
||||||
|
s.add(2, "Aimee");
|
||||||
|
s.add(2, "Logan");
|
||||||
|
s.add(2, "Blair");
|
||||||
|
assert_eq!(s.grades(), vec![2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_grade_for_empty_school() {
|
||||||
|
let s = school::School::new();
|
||||||
|
assert_eq!(s.grade(1), Vec::<String>::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_grade_when_no_students_have_that_grade() {
|
||||||
|
let mut s = school::School::new();
|
||||||
|
s.add(7, "Logan");
|
||||||
|
assert_eq!(s.grade(1), Vec::<String>::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_grade_for_one_student() {
|
||||||
|
let mut s = school::School::new();
|
||||||
|
s.add(2, "Aimee");
|
||||||
|
assert_eq!(s.grade(2), to_owned(&["Aimee"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_grade_returns_students_sorted_by_name() {
|
||||||
|
let mut s = school::School::new();
|
||||||
|
s.add(2, "James");
|
||||||
|
s.add(2, "Blair");
|
||||||
|
s.add(2, "Paul");
|
||||||
|
assert_eq!(s.grade(2), to_owned(&["Blair", "James", "Paul"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn test_add_students_to_different_grades() {
|
||||||
|
let mut s = school::School::new();
|
||||||
|
s.add(3, "Chelsea");
|
||||||
|
s.add(7, "Logan");
|
||||||
|
assert_eq!(s.grades(), vec![3, 7]);
|
||||||
|
assert_eq!(s.grade(3), to_owned(&["Chelsea"]));
|
||||||
|
assert_eq!(s.grade(7), to_owned(&["Logan"]));
|
||||||
|
}
|
||||||
18
health-statistics/.exercism/config.json
Normal file
18
health-statistics/.exercism/config.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"blurb": "Learn structs to store statistics for a health-monitoring system.",
|
||||||
|
"authors": [
|
||||||
|
"seanchen1991"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"src/lib.rs",
|
||||||
|
"Cargo.toml"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/health-statistics.rs"
|
||||||
|
],
|
||||||
|
"exemplar": [
|
||||||
|
".meta/exemplar.rs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
1
health-statistics/.exercism/metadata.json
Normal file
1
health-statistics/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"track":"rust","exercise":"health-statistics","id":"f7698b2154ad4d28ba7ae9b85f9714c2","url":"https://exercism.org/tracks/rust/exercises/health-statistics","handle":"ArthurDanjou","is_requester":true,"auto_approve":false}
|
||||||
7
health-statistics/Cargo.lock
generated
Normal file
7
health-statistics/Cargo.lock
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "health_statistics"
|
||||||
|
version = "0.1.0"
|
||||||
4
health-statistics/Cargo.toml
Normal file
4
health-statistics/Cargo.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[package]
|
||||||
|
name = "health_statistics"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
85
health-statistics/HELP.md
Normal file
85
health-statistics/HELP.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test
|
||||||
|
```
|
||||||
|
|
||||||
|
All but the first test have been ignored. After you get the first test to
|
||||||
|
pass, open the tests source file which is located in the `tests` directory
|
||||||
|
and remove the `#[ignore]` flag from the next test and get the tests to pass
|
||||||
|
again. Each separate test is a function with `#[test]` flag above it.
|
||||||
|
Continue, until you pass every test.
|
||||||
|
|
||||||
|
If you wish to run _only ignored_ tests without editing the tests source file, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are using Rust 1.51 or later, you can run _all_ tests with
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test -- --include-ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a specific test, for example `some_test`, you can use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test
|
||||||
|
```
|
||||||
|
|
||||||
|
If the specific test is ignored, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cargo test some_test -- --ignored
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about Rust tests refer to the online [test documentation][rust-tests].
|
||||||
|
|
||||||
|
[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit src/lib.rs Cargo.toml` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Rust track's documentation](https://exercism.org/docs/tracks/rust)
|
||||||
|
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
## Rust Installation
|
||||||
|
|
||||||
|
Refer to the [exercism help page][help-page] for Rust installation and learning
|
||||||
|
resources.
|
||||||
|
|
||||||
|
## Submitting the solution
|
||||||
|
|
||||||
|
Generally you should submit all files in which you implemented your solution (`src/lib.rs` in most cases). If you are using any external crates, please consider submitting the `Cargo.toml` file. This will make the review process faster and clearer.
|
||||||
|
|
||||||
|
## Feedback, Issues, Pull Requests
|
||||||
|
|
||||||
|
The GitHub [track repository][github] is the home for all of the Rust exercises. If you have feedback about an exercise, or want to help implement new exercises, head over there and create an issue. Members of the rust track team are happy to help!
|
||||||
|
|
||||||
|
If you want to know more about Exercism, take a look at the [contribution guide].
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
||||||
|
[help-page]: https://exercism.org/tracks/rust/learning
|
||||||
|
[github]: https://github.com/exercism/rust
|
||||||
|
[contribution guide]: https://exercism.org/docs/community/contributors
|
||||||
31
health-statistics/HINTS.md
Normal file
31
health-statistics/HINTS.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Hints
|
||||||
|
|
||||||
|
## General
|
||||||
|
|
||||||
|
## 1. Implement the `new()` method
|
||||||
|
|
||||||
|
- The `new()` method receives the arguments we want to instantiate a `User` instance with. It should return an instance of `User` with the specified name, age, and weight.
|
||||||
|
|
||||||
|
- See [here](https://doc.rust-lang.org/book/ch05-01-defining-structs.html) for additional examples on defining and instantiating structs.
|
||||||
|
|
||||||
|
## 2. Implement the getter methods
|
||||||
|
|
||||||
|
- The `name()`, `age()`, and `weight()` methods are getters. In other words, they are responsible for returning the corresponding field from a struct instance.
|
||||||
|
|
||||||
|
- Notice that the `name` method returns a `&str` when the `name` field on the `User` struct is a `String`. How can we get `&str` and `String` to play nice with each other?
|
||||||
|
|
||||||
|
- There's no need to use a `return` statement in Rust unless you expressly want a function or method to return early. Otherwise, it's more idiomatic to utilize an _implicit_ return by omitting the semicolon for the result we want a function or method to return. It's not _wrong_ to use an explicit return, but it's cleaner to take advantage of implicit returns where possible.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
fn foo() -> i32 {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- See [here](https://doc.rust-lang.org/book/ch05-03-method-syntax.html) for some more examples of defining methods on structs.
|
||||||
|
|
||||||
|
## 3. Implement the setter methods
|
||||||
|
|
||||||
|
- The `set_age()` and `set_weight()` methods are setters, responsible for updating the corresponding field on a struct instance with the input argument.
|
||||||
|
|
||||||
|
- As the signatures of these methods specify, the setter methods shouldn't return anything.
|
||||||
91
health-statistics/README.md
Normal file
91
health-statistics/README.md
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# Health Statistics
|
||||||
|
|
||||||
|
Welcome to Health Statistics on Exercism's Rust Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
It is often useful to group a collection of items together, and handle those groups as units. In Rust, we call such a group a struct, and each item one of the struct's fields. A struct defines the general set of fields available, but a particular example of a struct is called an instance.
|
||||||
|
|
||||||
|
Furthermore, structs can have methods defined on them, which have access to the fields. The struct itself in that case is referred to as `self`. When a method uses `&mut self`, the fields can be changed, or mutated. When a method uses `&self`, the fields cannot be changed: they are immutable. Controlling mutability helps the borrow-checker ensure that entire classes of concurrency bug just don't happen in Rust.
|
||||||
|
|
||||||
|
In this exercise, you'll be implementing two kinds of methods on a struct. The first are generally known as getters: they expose the struct's fields to the world, without letting anyone else mutate that value. In Rust, these methods idiomatically share the name of the field they expose, i.e., if we have a getter method that fetches a struct field called `name`, the method would simply be called `name()`.
|
||||||
|
|
||||||
|
You'll also be implementing methods of another type, generally known as setters. These change the value of the field. Setters aren't very common in Rust--if a field can be freely modified, it is more common to just make it public--but they're useful if updating the field should have side effects, or for access control: a setter marked as `pub(crate)` allows other modules within the same crate to update a private field, which can't be affected by the outside world.
|
||||||
|
|
||||||
|
Structs come in three flavors: structs with named fields, tuple structs, and unit structs. For this concept exercise, we'll be exploring the first variant: structs with named fields.
|
||||||
|
|
||||||
|
Structs are defined using the `struct` keyword, followed by the capitalized name of the type the struct is describing:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct Item {}
|
||||||
|
```
|
||||||
|
|
||||||
|
Additional types are then brought into the struct body as _fields_ of the struct, each with their own type:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct Item {
|
||||||
|
name: String,
|
||||||
|
weight: f32,
|
||||||
|
worth: u32,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Lastly, methods can be defined on structs inside of an `impl` block:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
impl Item {
|
||||||
|
// initializes and returns a new instance of our Item struct
|
||||||
|
fn new() -> Self {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
With that brief introduction to the syntax of structs out of the way, go ahead and take a look at the [instructions](instructions.md) for this exercise!
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
You're working on implementing a health-monitoring system. As part of that, you need to keep track of users' health statistics.
|
||||||
|
|
||||||
|
You'll start with some stubbed functions in an `impl` block as well as the following struct definition:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub struct User {
|
||||||
|
name: String,
|
||||||
|
age: u32,
|
||||||
|
weight: f32,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Your goal is to implement the stubbed out methods on the `User` `struct` defined in the `impl` block.
|
||||||
|
|
||||||
|
For example, the `new` method should return an instance of the `User` struct with the specified name, age, and weight values.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let mut bob = User::new(String::from("Bob"), 32, 155.2);
|
||||||
|
// Returns: a User with name "Bob", age 32, and weight 155.2
|
||||||
|
```
|
||||||
|
|
||||||
|
The `weight` method should return the weight of the `User`.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
bob.weight();
|
||||||
|
// Returns: 155.2
|
||||||
|
```
|
||||||
|
|
||||||
|
The `set_age` method should set the age of the `User`.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
bob.set_age(33);
|
||||||
|
// Updates Bob's age to 33; happy birthday Bob!
|
||||||
|
```
|
||||||
|
|
||||||
|
Have fun!
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @seanchen1991
|
||||||
39
health-statistics/src/lib.rs
Normal file
39
health-statistics/src/lib.rs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// This stub file contains items that aren't used yet; feel free to remove this module attribute
|
||||||
|
// to enable stricter warnings.
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
pub struct User {
|
||||||
|
name: String,
|
||||||
|
age: u32,
|
||||||
|
weight: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl User {
|
||||||
|
pub fn new(name: String, age: u32, weight: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
age,
|
||||||
|
weight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn age(&self) -> u32 {
|
||||||
|
self.age
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn weight(&self) -> f32 {
|
||||||
|
self.weight
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_age(&mut self, new_age: u32) {
|
||||||
|
self.age = new_age
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_weight(&mut self, new_weight: f32) {
|
||||||
|
self.weight = new_weight
|
||||||
|
}
|
||||||
|
}
|
||||||
1
health-statistics/target/.rustc_info.json
Normal file
1
health-statistics/target/.rustc_info.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"rustc_fingerprint":547482148007961314,"outputs":{"931469667778813386":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/arthurdanjou/.rustup/toolchains/stable-aarch64-apple-darwin\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"aes\"\ntarget_feature=\"crc\"\ntarget_feature=\"dit\"\ntarget_feature=\"dotprod\"\ntarget_feature=\"dpb\"\ntarget_feature=\"dpb2\"\ntarget_feature=\"fcma\"\ntarget_feature=\"fhm\"\ntarget_feature=\"flagm\"\ntarget_feature=\"fp16\"\ntarget_feature=\"frintts\"\ntarget_feature=\"jsconv\"\ntarget_feature=\"lor\"\ntarget_feature=\"lse\"\ntarget_feature=\"neon\"\ntarget_feature=\"paca\"\ntarget_feature=\"pacg\"\ntarget_feature=\"pan\"\ntarget_feature=\"pmuv3\"\ntarget_feature=\"ras\"\ntarget_feature=\"rcpc\"\ntarget_feature=\"rcpc2\"\ntarget_feature=\"rdm\"\ntarget_feature=\"sb\"\ntarget_feature=\"sha2\"\ntarget_feature=\"sha3\"\ntarget_feature=\"ssbs\"\ntarget_feature=\"vh\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n","stderr":""},"17598535894874457435":{"success":true,"status":"","code":0,"stdout":"rustc 1.61.0 (fe5b13d68 2022-05-18)\nbinary: rustc\ncommit-hash: fe5b13d681f25ee6474be29d748c65adcd91f69e\ncommit-date: 2022-05-18\nhost: aarch64-apple-darwin\nrelease: 1.61.0\nLLVM version: 14.0.0\n","stderr":""},"2797684049618456168":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n","stderr":""}},"successes":{}}
|
||||||
3
health-statistics/target/CACHEDIR.TAG
Normal file
3
health-statistics/target/CACHEDIR.TAG
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Signature: 8a477f597d28d172789f06886806bc55
|
||||||
|
# This file is a cache directory tag created by cargo.
|
||||||
|
# For information about cache directory tags see https://bford.info/cachedir/
|
||||||
0
health-statistics/target/debug/.cargo-lock
Normal file
0
health-statistics/target/debug/.cargo-lock
Normal file
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
This file has an mtime of when this was started.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
49b44726676092fc
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"rustc":5055087155190864114,"features":"[]","target":2579682610403781797,"profile":4734105543796642768,"path":2325082057379190229,"deps":[[12509414400136546036,"health_statistics",false,4812219169218510717]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/health_statistics-3855589a8de7cac3/dep-test-integration-test-health-statistics"}}],"rustflags":[],"metadata":7797948686568424061,"config":2202906307356721367,"compile_kind":0}
|
||||||
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
This file has an mtime of when this was started.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
7d3f9892d66fc842
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"rustc":5055087155190864114,"features":"[]","target":5102910661884761124,"profile":11736316127369858332,"path":17523903030608720598,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/health_statistics-62e3af01ebef91c4/dep-lib-health_statistics"}}],"rustflags":[],"metadata":7797948686568424061,"config":2202906307356721367,"compile_kind":0}
|
||||||
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
This file has an mtime of when this was started.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
9fbd36fdd78f00fb
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"rustc":5055087155190864114,"features":"[]","target":5102910661884761124,"profile":4734105543796642768,"path":17523903030608720598,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/health_statistics-786b473719522259/dep-test-lib-health_statistics"}}],"rustflags":[],"metadata":7797948686568424061,"config":2202906307356721367,"compile_kind":0}
|
||||||
BIN
health-statistics/target/debug/deps/health_statistics-3855589a8de7cac3
Executable file
BIN
health-statistics/target/debug/deps/health_statistics-3855589a8de7cac3
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user