aboutsummaryrefslogtreecommitdiff
path: root/rust
diff options
context:
space:
mode:
authorFederico Igne <git@federicoigne.com>2020-12-26 17:48:38 +0000
committerFederico Igne <git@federicoigne.com>2021-11-03 18:55:08 +0000
commit02481656966b0a8dfc95cf3c22bcc049660ff7d4 (patch)
tree8e39798fcaf27931d91c2088423fd4e97adcfc2d /rust
parent4e2052c4d792540c2f742b2c2a081b11117ed41d (diff)
downloadexercism-02481656966b0a8dfc95cf3c22bcc049660ff7d4.tar.gz
exercism-02481656966b0a8dfc95cf3c22bcc049660ff7d4.zip
Move Rust exercises in a subdirectory
Diffstat (limited to 'rust')
-rw-r--r--rust/armstrong-numbers/.exercism/metadata.json1
-rw-r--r--rust/armstrong-numbers/.gitignore8
-rw-r--r--rust/armstrong-numbers/Cargo.toml4
-rw-r--r--rust/armstrong-numbers/README.md94
-rw-r--r--rust/armstrong-numbers/src/lib.rs15
-rw-r--r--rust/armstrong-numbers/tests/armstrong-numbers.rs46
-rw-r--r--rust/beer-song/.exercism/metadata.json1
-rw-r--r--rust/beer-song/.gitignore8
-rw-r--r--rust/beer-song/Cargo.toml7
-rw-r--r--rust/beer-song/README.md401
-rw-r--r--rust/beer-song/src/intersperse.rs52
-rw-r--r--rust/beer-song/src/lib.rs20
-rw-r--r--rust/beer-song/tests/beer-song.rs31
-rw-r--r--rust/bob/.exercism/metadata.json1
-rw-r--r--rust/bob/.gitignore8
-rw-r--r--rust/bob/Cargo.toml4
-rw-r--r--rust/bob/README.md96
-rw-r--r--rust/bob/src/lib.rs75
-rw-r--r--rust/bob/tests/bob.rs179
-rw-r--r--rust/clock/.exercism/metadata.json1
-rw-r--r--rust/clock/.gitignore8
-rw-r--r--rust/clock/Cargo.toml6
-rw-r--r--rust/clock/README.md102
-rw-r--r--rust/clock/src/lib.rs44
-rw-r--r--rust/clock/tests/clock.rs294
-rw-r--r--rust/difference-of-squares/.exercism/metadata.json1
-rw-r--r--rust/difference-of-squares/.gitignore8
-rw-r--r--rust/difference-of-squares/Cargo.toml4
-rw-r--r--rust/difference-of-squares/README.md97
-rw-r--r--rust/difference-of-squares/src/lib.rs14
-rw-r--r--rust/difference-of-squares/tests/difference-of-squares.rs46
-rw-r--r--rust/dot-dsl/.exercism/metadata.json1
-rw-r--r--rust/dot-dsl/.gitignore8
-rw-r--r--rust/dot-dsl/Cargo.toml7
-rw-r--r--rust/dot-dsl/README.md121
-rw-r--r--rust/dot-dsl/src/lib.rs119
-rw-r--r--rust/dot-dsl/tests/dot-dsl.rs138
-rw-r--r--rust/gigasecond/.exercism/metadata.json1
-rw-r--r--rust/gigasecond/.gitignore8
-rw-r--r--rust/gigasecond/Cargo.toml8
-rw-r--r--rust/gigasecond/README.md89
-rw-r--r--rust/gigasecond/src/lib.rs7
-rw-r--r--rust/gigasecond/tests/gigasecond.rs51
-rw-r--r--rust/grains/.exercism/metadata.json1
-rw-r--r--rust/grains/.gitignore8
-rw-r--r--rust/grains/Cargo.toml4
-rw-r--r--rust/grains/README.md107
-rw-r--r--rust/grains/src/lib.rs23
-rw-r--r--rust/grains/tests/grains.rs65
-rw-r--r--rust/hello-world/.exercism/metadata.json1
-rw-r--r--rust/hello-world/.gitignore8
-rw-r--r--rust/hello-world/Cargo.toml4
-rw-r--r--rust/hello-world/GETTING_STARTED.md92
-rw-r--r--rust/hello-world/README.md95
-rw-r--r--rust/hello-world/src/lib.rs5
-rw-r--r--rust/hello-world/tests/hello-world.rs6
-rw-r--r--rust/high-scores/.exercism/metadata.json1
-rw-r--r--rust/high-scores/.gitignore8
-rw-r--r--rust/high-scores/Cargo.toml6
-rw-r--r--rust/high-scores/README.md95
-rw-r--r--rust/high-scores/src/lib.rs29
-rw-r--r--rust/high-scores/tests/high-scores.rs68
-rw-r--r--rust/leap/.exercism/metadata.json1
-rw-r--r--rust/leap/.gitignore8
-rw-r--r--rust/leap/Cargo.toml4
-rw-r--r--rust/leap/README.md105
-rw-r--r--rust/leap/src/lib.rs3
-rw-r--r--rust/leap/tests/leap.rs89
-rw-r--r--rust/matching-brackets/.exercism/metadata.json1
-rw-r--r--rust/matching-brackets/.gitignore8
-rw-r--r--rust/matching-brackets/Cargo.toml4
-rw-r--r--rust/matching-brackets/README.md85
-rw-r--r--rust/matching-brackets/src/lib.rs12
-rw-r--r--rust/matching-brackets/tests/matching-brackets.rs98
-rw-r--r--rust/nth-prime/.exercism/metadata.json1
-rw-r--r--rust/nth-prime/.gitignore8
-rw-r--r--rust/nth-prime/Cargo.toml6
-rw-r--r--rust/nth-prime/README.md92
-rw-r--r--rust/nth-prime/src/lib.rs8
-rw-r--r--rust/nth-prime/tests/nth-prime.rs21
-rw-r--r--rust/nucleotide-count/.exercism/metadata.json1
-rw-r--r--rust/nucleotide-count/.gitignore8
-rw-r--r--rust/nucleotide-count/Cargo.toml7
-rw-r--r--rust/nucleotide-count/README.md110
-rw-r--r--rust/nucleotide-count/src/lib.rs21
-rw-r--r--rust/nucleotide-count/tests/nucleotide-count.rs88
-rw-r--r--rust/paasio/.exercism/metadata.json1
-rw-r--r--rust/paasio/.gitignore8
-rw-r--r--rust/paasio/Cargo.toml4
-rw-r--r--rust/paasio/README.md102
-rw-r--r--rust/paasio/src/lib.rs82
-rw-r--r--rust/paasio/tests/paasio.rs192
-rw-r--r--rust/pascals-triangle/.exercism/metadata.json1
-rw-r--r--rust/pascals-triangle/.gitignore8
-rw-r--r--rust/pascals-triangle/Cargo.toml4
-rw-r--r--rust/pascals-triangle/README.md95
-rw-r--r--rust/pascals-triangle/src/lib.rs34
-rw-r--r--rust/pascals-triangle/tests/pascals-triangle.rs96
-rw-r--r--rust/prime-factors/.exercism/metadata.json1
-rw-r--r--rust/prime-factors/.gitignore8
-rw-r--r--rust/prime-factors/Cargo.toml6
-rw-r--r--rust/prime-factors/README.md110
-rw-r--r--rust/prime-factors/src/lib.rs18
-rw-r--r--rust/prime-factors/tests/prime-factors.rs36
-rw-r--r--rust/proverb/.exercism/metadata.json1
-rw-r--r--rust/proverb/.gitignore8
-rw-r--r--rust/proverb/Cargo.toml6
-rw-r--r--rust/proverb/README.md97
-rw-r--r--rust/proverb/src/lib.rs15
-rw-r--r--rust/proverb/tests/proverb.rs70
-rw-r--r--rust/raindrops/.exercism/metadata.json1
-rw-r--r--rust/raindrops/.gitignore8
-rw-r--r--rust/raindrops/Cargo.toml4
-rw-r--r--rust/raindrops/README.md96
-rw-r--r--rust/raindrops/src/lib.rs28
-rw-r--r--rust/raindrops/tests/raindrops.rs96
-rw-r--r--rust/reverse-string/.exercism/metadata.json1
-rw-r--r--rust/reverse-string/.gitignore8
-rw-r--r--rust/reverse-string/Cargo.toml10
-rw-r--r--rust/reverse-string/README.md103
-rw-r--r--rust/reverse-string/src/lib.rs5
-rw-r--r--rust/reverse-string/tests/reverse-string.rs62
-rw-r--r--rust/saddle-points/.exercism/metadata.json1
-rw-r--r--rust/saddle-points/.gitignore8
-rw-r--r--rust/saddle-points/Cargo.toml6
-rw-r--r--rust/saddle-points/README.md132
-rw-r--r--rust/saddle-points/src/lib.rs16
-rw-r--r--rust/saddle-points/tests/saddle-points.rs98
-rw-r--r--rust/simple-linked-list/.exercism/metadata.json1
-rw-r--r--rust/simple-linked-list/.gitignore8
-rw-r--r--rust/simple-linked-list/Cargo.toml6
-rw-r--r--rust/simple-linked-list/README.md137
-rw-r--r--rust/simple-linked-list/src/lib.rs109
-rw-r--r--rust/simple-linked-list/tests/simple-linked-list.rs118
-rw-r--r--rust/sum-of-multiples/.exercism/metadata.json1
-rw-r--r--rust/sum-of-multiples/.gitignore8
-rw-r--r--rust/sum-of-multiples/Cargo.toml4
-rw-r--r--rust/sum-of-multiples/README.md89
-rw-r--r--rust/sum-of-multiples/src/lib.rs3
-rw-r--r--rust/sum-of-multiples/tests/sum-of-multiples.rs81
140 files changed, 5900 insertions, 0 deletions
diff --git a/rust/armstrong-numbers/.exercism/metadata.json b/rust/armstrong-numbers/.exercism/metadata.json
new file mode 100644
index 0000000..cfda14e
--- /dev/null
+++ b/rust/armstrong-numbers/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"armstrong-numbers","id":"f53447212bdd4e1c96e26911eb961199","url":"https://exercism.io/my/solutions/f53447212bdd4e1c96e26911eb961199","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/armstrong-numbers/.gitignore b/rust/armstrong-numbers/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/armstrong-numbers/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/armstrong-numbers/Cargo.toml b/rust/armstrong-numbers/Cargo.toml
new file mode 100644
index 0000000..22e66de
--- /dev/null
+++ b/rust/armstrong-numbers/Cargo.toml
@@ -0,0 +1,4 @@
1[package]
2edition = "2018"
3name = "armstrong_numbers"
4version = "1.1.0"
diff --git a/rust/armstrong-numbers/README.md b/rust/armstrong-numbers/README.md
new file mode 100644
index 0000000..6437ffe
--- /dev/null
+++ b/rust/armstrong-numbers/README.md
@@ -0,0 +1,94 @@
1# Armstrong Numbers
2
3An [Armstrong number](https://en.wikipedia.org/wiki/Narcissistic_number)
4is a number that is the sum of its own digits each raised to the power
5of the number of digits.
6
7For example:
8
9- 9 is an Armstrong number, because `9 = 9^1 = 9`
10- 10 is *not* an Armstrong number, because `10 != 1^2 + 0^2 = 1`
11- 153 is an Armstrong number, because: `153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153`
12- 154 is *not* an Armstrong number, because: `154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190`
13
14Write some code to determine whether a number is an Armstrong number.
15
16## Rust Installation
17
18Refer to the [exercism help page][help-page] for Rust installation and learning
19resources.
20
21## Writing the Code
22
23Execute the tests with:
24
25```bash
26$ cargo test
27```
28
29All but the first test have been ignored. After you get the first test to
30pass, open the tests source file which is located in the `tests` directory
31and remove the `#[ignore]` flag from the next test and get the tests to pass
32again. Each separate test is a function with `#[test]` flag above it.
33Continue, until you pass every test.
34
35If you wish to run all ignored tests without editing the tests source file, use:
36
37```bash
38$ cargo test -- --ignored
39```
40
41To run a specific test, for example `some_test`, you can use:
42
43```bash
44$ cargo test some_test
45```
46
47If the specific test is ignored use:
48
49```bash
50$ cargo test some_test -- --ignored
51```
52
53To learn more about Rust tests refer to the [online test documentation][rust-tests]
54
55Make sure to read the [Modules][modules] chapter if you
56haven't already, it will help you with organizing your files.
57
58## Further improvements
59
60After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
61
62To format your solution, inside the solution directory use
63
64```bash
65cargo fmt
66```
67
68To see, if your solution contains some common ineffective use cases, inside the solution directory use
69
70```bash
71cargo clippy --all-targets
72```
73
74## Submitting the solution
75
76Generally 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.
77
78## Feedback, Issues, Pull Requests
79
80The [exercism/rust](https://github.com/exercism/rust) repository on 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!
81
82If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
83
84[help-page]: https://exercism.io/tracks/rust/learning
85[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
86[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
87[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
88
89## Source
90
91Wikipedia [https://en.wikipedia.org/wiki/Narcissistic_number](https://en.wikipedia.org/wiki/Narcissistic_number)
92
93## Submitting Incomplete Solutions
94It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/armstrong-numbers/src/lib.rs b/rust/armstrong-numbers/src/lib.rs
new file mode 100644
index 0000000..41b0824
--- /dev/null
+++ b/rust/armstrong-numbers/src/lib.rs
@@ -0,0 +1,15 @@
1
2fn digits(mut n: u32) -> (usize,Vec<u32>) {
3 let mut v = vec![];
4 while n > 9 {
5 v.push(n % 10);
6 n /= 10;
7 }
8 v.push(n);
9 (v.len(),v)
10}
11
12pub fn is_armstrong_number(num: u32) -> bool {
13 let (l,v) = digits(num);
14 v.iter().map(|x| x.pow(l as u32)).sum::<u32>() == num
15}
diff --git a/rust/armstrong-numbers/tests/armstrong-numbers.rs b/rust/armstrong-numbers/tests/armstrong-numbers.rs
new file mode 100644
index 0000000..9ac51d0
--- /dev/null
+++ b/rust/armstrong-numbers/tests/armstrong-numbers.rs
@@ -0,0 +1,46 @@
1use armstrong_numbers::*;
2
3#[test]
4fn test_zero_is_an_armstrong_number() {
5 assert!(is_armstrong_number(0))
6}
7
8#[test]
9fn test_single_digit_numbers_are_armstrong_numbers() {
10 assert!(is_armstrong_number(5))
11}
12
13#[test]
14fn test_there_are_no_2_digit_armstrong_numbers() {
15 assert!(!is_armstrong_number(10))
16}
17
18#[test]
19fn test_three_digit_armstrong_number() {
20 assert!(is_armstrong_number(153))
21}
22
23#[test]
24fn test_three_digit_non_armstrong_number() {
25 assert!(!is_armstrong_number(100))
26}
27
28#[test]
29fn test_four_digit_armstrong_number() {
30 assert!(is_armstrong_number(9474))
31}
32
33#[test]
34fn test_four_digit_non_armstrong_number() {
35 assert!(!is_armstrong_number(9475))
36}
37
38#[test]
39fn test_seven_digit_armstrong_number() {
40 assert!(is_armstrong_number(9_926_315))
41}
42
43#[test]
44fn test_seven_digit_non_armstrong_number() {
45 assert!(!is_armstrong_number(9_926_316))
46}
diff --git a/rust/beer-song/.exercism/metadata.json b/rust/beer-song/.exercism/metadata.json
new file mode 100644
index 0000000..640fbbc
--- /dev/null
+++ b/rust/beer-song/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"beer-song","id":"d7320f8ac9c543dc853815bbb5b4d4d5","url":"https://exercism.io/my/solutions/d7320f8ac9c543dc853815bbb5b4d4d5","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/beer-song/.gitignore b/rust/beer-song/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/beer-song/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/beer-song/Cargo.toml b/rust/beer-song/Cargo.toml
new file mode 100644
index 0000000..ff6683e
--- /dev/null
+++ b/rust/beer-song/Cargo.toml
@@ -0,0 +1,7 @@
1[package]
2edition = "2018"
3name = "beer-song"
4version = "0.0.0"
5
6[dependencies]
7itertools = "0.9"
diff --git a/rust/beer-song/README.md b/rust/beer-song/README.md
new file mode 100644
index 0000000..2ed305c
--- /dev/null
+++ b/rust/beer-song/README.md
@@ -0,0 +1,401 @@
1# Beer Song
2
3Recite the lyrics to that beloved classic, that field-trip favorite: 99 Bottles of Beer on the Wall.
4
5Note that not all verses are identical.
6
7```text
899 bottles of beer on the wall, 99 bottles of beer.
9Take one down and pass it around, 98 bottles of beer on the wall.
10
1198 bottles of beer on the wall, 98 bottles of beer.
12Take one down and pass it around, 97 bottles of beer on the wall.
13
1497 bottles of beer on the wall, 97 bottles of beer.
15Take one down and pass it around, 96 bottles of beer on the wall.
16
1796 bottles of beer on the wall, 96 bottles of beer.
18Take one down and pass it around, 95 bottles of beer on the wall.
19
2095 bottles of beer on the wall, 95 bottles of beer.
21Take one down and pass it around, 94 bottles of beer on the wall.
22
2394 bottles of beer on the wall, 94 bottles of beer.
24Take one down and pass it around, 93 bottles of beer on the wall.
25
2693 bottles of beer on the wall, 93 bottles of beer.
27Take one down and pass it around, 92 bottles of beer on the wall.
28
2992 bottles of beer on the wall, 92 bottles of beer.
30Take one down and pass it around, 91 bottles of beer on the wall.
31
3291 bottles of beer on the wall, 91 bottles of beer.
33Take one down and pass it around, 90 bottles of beer on the wall.
34
3590 bottles of beer on the wall, 90 bottles of beer.
36Take one down and pass it around, 89 bottles of beer on the wall.
37
3889 bottles of beer on the wall, 89 bottles of beer.
39Take one down and pass it around, 88 bottles of beer on the wall.
40
4188 bottles of beer on the wall, 88 bottles of beer.
42Take one down and pass it around, 87 bottles of beer on the wall.
43
4487 bottles of beer on the wall, 87 bottles of beer.
45Take one down and pass it around, 86 bottles of beer on the wall.
46
4786 bottles of beer on the wall, 86 bottles of beer.
48Take one down and pass it around, 85 bottles of beer on the wall.
49
5085 bottles of beer on the wall, 85 bottles of beer.
51Take one down and pass it around, 84 bottles of beer on the wall.
52
5384 bottles of beer on the wall, 84 bottles of beer.
54Take one down and pass it around, 83 bottles of beer on the wall.
55
5683 bottles of beer on the wall, 83 bottles of beer.
57Take one down and pass it around, 82 bottles of beer on the wall.
58
5982 bottles of beer on the wall, 82 bottles of beer.
60Take one down and pass it around, 81 bottles of beer on the wall.
61
6281 bottles of beer on the wall, 81 bottles of beer.
63Take one down and pass it around, 80 bottles of beer on the wall.
64
6580 bottles of beer on the wall, 80 bottles of beer.
66Take one down and pass it around, 79 bottles of beer on the wall.
67
6879 bottles of beer on the wall, 79 bottles of beer.
69Take one down and pass it around, 78 bottles of beer on the wall.
70
7178 bottles of beer on the wall, 78 bottles of beer.
72Take one down and pass it around, 77 bottles of beer on the wall.
73
7477 bottles of beer on the wall, 77 bottles of beer.
75Take one down and pass it around, 76 bottles of beer on the wall.
76
7776 bottles of beer on the wall, 76 bottles of beer.
78Take one down and pass it around, 75 bottles of beer on the wall.
79
8075 bottles of beer on the wall, 75 bottles of beer.
81Take one down and pass it around, 74 bottles of beer on the wall.
82
8374 bottles of beer on the wall, 74 bottles of beer.
84Take one down and pass it around, 73 bottles of beer on the wall.
85
8673 bottles of beer on the wall, 73 bottles of beer.
87Take one down and pass it around, 72 bottles of beer on the wall.
88
8972 bottles of beer on the wall, 72 bottles of beer.
90Take one down and pass it around, 71 bottles of beer on the wall.
91
9271 bottles of beer on the wall, 71 bottles of beer.
93Take one down and pass it around, 70 bottles of beer on the wall.
94
9570 bottles of beer on the wall, 70 bottles of beer.
96Take one down and pass it around, 69 bottles of beer on the wall.
97
9869 bottles of beer on the wall, 69 bottles of beer.
99Take one down and pass it around, 68 bottles of beer on the wall.
100
10168 bottles of beer on the wall, 68 bottles of beer.
102Take one down and pass it around, 67 bottles of beer on the wall.
103
10467 bottles of beer on the wall, 67 bottles of beer.
105Take one down and pass it around, 66 bottles of beer on the wall.
106
10766 bottles of beer on the wall, 66 bottles of beer.
108Take one down and pass it around, 65 bottles of beer on the wall.
109
11065 bottles of beer on the wall, 65 bottles of beer.
111Take one down and pass it around, 64 bottles of beer on the wall.
112
11364 bottles of beer on the wall, 64 bottles of beer.
114Take one down and pass it around, 63 bottles of beer on the wall.
115
11663 bottles of beer on the wall, 63 bottles of beer.
117Take one down and pass it around, 62 bottles of beer on the wall.
118
11962 bottles of beer on the wall, 62 bottles of beer.
120Take one down and pass it around, 61 bottles of beer on the wall.
121
12261 bottles of beer on the wall, 61 bottles of beer.
123Take one down and pass it around, 60 bottles of beer on the wall.
124
12560 bottles of beer on the wall, 60 bottles of beer.
126Take one down and pass it around, 59 bottles of beer on the wall.
127
12859 bottles of beer on the wall, 59 bottles of beer.
129Take one down and pass it around, 58 bottles of beer on the wall.
130
13158 bottles of beer on the wall, 58 bottles of beer.
132Take one down and pass it around, 57 bottles of beer on the wall.
133
13457 bottles of beer on the wall, 57 bottles of beer.
135Take one down and pass it around, 56 bottles of beer on the wall.
136
13756 bottles of beer on the wall, 56 bottles of beer.
138Take one down and pass it around, 55 bottles of beer on the wall.
139
14055 bottles of beer on the wall, 55 bottles of beer.
141Take one down and pass it around, 54 bottles of beer on the wall.
142
14354 bottles of beer on the wall, 54 bottles of beer.
144Take one down and pass it around, 53 bottles of beer on the wall.
145
14653 bottles of beer on the wall, 53 bottles of beer.
147Take one down and pass it around, 52 bottles of beer on the wall.
148
14952 bottles of beer on the wall, 52 bottles of beer.
150Take one down and pass it around, 51 bottles of beer on the wall.
151
15251 bottles of beer on the wall, 51 bottles of beer.
153Take one down and pass it around, 50 bottles of beer on the wall.
154
15550 bottles of beer on the wall, 50 bottles of beer.
156Take one down and pass it around, 49 bottles of beer on the wall.
157
15849 bottles of beer on the wall, 49 bottles of beer.
159Take one down and pass it around, 48 bottles of beer on the wall.
160
16148 bottles of beer on the wall, 48 bottles of beer.
162Take one down and pass it around, 47 bottles of beer on the wall.
163
16447 bottles of beer on the wall, 47 bottles of beer.
165Take one down and pass it around, 46 bottles of beer on the wall.
166
16746 bottles of beer on the wall, 46 bottles of beer.
168Take one down and pass it around, 45 bottles of beer on the wall.
169
17045 bottles of beer on the wall, 45 bottles of beer.
171Take one down and pass it around, 44 bottles of beer on the wall.
172
17344 bottles of beer on the wall, 44 bottles of beer.
174Take one down and pass it around, 43 bottles of beer on the wall.
175
17643 bottles of beer on the wall, 43 bottles of beer.
177Take one down and pass it around, 42 bottles of beer on the wall.
178
17942 bottles of beer on the wall, 42 bottles of beer.
180Take one down and pass it around, 41 bottles of beer on the wall.
181
18241 bottles of beer on the wall, 41 bottles of beer.
183Take one down and pass it around, 40 bottles of beer on the wall.
184
18540 bottles of beer on the wall, 40 bottles of beer.
186Take one down and pass it around, 39 bottles of beer on the wall.
187
18839 bottles of beer on the wall, 39 bottles of beer.
189Take one down and pass it around, 38 bottles of beer on the wall.
190
19138 bottles of beer on the wall, 38 bottles of beer.
192Take one down and pass it around, 37 bottles of beer on the wall.
193
19437 bottles of beer on the wall, 37 bottles of beer.
195Take one down and pass it around, 36 bottles of beer on the wall.
196
19736 bottles of beer on the wall, 36 bottles of beer.
198Take one down and pass it around, 35 bottles of beer on the wall.
199
20035 bottles of beer on the wall, 35 bottles of beer.
201Take one down and pass it around, 34 bottles of beer on the wall.
202
20334 bottles of beer on the wall, 34 bottles of beer.
204Take one down and pass it around, 33 bottles of beer on the wall.
205
20633 bottles of beer on the wall, 33 bottles of beer.
207Take one down and pass it around, 32 bottles of beer on the wall.
208
20932 bottles of beer on the wall, 32 bottles of beer.
210Take one down and pass it around, 31 bottles of beer on the wall.
211
21231 bottles of beer on the wall, 31 bottles of beer.
213Take one down and pass it around, 30 bottles of beer on the wall.
214
21530 bottles of beer on the wall, 30 bottles of beer.
216Take one down and pass it around, 29 bottles of beer on the wall.
217
21829 bottles of beer on the wall, 29 bottles of beer.
219Take one down and pass it around, 28 bottles of beer on the wall.
220
22128 bottles of beer on the wall, 28 bottles of beer.
222Take one down and pass it around, 27 bottles of beer on the wall.
223
22427 bottles of beer on the wall, 27 bottles of beer.
225Take one down and pass it around, 26 bottles of beer on the wall.
226
22726 bottles of beer on the wall, 26 bottles of beer.
228Take one down and pass it around, 25 bottles of beer on the wall.
229
23025 bottles of beer on the wall, 25 bottles of beer.
231Take one down and pass it around, 24 bottles of beer on the wall.
232
23324 bottles of beer on the wall, 24 bottles of beer.
234Take one down and pass it around, 23 bottles of beer on the wall.
235
23623 bottles of beer on the wall, 23 bottles of beer.
237Take one down and pass it around, 22 bottles of beer on the wall.
238
23922 bottles of beer on the wall, 22 bottles of beer.
240Take one down and pass it around, 21 bottles of beer on the wall.
241
24221 bottles of beer on the wall, 21 bottles of beer.
243Take one down and pass it around, 20 bottles of beer on the wall.
244
24520 bottles of beer on the wall, 20 bottles of beer.
246Take one down and pass it around, 19 bottles of beer on the wall.
247
24819 bottles of beer on the wall, 19 bottles of beer.
249Take one down and pass it around, 18 bottles of beer on the wall.
250
25118 bottles of beer on the wall, 18 bottles of beer.
252Take one down and pass it around, 17 bottles of beer on the wall.
253
25417 bottles of beer on the wall, 17 bottles of beer.
255Take one down and pass it around, 16 bottles of beer on the wall.
256
25716 bottles of beer on the wall, 16 bottles of beer.
258Take one down and pass it around, 15 bottles of beer on the wall.
259
26015 bottles of beer on the wall, 15 bottles of beer.
261Take one down and pass it around, 14 bottles of beer on the wall.
262
26314 bottles of beer on the wall, 14 bottles of beer.
264Take one down and pass it around, 13 bottles of beer on the wall.
265
26613 bottles of beer on the wall, 13 bottles of beer.
267Take one down and pass it around, 12 bottles of beer on the wall.
268
26912 bottles of beer on the wall, 12 bottles of beer.
270Take one down and pass it around, 11 bottles of beer on the wall.
271
27211 bottles of beer on the wall, 11 bottles of beer.
273Take one down and pass it around, 10 bottles of beer on the wall.
274
27510 bottles of beer on the wall, 10 bottles of beer.
276Take one down and pass it around, 9 bottles of beer on the wall.
277
2789 bottles of beer on the wall, 9 bottles of beer.
279Take one down and pass it around, 8 bottles of beer on the wall.
280
2818 bottles of beer on the wall, 8 bottles of beer.
282Take one down and pass it around, 7 bottles of beer on the wall.
283
2847 bottles of beer on the wall, 7 bottles of beer.
285Take one down and pass it around, 6 bottles of beer on the wall.
286
2876 bottles of beer on the wall, 6 bottles of beer.
288Take one down and pass it around, 5 bottles of beer on the wall.
289
2905 bottles of beer on the wall, 5 bottles of beer.
291Take one down and pass it around, 4 bottles of beer on the wall.
292
2934 bottles of beer on the wall, 4 bottles of beer.
294Take one down and pass it around, 3 bottles of beer on the wall.
295
2963 bottles of beer on the wall, 3 bottles of beer.
297Take one down and pass it around, 2 bottles of beer on the wall.
298
2992 bottles of beer on the wall, 2 bottles of beer.
300Take one down and pass it around, 1 bottle of beer on the wall.
301
3021 bottle of beer on the wall, 1 bottle of beer.
303Take it down and pass it around, no more bottles of beer on the wall.
304
305No more bottles of beer on the wall, no more bottles of beer.
306Go to the store and buy some more, 99 bottles of beer on the wall.
307```
308
309## For bonus points
310
311Did you get the tests passing and the code clean? If you want to, these
312are some additional things you could try:
313
314* Remove as much duplication as you possibly can.
315* Optimize for readability, even if it means introducing duplication.
316* If you've removed all the duplication, do you have a lot of
317 conditionals? Try replacing the conditionals with polymorphism, if it
318 applies in this language. How readable is it?
319
320Then please share your thoughts in a comment on the submission. Did this
321experiment make the code better? Worse? Did you learn anything from it?
322
323## Rust Installation
324
325Refer to the [exercism help page][help-page] for Rust installation and learning
326resources.
327
328## Writing the Code
329
330Execute the tests with:
331
332```bash
333$ cargo test
334```
335
336All but the first test have been ignored. After you get the first test to
337pass, open the tests source file which is located in the `tests` directory
338and remove the `#[ignore]` flag from the next test and get the tests to pass
339again. Each separate test is a function with `#[test]` flag above it.
340Continue, until you pass every test.
341
342If you wish to run all ignored tests without editing the tests source file, use:
343
344```bash
345$ cargo test -- --ignored
346```
347
348To run a specific test, for example `some_test`, you can use:
349
350```bash
351$ cargo test some_test
352```
353
354If the specific test is ignored use:
355
356```bash
357$ cargo test some_test -- --ignored
358```
359
360To learn more about Rust tests refer to the [online test documentation][rust-tests]
361
362Make sure to read the [Modules][modules] chapter if you
363haven't already, it will help you with organizing your files.
364
365## Further improvements
366
367After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
368
369To format your solution, inside the solution directory use
370
371```bash
372cargo fmt
373```
374
375To see, if your solution contains some common ineffective use cases, inside the solution directory use
376
377```bash
378cargo clippy --all-targets
379```
380
381## Submitting the solution
382
383Generally 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.
384
385## Feedback, Issues, Pull Requests
386
387The [exercism/rust](https://github.com/exercism/rust) repository on 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!
388
389If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
390
391[help-page]: https://exercism.io/tracks/rust/learning
392[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
393[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
394[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
395
396## Source
397
398Learn to Program by Chris Pine [http://pine.fm/LearnToProgram/?Chapter=06](http://pine.fm/LearnToProgram/?Chapter=06)
399
400## Submitting Incomplete Solutions
401It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/beer-song/src/intersperse.rs b/rust/beer-song/src/intersperse.rs
new file mode 100644
index 0000000..51580e6
--- /dev/null
+++ b/rust/beer-song/src/intersperse.rs
@@ -0,0 +1,52 @@
1use std::rc::Rc;
2
3/// An iterator that allows to insert a given element `elem` every `interval` elements of the input
4/// iterator.
5///
6/// The interleaved element is wrapped in a `Rc` smart pointer to avoid hard copies.
7pub struct Intersperse<I: Iterator> {
8 inner: std::iter::Peekable<I>, // required to have `peek(..)`
9 elem: Rc<I::Item>,
10 interval: u32,
11 intersperse: u32,
12}
13
14impl<I: Iterator> Intersperse<I> {
15 pub fn new(inner: I, elem: I::Item, interval: u32) -> Intersperse<I> {
16 Intersperse {
17 inner: inner.peekable(),
18 elem: Rc::new(elem),
19 interval: interval + 1, // `+ 1` needed to align semantics and implementation
20 intersperse: 0,
21 }
22 }
23}
24
25impl<I: Iterator> Iterator for Intersperse<I> {
26 type Item = Rc<I::Item>;
27
28 fn next(&mut self) -> Option<Self::Item> {
29 // Counter rotation
30 self.intersperse = (self.intersperse + 1) % self.interval;
31 // Insert a copy of the element only when counter goes to 0 and we haven't reached the end
32 // of the inner iterator.
33 if self.intersperse == 0 && self.inner.peek().is_some() {
34 Some(Rc::clone(&self.elem))
35 } else {
36 self.inner.next()
37 .map(|x| Rc::new(x)) // Go from Option<I::Item> to Option<Rc<I::Item>>
38 }
39 }
40}
41
42/// Extend `Iterator`s with `intersperse` function.
43pub trait IntersperseIterator: Iterator {
44 fn intersperse(self, elem: Self::Item, interval: u32) -> Intersperse<Self>
45 where
46 Self: Sized,
47 {
48 Intersperse::new(self, elem, interval)
49 }
50}
51
52impl<I: Iterator> IntersperseIterator for I {}
diff --git a/rust/beer-song/src/lib.rs b/rust/beer-song/src/lib.rs
new file mode 100644
index 0000000..990fbbf
--- /dev/null
+++ b/rust/beer-song/src/lib.rs
@@ -0,0 +1,20 @@
1use itertools::Itertools;
2
3pub fn verse(n: u32) -> String {
4 match n {
5 0 => format!( "No more bottles of beer on the wall, no more bottles of beer.\n\
6 Go to the store and buy some more, 99 bottles of beer on the wall.\n"),
7 1 => format!( "1 bottle of beer on the wall, 1 bottle of beer.\n\
8 Take it down and pass it around, no more bottles of beer on the wall.\n"),
9 2 => format!( "2 bottles of beer on the wall, 2 bottles of beer.\n\
10 Take one down and pass it around, 1 bottle of beer on the wall.\n"),
11 _ => format!( "{} bottles of beer on the wall, {} bottles of beer.\n\
12 Take one down and pass it around, {} bottles of beer on the wall.\n",
13 n, n, n - 1)
14 }
15}
16
17pub fn sing(start: u32, end: u32) -> String {
18 // Note: call to `join` can be substituted with `.intersperse(String::from("\n")).collect()`
19 (end..=start).rev().map(|x| verse(x)).join("\n")
20}
diff --git a/rust/beer-song/tests/beer-song.rs b/rust/beer-song/tests/beer-song.rs
new file mode 100644
index 0000000..2f2ad11
--- /dev/null
+++ b/rust/beer-song/tests/beer-song.rs
@@ -0,0 +1,31 @@
1use beer_song as beer;
2
3#[test]
4fn test_verse_0() {
5 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");
6}
7
8#[test]
9fn test_verse_1() {
10 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");
11}
12
13#[test]
14fn test_verse_2() {
15 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");
16}
17
18#[test]
19fn test_verse_8() {
20 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");
21}
22
23#[test]
24fn test_song_8_6() {
25 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");
26}
27
28#[test]
29fn test_song_3_0() {
30 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");
31}
diff --git a/rust/bob/.exercism/metadata.json b/rust/bob/.exercism/metadata.json
new file mode 100644
index 0000000..c9dfddb
--- /dev/null
+++ b/rust/bob/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"bob","id":"4e53ee4ebf414ac3b9da60e7011c04f9","url":"https://exercism.io/my/solutions/4e53ee4ebf414ac3b9da60e7011c04f9","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/bob/.gitignore b/rust/bob/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/bob/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/bob/Cargo.toml b/rust/bob/Cargo.toml
new file mode 100644
index 0000000..34a7fbf
--- /dev/null
+++ b/rust/bob/Cargo.toml
@@ -0,0 +1,4 @@
1[package]
2edition = "2018"
3name = "bob"
4version = "1.6.0"
diff --git a/rust/bob/README.md b/rust/bob/README.md
new file mode 100644
index 0000000..dd84948
--- /dev/null
+++ b/rust/bob/README.md
@@ -0,0 +1,96 @@
1# Bob
2
3Bob is a lackadaisical teenager. In conversation, his responses are very limited.
4
5Bob answers 'Sure.' if you ask him a question, such as "How are you?".
6
7He answers 'Whoa, chill out!' if you YELL AT HIM (in all capitals).
8
9He answers 'Calm down, I know what I'm doing!' if you yell a question at him.
10
11He says 'Fine. Be that way!' if you address him without actually saying
12anything.
13
14He answers 'Whatever.' to anything else.
15
16Bob's conversational partner is a purist when it comes to written communication and always follows normal rules regarding sentence punctuation in English.
17
18## Rust Installation
19
20Refer to the [exercism help page][help-page] for Rust installation and learning
21resources.
22
23## Writing the Code
24
25Execute the tests with:
26
27```bash
28$ cargo test
29```
30
31All but the first test have been ignored. After you get the first test to
32pass, open the tests source file which is located in the `tests` directory
33and remove the `#[ignore]` flag from the next test and get the tests to pass
34again. Each separate test is a function with `#[test]` flag above it.
35Continue, until you pass every test.
36
37If you wish to run all ignored tests without editing the tests source file, use:
38
39```bash
40$ cargo test -- --ignored
41```
42
43To run a specific test, for example `some_test`, you can use:
44
45```bash
46$ cargo test some_test
47```
48
49If the specific test is ignored use:
50
51```bash
52$ cargo test some_test -- --ignored
53```
54
55To learn more about Rust tests refer to the [online test documentation][rust-tests]
56
57Make sure to read the [Modules][modules] chapter if you
58haven't already, it will help you with organizing your files.
59
60## Further improvements
61
62After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
63
64To format your solution, inside the solution directory use
65
66```bash
67cargo fmt
68```
69
70To see, if your solution contains some common ineffective use cases, inside the solution directory use
71
72```bash
73cargo clippy --all-targets
74```
75
76## Submitting the solution
77
78Generally 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.
79
80## Feedback, Issues, Pull Requests
81
82The [exercism/rust](https://github.com/exercism/rust) repository on 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!
83
84If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
85
86[help-page]: https://exercism.io/tracks/rust/learning
87[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
88[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
89[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
90
91## Source
92
93Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. [http://pine.fm/LearnToProgram/?Chapter=06](http://pine.fm/LearnToProgram/?Chapter=06)
94
95## Submitting Incomplete Solutions
96It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/bob/src/lib.rs b/rust/bob/src/lib.rs
new file mode 100644
index 0000000..ae18a3d
--- /dev/null
+++ b/rust/bob/src/lib.rs
@@ -0,0 +1,75 @@
1/* The solution consists of an implementation of a simple Finite State Automaton whose states and
2 * transition messages are represented by the `State` and `Message` enums.
3 *
4 * `process(State, Message) -> State` represents the main transition function for the FSA. This
5 * allows us to compute the answer with a single visit of the input string.
6 *
7 * Note: some duplicate states (`QuestLow`, `ElseLow`) are needed in order to remember whether we
8 * have seen a lowercase character already or not. This is probably not the minimal number of
9 * states required to solve the problem.
10 */
11enum State { Nothing, QuestLow, Quest, Yell, YellQ, ElseLow, Else }
12enum Message { Whitespace, Upper, Lower, Symbol, Question }
13
14fn to_message(c: char) -> Message {
15 match c as u8 {
16 0..=32 => Message::Whitespace, // All controll characters are considered whitespace
17 63 => Message::Question,
18 65..=90 => Message::Upper,
19 97..=122 => Message::Lower,
20 _ => Message::Symbol // Anything else (numbers incl.) is a symbol
21 }
22}
23
24fn process(s: State, m: Message) -> State {
25 match s {
26 State::Nothing => match m {
27 Message::Whitespace => s,
28 Message::Upper => State::Yell,
29 Message::Lower => State::ElseLow,
30 Message::Question => State::Quest,
31 Message::Symbol => State::Else
32 },
33 State::QuestLow => match m {
34 Message::Whitespace | Message::Question => s,
35 _ => State::ElseLow
36 },
37 State::Quest => match m {
38 Message::Upper => State::Yell,
39 Message::Lower => State::ElseLow,
40 Message::Symbol => State::Else,
41 _ => s
42 },
43 State::Yell => match m {
44 Message::Lower => State::ElseLow,
45 Message::Question => State::YellQ,
46 _ => s
47 },
48 State::YellQ => match m {
49 Message::Symbol | Message::Upper => State::Yell,
50 Message::Lower => State::ElseLow,
51 _ => s
52 },
53 State::ElseLow => match m {
54 Message::Question => State::QuestLow,
55 _ => s
56 },
57 State::Else => match m {
58 Message::Upper => State::Yell,
59 Message::Lower => State::ElseLow,
60 Message::Question => State::Quest,
61 _ => s
62 }
63 }
64}
65
66pub fn reply(message: &str) -> &str {
67 let state = message.chars().fold(State::Nothing, |s, c| process(s,to_message(c)));
68 match state {
69 State::Nothing => "Fine. Be that way!",
70 State::QuestLow | State::Quest => "Sure.",
71 State::Yell => "Whoa, chill out!",
72 State::YellQ => "Calm down, I know what I'm doing!",
73 _ => "Whatever."
74 }
75}
diff --git a/rust/bob/tests/bob.rs b/rust/bob/tests/bob.rs
new file mode 100644
index 0000000..b6221eb
--- /dev/null
+++ b/rust/bob/tests/bob.rs
@@ -0,0 +1,179 @@
1fn process_response_case(phrase: &str, expected_response: &str) {
2 assert_eq!(bob::reply(phrase), expected_response);
3}
4
5#[test]
6/// stating something
7fn test_stating_something() {
8 process_response_case("Tom-ay-to, tom-aaaah-to.", "Whatever.");
9}
10
11
12#[test]
13/// ending with whitespace
14fn test_ending_with_whitespace() {
15 process_response_case("Okay if like my spacebar quite a bit? ", "Sure.");
16}
17
18
19#[test]
20/// shouting numbers
21fn test_shouting_numbers() {
22 process_response_case("1, 2, 3 GO!", "Whoa, chill out!");
23}
24
25
26#[test]
27/// other whitespace
28fn test_other_whitespace() {
29 process_response_case("\r\r ", "Fine. Be that way!");
30}
31
32
33#[test]
34/// shouting with special characters
35fn test_shouting_with_special_characters() {
36 process_response_case("ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!", "Whoa, chill out!");
37}
38
39
40#[test]
41/// talking forcefully
42fn test_talking_forcefully() {
43 process_response_case("Hi there!", "Whatever.");
44}
45
46
47#[test]
48/// prattling on
49fn test_prattling_on() {
50 process_response_case("Wait! Hang on. Are you going to be OK?", "Sure.");
51}
52
53
54#[test]
55/// forceful question
56fn test_forceful_question() {
57 process_response_case("WHAT'S GOING ON?", "Calm down, I know what I'm doing!");
58}
59
60
61#[test]
62/// shouting with no exclamation mark
63fn test_shouting_with_no_exclamation_mark() {
64 process_response_case("I HATE THE DENTIST", "Whoa, chill out!");
65}
66
67
68#[test]
69/// asking gibberish
70fn test_asking_gibberish() {
71 process_response_case("fffbbcbeab?", "Sure.");
72}
73
74
75#[test]
76/// question with no letters
77fn test_question_with_no_letters() {
78 process_response_case("4?", "Sure.");
79}
80
81
82#[test]
83/// no letters
84fn test_no_letters() {
85 process_response_case("1, 2, 3", "Whatever.");
86}
87
88
89#[test]
90/// statement containing question mark
91fn test_statement_containing_question_mark() {
92 process_response_case("Ending with ? means a question.", "Whatever.");
93}
94
95
96//NEW
97#[test]
98/// multiple line question
99fn test_multiple_line_question() {
100 process_response_case("\rDoes this cryogenic chamber make me look fat?\rNo.", "Whatever.");
101}
102
103
104#[test]
105/// non-question ending with whitespace
106fn test_nonquestion_ending_with_whitespace() {
107 process_response_case("This is a statement ending with whitespace ", "Whatever.");
108}
109
110
111#[test]
112/// shouting
113fn test_shouting() {
114 process_response_case("WATCH OUT!", "Whoa, chill out!");
115}
116
117
118#[test]
119/// non-letters with question
120fn test_nonletters_with_question() {
121 process_response_case(":) ?", "Sure.");
122}
123
124
125#[test]
126/// shouting gibberish
127fn test_shouting_gibberish() {
128 process_response_case("FCECDFCAAB", "Whoa, chill out!");
129}
130
131
132#[test]
133/// asking a question
134fn test_asking_a_question() {
135 process_response_case("Does this cryogenic chamber make me look fat?", "Sure.");
136}
137
138
139#[test]
140/// asking a numeric question
141fn test_asking_a_numeric_question() {
142 process_response_case("You are, what, like 15?", "Sure.");
143}
144
145
146#[test]
147/// silence
148fn test_silence() {
149 process_response_case("", "Fine. Be that way!");
150}
151
152
153#[test]
154/// starting with whitespace
155fn test_starting_with_whitespace() {
156 process_response_case(" hmmmmmmm...", "Whatever.");
157}
158
159
160#[test]
161/// using acronyms in regular speech
162fn test_using_acronyms_in_regular_speech() {
163 process_response_case("It's OK if you don't want to go work for NASA.", "Whatever.");
164}
165
166
167#[test]
168/// alternate silence
169fn test_alternate_silence() {
170 process_response_case(" ", "Fine. Be that way!");
171}
172
173
174#[test]
175/// prolonged silence
176fn test_prolonged_silence() {
177 process_response_case(" ", "Fine. Be that way!");
178}
179
diff --git a/rust/clock/.exercism/metadata.json b/rust/clock/.exercism/metadata.json
new file mode 100644
index 0000000..cbe366b
--- /dev/null
+++ b/rust/clock/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"clock","id":"f95dd1061dd34278af4d6838330bd546","url":"https://exercism.io/my/solutions/f95dd1061dd34278af4d6838330bd546","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/clock/.gitignore b/rust/clock/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/clock/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/clock/Cargo.toml b/rust/clock/Cargo.toml
new file mode 100644
index 0000000..376e7f1
--- /dev/null
+++ b/rust/clock/Cargo.toml
@@ -0,0 +1,6 @@
1[package]
2edition = "2018"
3name = "clock"
4version = "2.4.0"
5
6[dependencies]
diff --git a/rust/clock/README.md b/rust/clock/README.md
new file mode 100644
index 0000000..8348e33
--- /dev/null
+++ b/rust/clock/README.md
@@ -0,0 +1,102 @@
1# Clock
2
3Implement a clock that handles times without dates.
4
5You should be able to add and subtract minutes to it.
6
7Two clocks that represent the same time should be equal to each other.
8
9## Rust Traits for `.to_string()`
10
11Did you implement `.to_string()` for the `Clock` struct?
12
13If so, try implementing the
14[Display trait](https://doc.rust-lang.org/std/fmt/trait.Display.html) for `Clock` instead.
15
16Traits allow for a common way to implement functionality for various types.
17
18For additional learning, consider how you might implement `String::from` for the `Clock` type.
19You don't have to actually implement this—it's redundant with `Display`, which is generally the
20better choice when the destination type is `String`—but it's useful to have a few type-conversion
21traits in your toolkit.
22
23
24## Rust Installation
25
26Refer to the [exercism help page][help-page] for Rust installation and learning
27resources.
28
29## Writing the Code
30
31Execute the tests with:
32
33```bash
34$ cargo test
35```
36
37All but the first test have been ignored. After you get the first test to
38pass, open the tests source file which is located in the `tests` directory
39and remove the `#[ignore]` flag from the next test and get the tests to pass
40again. Each separate test is a function with `#[test]` flag above it.
41Continue, until you pass every test.
42
43If you wish to run all ignored tests without editing the tests source file, use:
44
45```bash
46$ cargo test -- --ignored
47```
48
49To run a specific test, for example `some_test`, you can use:
50
51```bash
52$ cargo test some_test
53```
54
55If the specific test is ignored use:
56
57```bash
58$ cargo test some_test -- --ignored
59```
60
61To learn more about Rust tests refer to the [online test documentation][rust-tests]
62
63Make sure to read the [Modules][modules] chapter if you
64haven't already, it will help you with organizing your files.
65
66## Further improvements
67
68After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
69
70To format your solution, inside the solution directory use
71
72```bash
73cargo fmt
74```
75
76To see, if your solution contains some common ineffective use cases, inside the solution directory use
77
78```bash
79cargo clippy --all-targets
80```
81
82## Submitting the solution
83
84Generally 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.
85
86## Feedback, Issues, Pull Requests
87
88The [exercism/rust](https://github.com/exercism/rust) repository on 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!
89
90If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
91
92[help-page]: https://exercism.io/tracks/rust/learning
93[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
94[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
95[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
96
97## Source
98
99Pairing session with Erin Drummond [https://twitter.com/ebdrummond](https://twitter.com/ebdrummond)
100
101## Submitting Incomplete Solutions
102It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/clock/src/lib.rs b/rust/clock/src/lib.rs
new file mode 100644
index 0000000..3ae8a62
--- /dev/null
+++ b/rust/clock/src/lib.rs
@@ -0,0 +1,44 @@
1use std::fmt;
2use std::ops::Add;
3
4#[derive(Debug, PartialEq, Clone, Copy)]
5pub struct Clock {
6 hours: i32,
7 minutes: i32,
8}
9
10impl fmt::Display for Clock {
11 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12 write!(f, "{:02}:{:02}", self.hours, self.minutes)
13 }
14}
15
16impl Add<i32> for Clock {
17 type Output = Self;
18
19 fn add(self, minutes: i32) -> Self {
20 Self::new(self.hours, self.minutes + minutes)
21 }
22}
23
24/* impl From<Clock> for String {
25 * fn from(c: Clock) -> String {
26 * format!("{}",c)
27 * }
28 * }
29 */
30
31impl Clock {
32 pub fn new(hours: i32, minutes: i32) -> Self {
33 let hours = hours + minutes / 60 - if minutes % 60 < 0 { 1 } else { 0 };
34 let hours = hours % 24;
35 let hours = hours + if hours < 0 { 24 } else { 0 };
36 let minutes = minutes % 60;
37 let minutes = minutes + if minutes < 0 { 60 } else { 0 };
38 Clock { hours, minutes }
39 }
40
41 pub fn add_minutes(self, minutes: i32) -> Self {
42 self + minutes
43 }
44}
diff --git a/rust/clock/tests/clock.rs b/rust/clock/tests/clock.rs
new file mode 100644
index 0000000..04f5241
--- /dev/null
+++ b/rust/clock/tests/clock.rs
@@ -0,0 +1,294 @@
1use clock::Clock;
2
3//
4// Clock Creation
5//
6
7#[test]
8fn test_on_the_hour() {
9 assert_eq!(Clock::new(8, 0).to_string(), "08:00");
10}
11
12#[test]
13fn test_past_the_hour() {
14 assert_eq!(Clock::new(11, 9).to_string(), "11:09");
15}
16
17#[test]
18fn test_midnight_is_zero_hours() {
19 assert_eq!(Clock::new(24, 0).to_string(), "00:00");
20}
21
22#[test]
23fn test_hour_rolls_over() {
24 assert_eq!(Clock::new(25, 0).to_string(), "01:00");
25}
26
27#[test]
28fn test_hour_rolls_over_continuously() {
29 assert_eq!(Clock::new(100, 0).to_string(), "04:00");
30}
31
32#[test]
33fn test_sixty_minutes_is_next_hour() {
34 assert_eq!(Clock::new(1, 60).to_string(), "02:00");
35}
36
37#[test]
38fn test_minutes_roll_over() {
39 assert_eq!(Clock::new(0, 160).to_string(), "02:40");
40}
41
42#[test]
43fn test_minutes_roll_over_continuously() {
44 assert_eq!(Clock::new(0, 1723).to_string(), "04:43");
45}
46
47#[test]
48fn test_hours_and_minutes_roll_over() {
49 assert_eq!(Clock::new(25, 160).to_string(), "03:40");
50}
51
52#[test]
53fn test_hours_and_minutes_roll_over_continuously() {
54 assert_eq!(Clock::new(201, 3001).to_string(), "11:01");
55}
56
57#[test]
58fn test_hours_and_minutes_roll_over_to_exactly_midnight() {
59 assert_eq!(Clock::new(72, 8640).to_string(), "00:00");
60}
61
62#[test]
63fn test_negative_hour() {
64 assert_eq!(Clock::new(-1, 15).to_string(), "23:15");
65}
66
67#[test]
68fn test_negative_hour_roll_over() {
69 assert_eq!(Clock::new(-25, 00).to_string(), "23:00");
70}
71
72#[test]
73fn test_negative_hour_roll_over_continuously() {
74 assert_eq!(Clock::new(-91, 00).to_string(), "05:00");
75}
76
77#[test]
78fn test_negative_minutes() {
79 assert_eq!(Clock::new(1, -40).to_string(), "00:20");
80}
81
82#[test]
83fn test_negative_minutes_roll_over() {
84 assert_eq!(Clock::new(1, -160).to_string(), "22:20");
85}
86
87#[test]
88fn test_negative_minutes_roll_over_continuously() {
89 assert_eq!(Clock::new(1, -4820).to_string(), "16:40");
90}
91
92#[test]
93fn test_negative_sixty_minutes_is_prev_hour() {
94 assert_eq!(Clock::new(2, -60).to_string(), "01:00");
95}
96
97#[test]
98fn test_negative_hour_and_minutes_both_roll_over() {
99 assert_eq!(Clock::new(-25, -160).to_string(), "20:20");
100}
101
102#[test]
103fn test_negative_hour_and_minutes_both_roll_over_continuously() {
104 assert_eq!(Clock::new(-121, -5810).to_string(), "22:10");
105}
106
107#[test]
108fn test_zero_hour_and_negative_minutes() {
109 assert_eq!(Clock::new(0, -22).to_string(), "23:38");
110}
111
112//
113// Clock Math
114//
115
116#[test]
117fn test_add_minutes() {
118 let clock = Clock::new(10, 0).add_minutes(3);
119 assert_eq!(clock.to_string(), "10:03");
120}
121
122#[test]
123fn test_add_no_minutes() {
124 let clock = Clock::new(6, 41).add_minutes(0);
125 assert_eq!(clock.to_string(), "06:41");
126}
127
128#[test]
129fn test_add_to_next_hour() {
130 let clock = Clock::new(0, 45).add_minutes(40);
131 assert_eq!(clock.to_string(), "01:25");
132}
133
134#[test]
135fn test_add_more_than_one_hour() {
136 let clock = Clock::new(10, 0).add_minutes(61);
137 assert_eq!(clock.to_string(), "11:01");
138}
139
140#[test]
141fn test_add_more_than_two_hours_with_carry() {
142 let clock = Clock::new(0, 45).add_minutes(160);
143 assert_eq!(clock.to_string(), "03:25");
144}
145
146#[test]
147fn test_add_across_midnight() {
148 let clock = Clock::new(23, 59).add_minutes(2);
149 assert_eq!(clock.to_string(), "00:01");
150}
151
152#[test]
153fn test_add_more_than_one_day() {
154 let clock = Clock::new(5, 32).add_minutes(1500);
155 assert_eq!(clock.to_string(), "06:32");
156}
157
158#[test]
159fn test_add_more_than_two_days() {
160 let clock = Clock::new(1, 1).add_minutes(3500);
161 assert_eq!(clock.to_string(), "11:21");
162}
163
164#[test]
165fn test_subtract_minutes() {
166 let clock = Clock::new(10, 3).add_minutes(-3);
167 assert_eq!(clock.to_string(), "10:00");
168}
169
170#[test]
171fn test_subtract_to_previous_hour() {
172 let clock = Clock::new(10, 3).add_minutes(-30);
173 assert_eq!(clock.to_string(), "09:33");
174}
175
176#[test]
177fn test_subtract_more_than_an_hour() {
178 let clock = Clock::new(10, 3).add_minutes(-70);
179 assert_eq!(clock.to_string(), "08:53");
180}
181
182#[test]
183fn test_subtract_across_midnight() {
184 let clock = Clock::new(0, 3).add_minutes(-4);
185 assert_eq!(clock.to_string(), "23:59");
186}
187
188#[test]
189fn test_subtract_more_than_two_hours() {
190 let clock = Clock::new(0, 0).add_minutes(-160);
191 assert_eq!(clock.to_string(), "21:20");
192}
193
194#[test]
195fn test_subtract_more_than_two_hours_with_borrow() {
196 let clock = Clock::new(6, 15).add_minutes(-160);
197 assert_eq!(clock.to_string(), "03:35");
198}
199
200#[test]
201fn test_subtract_more_than_one_day() {
202 let clock = Clock::new(5, 32).add_minutes(-1500);
203 assert_eq!(clock.to_string(), "04:32");
204}
205
206#[test]
207fn test_subtract_mores_than_two_days() {
208 let clock = Clock::new(2, 20).add_minutes(-3000);
209 assert_eq!(clock.to_string(), "00:20");
210}
211
212//
213// Test Equality
214//
215
216#[test]
217fn test_compare_clocks_for_equality() {
218 assert_eq!(Clock::new(15, 37), Clock::new(15, 37));
219}
220
221#[test]
222fn test_compare_clocks_a_minute_apart() {
223 assert_ne!(Clock::new(15, 36), Clock::new(15, 37));
224}
225
226#[test]
227fn test_compare_clocks_an_hour_apart() {
228 assert_ne!(Clock::new(14, 37), Clock::new(15, 37));
229}
230
231#[test]
232fn test_compare_clocks_with_hour_overflow() {
233 assert_eq!(Clock::new(10, 37), Clock::new(34, 37));
234}
235
236#[test]
237fn test_compare_clocks_with_hour_overflow_by_several_days() {
238 assert_eq!(Clock::new(3, 11), Clock::new(99, 11));
239}
240
241#[test]
242fn test_compare_clocks_with_negative_hour() {
243 assert_eq!(Clock::new(22, 40), Clock::new(-2, 40));
244}
245
246#[test]
247fn test_compare_clocks_with_negative_hour_that_wraps() {
248 assert_eq!(Clock::new(17, 3), Clock::new(-31, 3));
249}
250
251#[test]
252fn test_compare_clocks_with_negative_hour_that_wraps_multiple_times() {
253 assert_eq!(Clock::new(13, 49), Clock::new(-83, 49));
254}
255
256#[test]
257fn test_compare_clocks_with_minutes_overflow() {
258 assert_eq!(Clock::new(0, 1), Clock::new(0, 1441));
259}
260
261#[test]
262fn test_compare_clocks_with_minutes_overflow_by_several_days() {
263 assert_eq!(Clock::new(2, 2), Clock::new(2, 4322));
264}
265
266#[test]
267fn test_compare_clocks_with_negative_minute() {
268 assert_eq!(Clock::new(2, 40), Clock::new(3, -20))
269}
270
271#[test]
272fn test_compare_clocks_with_negative_minute_that_wraps() {
273 assert_eq!(Clock::new(4, 10), Clock::new(5, -1490))
274}
275
276#[test]
277fn test_compare_clocks_with_negative_minute_that_wraps_multiple() {
278 assert_eq!(Clock::new(6, 15), Clock::new(6, -4305))
279}
280
281#[test]
282fn test_compare_clocks_with_negative_hours_and_minutes() {
283 assert_eq!(Clock::new(7, 32), Clock::new(-12, -268))
284}
285
286#[test]
287fn test_compare_clocks_with_negative_hours_and_minutes_that_wrap() {
288 assert_eq!(Clock::new(18, 7), Clock::new(-54, -11_513))
289}
290
291#[test]
292fn test_compare_full_clock_and_zeroed_clock() {
293 assert_eq!(Clock::new(24, 0), Clock::new(0, 0))
294}
diff --git a/rust/difference-of-squares/.exercism/metadata.json b/rust/difference-of-squares/.exercism/metadata.json
new file mode 100644
index 0000000..7e844ee
--- /dev/null
+++ b/rust/difference-of-squares/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"difference-of-squares","id":"9ad3be19e839435282ee30ce156fdb07","url":"https://exercism.io/my/solutions/9ad3be19e839435282ee30ce156fdb07","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/difference-of-squares/.gitignore b/rust/difference-of-squares/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/difference-of-squares/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/difference-of-squares/Cargo.toml b/rust/difference-of-squares/Cargo.toml
new file mode 100644
index 0000000..41e2b29
--- /dev/null
+++ b/rust/difference-of-squares/Cargo.toml
@@ -0,0 +1,4 @@
1[package]
2edition = "2018"
3name = "difference-of-squares"
4version = "1.2.0"
diff --git a/rust/difference-of-squares/README.md b/rust/difference-of-squares/README.md
new file mode 100644
index 0000000..d940ad5
--- /dev/null
+++ b/rust/difference-of-squares/README.md
@@ -0,0 +1,97 @@
1# Difference Of Squares
2
3Find the difference between the square of the sum and the sum of the squares of the first N natural numbers.
4
5The square of the sum of the first ten natural numbers is
6(1 + 2 + ... + 10)² = 55² = 3025.
7
8The sum of the squares of the first ten natural numbers is
91² + 2² + ... + 10² = 385.
10
11Hence the difference between the square of the sum of the first
12ten natural numbers and the sum of the squares of the first ten
13natural numbers is 3025 - 385 = 2640.
14
15You are not expected to discover an efficient solution to this yourself from
16first principles; research is allowed, indeed, encouraged. Finding the best
17algorithm for the problem is a key skill in software engineering.
18
19## Rust Installation
20
21Refer to the [exercism help page][help-page] for Rust installation and learning
22resources.
23
24## Writing the Code
25
26Execute the tests with:
27
28```bash
29$ cargo test
30```
31
32All but the first test have been ignored. After you get the first test to
33pass, open the tests source file which is located in the `tests` directory
34and remove the `#[ignore]` flag from the next test and get the tests to pass
35again. Each separate test is a function with `#[test]` flag above it.
36Continue, until you pass every test.
37
38If you wish to run all ignored tests without editing the tests source file, use:
39
40```bash
41$ cargo test -- --ignored
42```
43
44To run a specific test, for example `some_test`, you can use:
45
46```bash
47$ cargo test some_test
48```
49
50If the specific test is ignored use:
51
52```bash
53$ cargo test some_test -- --ignored
54```
55
56To learn more about Rust tests refer to the [online test documentation][rust-tests]
57
58Make sure to read the [Modules][modules] chapter if you
59haven't already, it will help you with organizing your files.
60
61## Further improvements
62
63After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
64
65To format your solution, inside the solution directory use
66
67```bash
68cargo fmt
69```
70
71To see, if your solution contains some common ineffective use cases, inside the solution directory use
72
73```bash
74cargo clippy --all-targets
75```
76
77## Submitting the solution
78
79Generally 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.
80
81## Feedback, Issues, Pull Requests
82
83The [exercism/rust](https://github.com/exercism/rust) repository on 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!
84
85If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
86
87[help-page]: https://exercism.io/tracks/rust/learning
88[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
89[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
90[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
91
92## Source
93
94Problem 6 at Project Euler [http://projecteuler.net/problem=6](http://projecteuler.net/problem=6)
95
96## Submitting Incomplete Solutions
97It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/difference-of-squares/src/lib.rs b/rust/difference-of-squares/src/lib.rs
new file mode 100644
index 0000000..4599733
--- /dev/null
+++ b/rust/difference-of-squares/src/lib.rs
@@ -0,0 +1,14 @@
1/// Implements square of Gauss' formula
2pub fn square_of_sum(n: u32) -> u32 {
3 (n * (n + 1) / 2).pow(2)
4}
5
6/// Implements the formula reported in Wolfram|Alpha at this
7/// [link](https://www.wolframalpha.com/input/?i=sum+of+squares&assumption=%7B%22F%22%2C+%22SumOfSquaresOfIntegers%22%2C+%22sumlowerlimit%22%7D+-%3E%221%22&assumption=%7B%22F%22%2C+%22SumOfSquaresOfIntegers%22%2C+%22sumupperlimit2%22%7D+-%3E%22n%22)
8pub fn sum_of_squares(n: u32) -> u32 {
9 n * (1 + n) * (1 + 2 * n) / 6
10}
11
12pub fn difference(n: u32) -> u32 {
13 square_of_sum(n) - sum_of_squares(n)
14}
diff --git a/rust/difference-of-squares/tests/difference-of-squares.rs b/rust/difference-of-squares/tests/difference-of-squares.rs
new file mode 100644
index 0000000..4a029b3
--- /dev/null
+++ b/rust/difference-of-squares/tests/difference-of-squares.rs
@@ -0,0 +1,46 @@
1use difference_of_squares as squares;
2
3#[test]
4fn test_square_of_sum_1() {
5 assert_eq!(1, squares::square_of_sum(1));
6}
7
8#[test]
9fn test_square_of_sum_5() {
10 assert_eq!(225, squares::square_of_sum(5));
11}
12
13#[test]
14fn test_square_of_sum_100() {
15 assert_eq!(25_502_500, squares::square_of_sum(100));
16}
17
18#[test]
19fn test_sum_of_squares_1() {
20 assert_eq!(1, squares::sum_of_squares(1));
21}
22
23#[test]
24fn test_sum_of_squares_5() {
25 assert_eq!(55, squares::sum_of_squares(5));
26}
27
28#[test]
29fn test_sum_of_squares_100() {
30 assert_eq!(338_350, squares::sum_of_squares(100));
31}
32
33#[test]
34fn test_difference_1() {
35 assert_eq!(0, squares::difference(1));
36}
37
38#[test]
39fn test_difference_5() {
40 assert_eq!(170, squares::difference(5));
41}
42
43#[test]
44fn test_difference_100() {
45 assert_eq!(25_164_150, squares::difference(100));
46}
diff --git a/rust/dot-dsl/.exercism/metadata.json b/rust/dot-dsl/.exercism/metadata.json
new file mode 100644
index 0000000..5399056
--- /dev/null
+++ b/rust/dot-dsl/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"dot-dsl","id":"57ca2e502fdf482aa52e91c4f4f7f51e","url":"https://exercism.io/my/solutions/57ca2e502fdf482aa52e91c4f4f7f51e","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/dot-dsl/.gitignore b/rust/dot-dsl/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/dot-dsl/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/dot-dsl/Cargo.toml b/rust/dot-dsl/Cargo.toml
new file mode 100644
index 0000000..3da0d67
--- /dev/null
+++ b/rust/dot-dsl/Cargo.toml
@@ -0,0 +1,7 @@
1[package]
2edition = "2018"
3name = "dot-dsl"
4version = "0.1.0"
5
6[dependencies]
7maplit = "1.0.1"
diff --git a/rust/dot-dsl/README.md b/rust/dot-dsl/README.md
new file mode 100644
index 0000000..29e0e7a
--- /dev/null
+++ b/rust/dot-dsl/README.md
@@ -0,0 +1,121 @@
1# DOT DSL
2
3A [Domain Specific Language (DSL)](https://en.wikipedia.org/wiki/Domain-specific_language) is a
4small language optimized for a specific domain. Since a DSL is
5targeted, it can greatly impact productivity/understanding by allowing the
6writer to declare *what* they want rather than *how*.
7
8One problem area where they are applied are complex customizations/configurations.
9
10For example the [DOT language](https://en.wikipedia.org/wiki/DOT_(graph_description_language)) allows
11you to write a textual description of a graph which is then transformed into a picture by one of
12the [Graphviz](http://graphviz.org/) tools (such as `dot`). A simple graph looks like this:
13
14 graph {
15 graph [bgcolor="yellow"]
16 a [color="red"]
17 b [color="blue"]
18 a -- b [color="green"]
19 }
20
21Putting this in a file `example.dot` and running `dot example.dot -T png
22-o example.png` creates an image `example.png` with red and blue circle
23connected by a green line on a yellow background.
24
25Write a Domain Specific Language similar to the Graphviz dot language.
26
27Our DSL is similar to the Graphviz dot language in that our DSL will be used
28to create graph data structures. However, unlike the DOT Language, our DSL will
29be an internal DSL for use only in our language.
30
31More information about the difference between internal and external DSLs can be
32found [here](https://martinfowler.com/bliki/DomainSpecificLanguage.html).
33
34## Builder pattern
35
36This exercise expects you to build several structs using `builder pattern`.
37In short, this pattern allows you to split the construction function of your struct, that contains a lot of arguments, into
38several separate functions. This approach gives you the means to make compact but highly-flexible struct construction and
39configuration.
40You can read more about it on the [following page](https://doc.rust-lang.org/1.0.0/style/ownership/builders.html).
41
42
43## Rust Installation
44
45Refer to the [exercism help page][help-page] for Rust installation and learning
46resources.
47
48## Writing the Code
49
50Execute the tests with:
51
52```bash
53$ cargo test
54```
55
56All but the first test have been ignored. After you get the first test to
57pass, open the tests source file which is located in the `tests` directory
58and remove the `#[ignore]` flag from the next test and get the tests to pass
59again. Each separate test is a function with `#[test]` flag above it.
60Continue, until you pass every test.
61
62If you wish to run all ignored tests without editing the tests source file, use:
63
64```bash
65$ cargo test -- --ignored
66```
67
68To run a specific test, for example `some_test`, you can use:
69
70```bash
71$ cargo test some_test
72```
73
74If the specific test is ignored use:
75
76```bash
77$ cargo test some_test -- --ignored
78```
79
80To learn more about Rust tests refer to the [online test documentation][rust-tests]
81
82Make sure to read the [Modules][modules] chapter if you
83haven't already, it will help you with organizing your files.
84
85## Further improvements
86
87After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
88
89To format your solution, inside the solution directory use
90
91```bash
92cargo fmt
93```
94
95To see, if your solution contains some common ineffective use cases, inside the solution directory use
96
97```bash
98cargo clippy --all-targets
99```
100
101## Submitting the solution
102
103Generally 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.
104
105## Feedback, Issues, Pull Requests
106
107The [exercism/rust](https://github.com/exercism/rust) repository on 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!
108
109If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
110
111[help-page]: https://exercism.io/tracks/rust/learning
112[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
113[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
114[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
115
116## Source
117
118Wikipedia [https://en.wikipedia.org/wiki/DOT_(graph_description_language)](https://en.wikipedia.org/wiki/DOT_(graph_description_language))
119
120## Submitting Incomplete Solutions
121It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/dot-dsl/src/lib.rs b/rust/dot-dsl/src/lib.rs
new file mode 100644
index 0000000..654ee09
--- /dev/null
+++ b/rust/dot-dsl/src/lib.rs
@@ -0,0 +1,119 @@
1pub mod graph {
2
3 use graph_items::edge::Edge;
4 use graph_items::node::Node;
5 use std::collections::HashMap;
6
7 pub mod graph_items {
8
9 pub mod node {
10
11 use std::collections::HashMap;
12
13 #[derive(Default, Debug, PartialEq, Eq, Clone)]
14 pub struct Node<'a> {
15 pub name: &'a str,
16 attrs: HashMap<String, String>,
17 }
18
19 impl<'a> Node<'a> {
20 pub fn new(name: &'a str) -> Node<'a> {
21 Node {
22 name,
23 ..Default::default()
24 }
25 }
26
27 pub fn with_attrs(mut self, attrs: &[(&'a str, &'a str)]) -> Node<'a> {
28 for (key, value) in attrs {
29 self.attrs.insert(key.to_string(), value.to_string());
30 }
31 self
32 }
33
34 pub fn get_attr(&self, key: &str) -> Option<&str> {
35 self.attrs.get(key).map(|s| &s[..])
36 }
37 }
38 }
39
40 pub mod edge {
41
42 use std::collections::HashMap;
43
44 #[derive(Default, Debug, PartialEq, Eq, Clone)]
45 pub struct Edge<'a> {
46 pub x: &'a str,
47 pub y: &'a str,
48 attrs: HashMap<String, String>,
49 }
50
51 impl<'a> Edge<'a> {
52 pub fn new(x: &'a str, y: &'a str) -> Edge<'a> {
53 Edge {
54 x,
55 y,
56 ..Default::default()
57 }
58 }
59
60 pub fn with_attrs(mut self, attrs: &[(&'a str, &'a str)]) -> Edge<'a> {
61 for (key, value) in attrs {
62 self.attrs.insert(key.to_string(), value.to_string());
63 }
64 self
65 }
66
67 pub fn get_attr(&self, key: &str) -> Option<&str> {
68 self.attrs.get(key).map(|s| &s[..])
69 }
70 }
71 }
72 }
73
74 #[derive(Default, Debug)]
75 pub struct Graph<'a> {
76 pub nodes: Vec<Node<'a>>,
77 pub edges: Vec<Edge<'a>>,
78 pub attrs: HashMap<String, String>,
79 }
80
81 impl<'a> Graph<'a> {
82 pub fn new() -> Self {
83 Default::default()
84 }
85
86 pub fn with_attrs(mut self, attrs: &[(&'a str, &'a str)]) -> Graph<'a> {
87 for (key, value) in attrs {
88 self.attrs.insert(key.to_string(), value.to_string());
89 }
90 self
91 }
92
93 pub fn with_nodes(mut self, nodes: &[Node<'a>]) -> Graph<'a> {
94 for node in nodes {
95 self.nodes.push(node.clone());
96 }
97 self
98 }
99
100 pub fn with_edges(mut self, edges: &[Edge<'a>]) -> Graph<'a> {
101 for edge in edges {
102 self.edges.push(edge.clone())
103 }
104 self
105 }
106
107 pub fn get_node(&self, name: &str) -> Option<&Node<'a>> {
108 self.nodes.iter().find(|&node| node.name == name)
109 }
110
111 pub fn get_edge(&self, x: &str, y: &str) -> Option<&Edge<'a>> {
112 self.edges.iter().find(|&edge| edge.x == x && edge.y == y)
113 }
114
115 pub fn get_attr(&self, key: &str) -> Option<&str> {
116 self.attrs.get(key).map(|s| &s[..])
117 }
118 }
119}
diff --git a/rust/dot-dsl/tests/dot-dsl.rs b/rust/dot-dsl/tests/dot-dsl.rs
new file mode 100644
index 0000000..ae469b7
--- /dev/null
+++ b/rust/dot-dsl/tests/dot-dsl.rs
@@ -0,0 +1,138 @@
1use dot_dsl::graph::graph_items::edge::Edge;
2use dot_dsl::graph::graph_items::node::Node;
3use dot_dsl::graph::Graph;
4use maplit::hashmap;
5
6#[test]
7fn test_empty_graph() {
8 let graph = Graph::new();
9
10 assert!(graph.nodes.is_empty());
11
12 assert!(graph.edges.is_empty());
13
14 assert!(graph.attrs.is_empty());
15}
16
17#[test]
18fn test_graph_with_one_node() {
19 let nodes = vec![Node::new("a")];
20
21 let graph = Graph::new().with_nodes(&nodes);
22
23 assert!(graph.edges.is_empty());
24
25 assert!(graph.attrs.is_empty());
26
27 assert_eq!(graph.nodes, vec![Node::new("a")]);
28}
29
30#[test]
31fn test_graph_with_one_node_with_keywords() {
32 let nodes = vec![Node::new("a").with_attrs(&[("color", "green")])];
33
34 let graph = Graph::new().with_nodes(&nodes);
35
36 assert!(graph.edges.is_empty());
37
38 assert!(graph.attrs.is_empty());
39
40 assert_eq!(
41 graph.nodes,
42 vec![Node::new("a").with_attrs(&[("color", "green")])]
43 );
44}
45
46#[test]
47fn test_graph_with_one_edge() {
48 let edges = vec![Edge::new("a", "b")];
49
50 let graph = Graph::new().with_edges(&edges);
51
52 assert!(graph.nodes.is_empty());
53
54 assert!(graph.attrs.is_empty());
55
56 assert_eq!(graph.edges, vec![Edge::new("a", "b")]);
57}
58
59#[test]
60fn test_graph_with_one_attribute() {
61 let graph = Graph::new().with_attrs(&[("foo", "1")]);
62
63 let expected_attrs = hashmap! {
64 "foo".to_string() => "1".to_string(),
65 };
66
67 assert!(graph.nodes.is_empty());
68
69 assert!(graph.edges.is_empty());
70
71 assert_eq!(graph.attrs, expected_attrs);
72}
73
74#[test]
75fn test_graph_with_attributes() {
76 let nodes = vec![
77 Node::new("a").with_attrs(&[("color", "green")]),
78 Node::new("c"),
79 Node::new("b").with_attrs(&[("label", "Beta!")]),
80 ];
81
82 let edges = vec![
83 Edge::new("b", "c"),
84 Edge::new("a", "b").with_attrs(&[("color", "blue")]),
85 ];
86
87 let attrs = vec![("foo", "1"), ("title", "Testing Attrs"), ("bar", "true")];
88
89 let expected_attrs = hashmap! {
90 "foo".to_string() => "1".to_string(),
91 "title".to_string() => "Testing Attrs".to_string(),
92 "bar".to_string() => "true".to_string(),
93 };
94
95 let graph = Graph::new()
96 .with_nodes(&nodes)
97 .with_edges(&edges)
98 .with_attrs(&attrs);
99
100 assert_eq!(
101 graph.nodes,
102 vec![
103 Node::new("a").with_attrs(&[("color", "green")]),
104 Node::new("c"),
105 Node::new("b").with_attrs(&[("label", "Beta!")]),
106 ]
107 );
108
109 assert_eq!(
110 graph.edges,
111 vec![
112 Edge::new("b", "c"),
113 Edge::new("a", "b").with_attrs(&[("color", "blue")]),
114 ]
115 );
116
117 assert_eq!(graph.attrs, expected_attrs);
118}
119
120#[test]
121fn test_graph_stores_attributes() {
122 let attributes = [("foo", "bar"), ("bat", "baz"), ("bim", "bef")];
123 let graph = Graph::new().with_nodes(
124 &["a", "b", "c"]
125 .iter()
126 .zip(attributes.iter())
127 .map(|(name, &attr)| Node::new(&name).with_attrs(&[attr]))
128 .collect::<Vec<_>>(),
129 );
130
131 assert_eq!(
132 graph
133 .get_node("c")
134 .expect("node must be stored")
135 .get_attr("bim"),
136 Some("bef")
137 );
138}
diff --git a/rust/gigasecond/.exercism/metadata.json b/rust/gigasecond/.exercism/metadata.json
new file mode 100644
index 0000000..7bd17ac
--- /dev/null
+++ b/rust/gigasecond/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"gigasecond","id":"2131caf991cf446292290bef2e6d64da","url":"https://exercism.io/my/solutions/2131caf991cf446292290bef2e6d64da","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/gigasecond/.gitignore b/rust/gigasecond/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/gigasecond/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/gigasecond/Cargo.toml b/rust/gigasecond/Cargo.toml
new file mode 100644
index 0000000..1a8fb2c
--- /dev/null
+++ b/rust/gigasecond/Cargo.toml
@@ -0,0 +1,8 @@
1[package]
2edition = "2018"
3name = "gigasecond"
4version = "2.0.0"
5
6[dependencies]
7chrono = "0.4"
8
diff --git a/rust/gigasecond/README.md b/rust/gigasecond/README.md
new file mode 100644
index 0000000..9368f91
--- /dev/null
+++ b/rust/gigasecond/README.md
@@ -0,0 +1,89 @@
1# Gigasecond
2
3Given a moment, determine the moment that would be after a gigasecond
4has passed.
5
6A gigasecond is 10^9 (1,000,000,000) seconds.
7
8If you're unsure what operations you can perform on `DateTime<Utc>` take a look at the [chrono crate](https://docs.rs/chrono) which is listed as a dependency in the `Cargo.toml` file for this exercise.
9
10
11## Rust Installation
12
13Refer to the [exercism help page][help-page] for Rust installation and learning
14resources.
15
16## Writing the Code
17
18Execute the tests with:
19
20```bash
21$ cargo test
22```
23
24All but the first test have been ignored. After you get the first test to
25pass, open the tests source file which is located in the `tests` directory
26and remove the `#[ignore]` flag from the next test and get the tests to pass
27again. Each separate test is a function with `#[test]` flag above it.
28Continue, until you pass every test.
29
30If you wish to run all ignored tests without editing the tests source file, use:
31
32```bash
33$ cargo test -- --ignored
34```
35
36To run a specific test, for example `some_test`, you can use:
37
38```bash
39$ cargo test some_test
40```
41
42If the specific test is ignored use:
43
44```bash
45$ cargo test some_test -- --ignored
46```
47
48To learn more about Rust tests refer to the [online test documentation][rust-tests]
49
50Make sure to read the [Modules][modules] chapter if you
51haven't already, it will help you with organizing your files.
52
53## Further improvements
54
55After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
56
57To format your solution, inside the solution directory use
58
59```bash
60cargo fmt
61```
62
63To see, if your solution contains some common ineffective use cases, inside the solution directory use
64
65```bash
66cargo clippy --all-targets
67```
68
69## Submitting the solution
70
71Generally 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.
72
73## Feedback, Issues, Pull Requests
74
75The [exercism/rust](https://github.com/exercism/rust) repository on 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!
76
77If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
78
79[help-page]: https://exercism.io/tracks/rust/learning
80[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
81[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
82[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
83
84## Source
85
86Chapter 9 in Chris Pine's online Learn to Program tutorial. [http://pine.fm/LearnToProgram/?Chapter=09](http://pine.fm/LearnToProgram/?Chapter=09)
87
88## Submitting Incomplete Solutions
89It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/gigasecond/src/lib.rs b/rust/gigasecond/src/lib.rs
new file mode 100644
index 0000000..0abd90b
--- /dev/null
+++ b/rust/gigasecond/src/lib.rs
@@ -0,0 +1,7 @@
1use chrono::{DateTime, Duration, Utc};
2
3// Returns a Utc DateTime one billion seconds after start.
4pub fn after(start: DateTime<Utc>) -> DateTime<Utc> {
5 let gigasecond = Duration::seconds(1_000_000_000);
6 start + gigasecond
7}
diff --git a/rust/gigasecond/tests/gigasecond.rs b/rust/gigasecond/tests/gigasecond.rs
new file mode 100644
index 0000000..4fe139b
--- /dev/null
+++ b/rust/gigasecond/tests/gigasecond.rs
@@ -0,0 +1,51 @@
1use chrono::{TimeZone, Utc};
2
3#[test]
4fn test_date() {
5 let start_date = Utc.ymd(2011, 4, 25).and_hms(0, 0, 0);
6
7 assert_eq!(
8 gigasecond::after(start_date),
9 Utc.ymd(2043, 1, 1).and_hms(1, 46, 40)
10 );
11}
12
13#[test]
14fn test_another_date() {
15 let start_date = Utc.ymd(1977, 6, 13).and_hms(0, 0, 0);
16
17 assert_eq!(
18 gigasecond::after(start_date),
19 Utc.ymd(2009, 2, 19).and_hms(1, 46, 40)
20 );
21}
22
23#[test]
24fn test_third_date() {
25 let start_date = Utc.ymd(1959, 7, 19).and_hms(0, 0, 0);
26
27 assert_eq!(
28 gigasecond::after(start_date),
29 Utc.ymd(1991, 3, 27).and_hms(1, 46, 40)
30 );
31}
32
33#[test]
34fn test_datetime() {
35 let start_date = Utc.ymd(2015, 1, 24).and_hms(22, 0, 0);
36
37 assert_eq!(
38 gigasecond::after(start_date),
39 Utc.ymd(2046, 10, 2).and_hms(23, 46, 40)
40 );
41}
42
43#[test]
44fn test_another_datetime() {
45 let start_date = Utc.ymd(2015, 1, 24).and_hms(23, 59, 59);
46
47 assert_eq!(
48 gigasecond::after(start_date),
49 Utc.ymd(2046, 10, 3).and_hms(1, 46, 39)
50 );
51}
diff --git a/rust/grains/.exercism/metadata.json b/rust/grains/.exercism/metadata.json
new file mode 100644
index 0000000..c20eb3a
--- /dev/null
+++ b/rust/grains/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"grains","id":"cfeb306e73c0483aa2a6e1fcc8d1029b","url":"https://exercism.io/my/solutions/cfeb306e73c0483aa2a6e1fcc8d1029b","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/grains/.gitignore b/rust/grains/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/grains/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/grains/Cargo.toml b/rust/grains/Cargo.toml
new file mode 100644
index 0000000..6bf141e
--- /dev/null
+++ b/rust/grains/Cargo.toml
@@ -0,0 +1,4 @@
1[package]
2edition = "2018"
3name = "grains"
4version = "1.2.0"
diff --git a/rust/grains/README.md b/rust/grains/README.md
new file mode 100644
index 0000000..e54de2c
--- /dev/null
+++ b/rust/grains/README.md
@@ -0,0 +1,107 @@
1# Grains
2
3Calculate the number of grains of wheat on a chessboard given that the number
4on each square doubles.
5
6There once was a wise servant who saved the life of a prince. The king
7promised to pay whatever the servant could dream up. Knowing that the
8king loved chess, the servant told the king he would like to have grains
9of wheat. One grain on the first square of a chess board, with the number
10of grains doubling on each successive square.
11
12There are 64 squares on a chessboard (where square 1 has one grain, square 2 has two grains, and so on).
13
14Write code that shows:
15- how many grains were on a given square, and
16- the total number of grains on the chessboard
17
18## For bonus points
19
20Did you get the tests passing and the code clean? If you want to, these
21are some additional things you could try:
22
23- Optimize for speed.
24- Optimize for readability.
25
26Then please share your thoughts in a comment on the submission. Did this
27experiment make the code better? Worse? Did you learn anything from it?
28
29## Rust Installation
30
31Refer to the [exercism help page][help-page] for Rust installation and learning
32resources.
33
34## Writing the Code
35
36Execute the tests with:
37
38```bash
39$ cargo test
40```
41
42All but the first test have been ignored. After you get the first test to
43pass, open the tests source file which is located in the `tests` directory
44and remove the `#[ignore]` flag from the next test and get the tests to pass
45again. Each separate test is a function with `#[test]` flag above it.
46Continue, until you pass every test.
47
48If you wish to run all ignored tests without editing the tests source file, use:
49
50```bash
51$ cargo test -- --ignored
52```
53
54To run a specific test, for example `some_test`, you can use:
55
56```bash
57$ cargo test some_test
58```
59
60If the specific test is ignored use:
61
62```bash
63$ cargo test some_test -- --ignored
64```
65
66To learn more about Rust tests refer to the [online test documentation][rust-tests]
67
68Make sure to read the [Modules][modules] chapter if you
69haven't already, it will help you with organizing your files.
70
71## Further improvements
72
73After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
74
75To format your solution, inside the solution directory use
76
77```bash
78cargo fmt
79```
80
81To see, if your solution contains some common ineffective use cases, inside the solution directory use
82
83```bash
84cargo clippy --all-targets
85```
86
87## Submitting the solution
88
89Generally 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.
90
91## Feedback, Issues, Pull Requests
92
93The [exercism/rust](https://github.com/exercism/rust) repository on 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!
94
95If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
96
97[help-page]: https://exercism.io/tracks/rust/learning
98[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
99[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
100[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
101
102## Source
103
104JavaRanch Cattle Drive, exercise 6 [http://www.javaranch.com/grains.jsp](http://www.javaranch.com/grains.jsp)
105
106## Submitting Incomplete Solutions
107It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/grains/src/lib.rs b/rust/grains/src/lib.rs
new file mode 100644
index 0000000..05449be
--- /dev/null
+++ b/rust/grains/src/lib.rs
@@ -0,0 +1,23 @@
1pub fn square(s: u32) -> u64 {
2 assert!(s > 0 && s < 65,"Square must be between 1 and 64");
3 2_u64.pow(s-1)
4}
5
6/// This version uses the already defined `square(s)` function.
7///
8/// There is also a faster way to compute this according to
9/// [Wolfram|Alpha](https://www.wolframalpha.com/input/?i=sum_0%5En+2%5En)
10///
11/// 2_u64.pow(65) - 1 == 18_446_744_073_709_551_615
12///
13/// this solution however doesn't work because
14///
15/// 2_u64.pow(65) == 18_446_744_073_709_551_616
16///
17/// which overflows since
18///
19/// std::u64::MAX == 18_446_744_073_709_551_615
20///
21pub fn total() -> u64 {
22 (1..65).map(square).sum() // std::u64::MAX
23}
diff --git a/rust/grains/tests/grains.rs b/rust/grains/tests/grains.rs
new file mode 100644
index 0000000..405eb4d
--- /dev/null
+++ b/rust/grains/tests/grains.rs
@@ -0,0 +1,65 @@
1use grains;
2
3fn process_square_case(input: u32, expected: u64) {
4 assert_eq!(grains::square(input), expected);
5}
6
7#[test]
8/// 1
9fn test_1() {
10 process_square_case(1, 1);
11}
12
13#[test]
14/// 2
15fn test_2() {
16 process_square_case(2, 2);
17}
18
19#[test]
20/// 3
21fn test_3() {
22 process_square_case(3, 4);
23}
24
25#[test]
26/// 4
27fn test_4() {
28 process_square_case(4, 8);
29}
30
31//NEW
32#[test]
33/// 16
34fn test_16() {
35 process_square_case(16, 32_768);
36}
37
38#[test]
39/// 32
40fn test_32() {
41 process_square_case(32, 2_147_483_648);
42}
43
44#[test]
45/// 64
46fn test_64() {
47 process_square_case(64, 9_223_372_036_854_775_808);
48}
49
50#[test]
51#[should_panic(expected = "Square must be between 1 and 64")]
52fn test_square_0_raises_an_exception() {
53 grains::square(0);
54}
55
56#[test]
57#[should_panic(expected = "Square must be between 1 and 64")]
58fn test_square_greater_than_64_raises_an_exception() {
59 grains::square(65);
60}
61
62#[test]
63fn test_returns_the_total_number_of_grains_on_the_board() {
64 assert_eq!(grains::total(), 18_446_744_073_709_551_615);
65}
diff --git a/rust/hello-world/.exercism/metadata.json b/rust/hello-world/.exercism/metadata.json
new file mode 100644
index 0000000..0e3e354
--- /dev/null
+++ b/rust/hello-world/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"hello-world","id":"aac7852c428e494ca701dc74d200c468","url":"https://exercism.io/my/solutions/aac7852c428e494ca701dc74d200c468","handle":"dyamon","is_requester":true,"auto_approve":true} \ No newline at end of file
diff --git a/rust/hello-world/.gitignore b/rust/hello-world/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/hello-world/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/hello-world/Cargo.toml b/rust/hello-world/Cargo.toml
new file mode 100644
index 0000000..4d9f8bb
--- /dev/null
+++ b/rust/hello-world/Cargo.toml
@@ -0,0 +1,4 @@
1[package]
2edition = "2018"
3name = "hello-world"
4version = "1.1.0"
diff --git a/rust/hello-world/GETTING_STARTED.md b/rust/hello-world/GETTING_STARTED.md
new file mode 100644
index 0000000..5eeea95
--- /dev/null
+++ b/rust/hello-world/GETTING_STARTED.md
@@ -0,0 +1,92 @@
1# Getting Started
2
3These exercises lean on Test-Driven Development (TDD), but they're not
4an exact match.
5
6The following steps assume that you are in the same directory as the exercise.
7
8You must have rust installed.
9Follow the [Installation chapter in the Rust book](https://doc.rust-lang.org/book/ch01-01-installation.html).
10The [Rust language section](http://exercism.io/languages/rust)
11section from exercism is also useful.
12
13## Step 1
14
15Run the test suite. It can be run with `cargo`, which is installed with rust.
16
17```
18$ cargo test
19```
20
21This will compile the `hello-world` crate and run the test, which fails.
22
23```
24running 1 test
25test test_hello_world ... FAILED
26
27failures:
28
29---- test_hello_world stdout ----
30thread 'test_hello_world' panicked at 'assertion failed: `(left == right)`
31(left: `"Hello, World!"`, right: `"Goodbye, World!"`)', tests/hello-world.rs:5
32
33failures:
34 test_hello_world
35
36test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
37```
38
39### Understanding Test Failures
40
41The `test_hello_world` failure states that it is expecting the value,
42`"Hello, World!"`, to be returned from `hello()`.
43The left side of the assertion (at line 5) should be equal to the right side.
44
45```
46---- test_hello_world stdout ----
47thread 'test_hello_world' panicked at 'assertion failed: `(left == right)`
48(left: `"Hello, World!"`, right: `"Goodbye, World!"`)', tests/hello-world.rs:5
49```
50
51### Fixing the Error
52
53To fix it, open up `src/lib.rs` and change the `hello` function to return
54`"Hello, World!"` instead of `"Goodbye, World!"`.
55
56```rust
57pub fn hello() -> &'static str {
58 "Hello, World!"
59}
60```
61
62## Step 2
63
64Run the test again. This time, it will pass.
65
66```
67running 0 tests
68
69test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
70
71 Running target/debug/deps/hello_world-bd1f06dc726ef14f
72
73running 1 test
74test test_hello_world ... ok
75
76test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
77
78 Doc-tests hello-world
79
80running 0 tests
81
82test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
83```
84
85## Submit
86
87Once the test is passing, you can submit your code with the following
88command:
89
90```
91$ exercism submit src/lib.rs
92```
diff --git a/rust/hello-world/README.md b/rust/hello-world/README.md
new file mode 100644
index 0000000..775dd89
--- /dev/null
+++ b/rust/hello-world/README.md
@@ -0,0 +1,95 @@
1# Hello World
2
3The classical introductory exercise. Just say "Hello, World!".
4
5["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is
6the traditional first program for beginning programming in a new language
7or environment.
8
9The objectives are simple:
10
11- Write a function that returns the string "Hello, World!".
12- Run the test suite and make sure that it succeeds.
13- Submit your solution and check it at the website.
14
15If everything goes well, you will be ready to fetch your first real exercise.
16
17## Rust Installation
18
19Refer to the [exercism help page][help-page] for Rust installation and learning
20resources.
21
22## Writing the Code
23
24Execute the tests with:
25
26```bash
27$ cargo test
28```
29
30All but the first test have been ignored. After you get the first test to
31pass, open the tests source file which is located in the `tests` directory
32and remove the `#[ignore]` flag from the next test and get the tests to pass
33again. Each separate test is a function with `#[test]` flag above it.
34Continue, until you pass every test.
35
36If you wish to run all ignored tests without editing the tests source file, use:
37
38```bash
39$ cargo test -- --ignored
40```
41
42To run a specific test, for example `some_test`, you can use:
43
44```bash
45$ cargo test some_test
46```
47
48If the specific test is ignored use:
49
50```bash
51$ cargo test some_test -- --ignored
52```
53
54To learn more about Rust tests refer to the [online test documentation][rust-tests]
55
56Make sure to read the [Modules][modules] chapter if you
57haven't already, it will help you with organizing your files.
58
59## Further improvements
60
61After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
62
63To format your solution, inside the solution directory use
64
65```bash
66cargo fmt
67```
68
69To see, if your solution contains some common ineffective use cases, inside the solution directory use
70
71```bash
72cargo clippy --all-targets
73```
74
75## Submitting the solution
76
77Generally 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.
78
79## Feedback, Issues, Pull Requests
80
81The [exercism/rust](https://github.com/exercism/rust) repository on 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!
82
83If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
84
85[help-page]: https://exercism.io/tracks/rust/learning
86[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
87[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
88[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
89
90## Source
91
92This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
93
94## Submitting Incomplete Solutions
95It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/hello-world/src/lib.rs b/rust/hello-world/src/lib.rs
new file mode 100644
index 0000000..8f68273
--- /dev/null
+++ b/rust/hello-world/src/lib.rs
@@ -0,0 +1,5 @@
1// The &'static here means the return type has a static lifetime.
2// This is a Rust feature that you don't need to worry about now.
3pub fn hello() -> &'static str {
4 "Hello, World!"
5}
diff --git a/rust/hello-world/tests/hello-world.rs b/rust/hello-world/tests/hello-world.rs
new file mode 100644
index 0000000..c0d9536
--- /dev/null
+++ b/rust/hello-world/tests/hello-world.rs
@@ -0,0 +1,6 @@
1use hello_world;
2
3#[test]
4fn test_hello_world() {
5 assert_eq!("Hello, World!", hello_world::hello());
6}
diff --git a/rust/high-scores/.exercism/metadata.json b/rust/high-scores/.exercism/metadata.json
new file mode 100644
index 0000000..467784c
--- /dev/null
+++ b/rust/high-scores/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"high-scores","id":"4454fe8e84a84eb9860d6790c283b2c3","url":"https://exercism.io/my/solutions/4454fe8e84a84eb9860d6790c283b2c3","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/high-scores/.gitignore b/rust/high-scores/.gitignore
new file mode 100644
index 0000000..e130ceb
--- /dev/null
+++ b/rust/high-scores/.gitignore
@@ -0,0 +1,8 @@
1# Generated by exercism rust track exercise tool
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/high-scores/Cargo.toml b/rust/high-scores/Cargo.toml
new file mode 100644
index 0000000..f4d70fe
--- /dev/null
+++ b/rust/high-scores/Cargo.toml
@@ -0,0 +1,6 @@
1[dependencies]
2
3[package]
4edition = "2018"
5name = "high-scores"
6version = "4.0.0"
diff --git a/rust/high-scores/README.md b/rust/high-scores/README.md
new file mode 100644
index 0000000..f60b890
--- /dev/null
+++ b/rust/high-scores/README.md
@@ -0,0 +1,95 @@
1# High Scores
2
3Manage a game player's High Score list.
4
5Your task is to build a high-score component of the classic Frogger
6game, one of the highest selling and addictive games of all time, and a
7classic of the arcade era. Your task is to write methods that return the
8highest score from the list, the last added score and the three highest
9scores.
10
11## Hints
12
13Consider retaining a reference to `scores` in the struct - copying is not
14necessary. You will require some lifetime annotations, though.
15
16
17## Rust Installation
18
19Refer to the [exercism help page][help-page] for Rust installation and learning
20resources.
21
22## Writing the Code
23
24Execute the tests with:
25
26```bash
27$ cargo test
28```
29
30All but the first test have been ignored. After you get the first test to
31pass, open the tests source file which is located in the `tests` directory
32and remove the `#[ignore]` flag from the next test and get the tests to pass
33again. Each separate test is a function with `#[test]` flag above it.
34Continue, until you pass every test.
35
36If you wish to run all ignored tests without editing the tests source file, use:
37
38```bash
39$ cargo test -- --ignored
40```
41
42To run a specific test, for example `some_test`, you can use:
43
44```bash
45$ cargo test some_test
46```
47
48If the specific test is ignored use:
49
50```bash
51$ cargo test some_test -- --ignored
52```
53
54To learn more about Rust tests refer to the [online test documentation][rust-tests]
55
56Make sure to read the [Modules][modules] chapter if you
57haven't already, it will help you with organizing your files.
58
59## Further improvements
60
61After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
62
63To format your solution, inside the solution directory use
64
65```bash
66cargo fmt
67```
68
69To see, if your solution contains some common ineffective use cases, inside the solution directory use
70
71```bash
72cargo clippy --all-targets
73```
74
75## Submitting the solution
76
77Generally 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.
78
79## Feedback, Issues, Pull Requests
80
81The [exercism/rust](https://github.com/exercism/rust) repository on 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!
82
83If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
84
85[help-page]: https://exercism.io/tracks/rust/learning
86[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
87[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
88[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
89
90## Source
91
92Tribute to the eighties' arcade game Frogger
93
94## Submitting Incomplete Solutions
95It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/high-scores/src/lib.rs b/rust/high-scores/src/lib.rs
new file mode 100644
index 0000000..a7e6c3d
--- /dev/null
+++ b/rust/high-scores/src/lib.rs
@@ -0,0 +1,29 @@
1#[derive(Debug)]
2pub struct HighScores<'a> {
3 scores: &'a [u32]
4}
5
6impl<'a> HighScores<'a> {
7 pub fn new(scores: &'a [u32]) -> Self {
8 HighScores{ scores }
9 }
10
11 pub fn scores(&self) -> &[u32] {
12 self.scores
13 }
14
15 pub fn latest(&self) -> Option<u32> {
16 self.scores.last().copied()
17 }
18
19 pub fn personal_best(&self) -> Option<u32> {
20 self.scores.iter().max().copied()
21 }
22
23 pub fn personal_top_three(&self) -> Vec<u32> {
24 let mut top3 = self.scores.to_vec();
25 top3.sort_unstable_by(|a,b| b.cmp(a));
26 top3.truncate(3);
27 top3
28 }
29}
diff --git a/rust/high-scores/tests/high-scores.rs b/rust/high-scores/tests/high-scores.rs
new file mode 100644
index 0000000..4d2feb7
--- /dev/null
+++ b/rust/high-scores/tests/high-scores.rs
@@ -0,0 +1,68 @@
1use high_scores::HighScores;
2
3#[test]
4fn test_list_of_scores() {
5 let expected = [30, 50, 20, 70];
6 let high_scores = HighScores::new(&expected);
7 assert_eq!(high_scores.scores(), &expected);
8}
9
10#[test]
11fn test_latest_score() {
12 let high_scores = HighScores::new(&[100, 0, 90, 30]);
13 assert_eq!(high_scores.latest(), Some(30));
14}
15
16#[test]
17fn test_latest_score_empty() {
18 let high_scores = HighScores::new(&[]);
19 assert_eq!(high_scores.latest(), None);
20}
21
22#[test]
23fn test_personal_best() {
24 let high_scores = HighScores::new(&[40, 100, 70]);
25 assert_eq!(high_scores.personal_best(), Some(100));
26}
27
28#[test]
29fn test_personal_best_empty() {
30 let high_scores = HighScores::new(&[]);
31 assert_eq!(high_scores.personal_best(), None);
32}
33
34#[test]
35fn test_personal_top_three() {
36 let high_scores = HighScores::new(&[10, 30, 90, 30, 100, 20, 10, 0, 30, 40, 40, 70, 70]);
37 assert_eq!(high_scores.personal_top_three(), vec![100, 90, 70]);
38}
39
40#[test]
41fn test_personal_top_three_highest_to_lowest() {
42 let high_scores = HighScores::new(&[20, 10, 30]);
43 assert_eq!(high_scores.personal_top_three(), vec![30, 20, 10]);
44}
45
46#[test]
47fn test_personal_top_three_with_tie() {
48 let high_scores = HighScores::new(&[40, 20, 40, 30]);
49 assert_eq!(high_scores.personal_top_three(), vec![40, 40, 30]);
50}
51
52#[test]
53fn test_personal_top_three_with_less_than_three_scores() {
54 let high_scores = HighScores::new(&[30, 70]);
55 assert_eq!(high_scores.personal_top_three(), vec![70, 30]);
56}
57
58#[test]
59fn test_personal_top_three_only_one_score() {
60 let high_scores = HighScores::new(&[40]);
61 assert_eq!(high_scores.personal_top_three(), vec![40]);
62}
63
64#[test]
65fn test_personal_top_three_empty() {
66 let high_scores = HighScores::new(&[]);
67 assert!(high_scores.personal_top_three().is_empty());
68}
diff --git a/rust/leap/.exercism/metadata.json b/rust/leap/.exercism/metadata.json
new file mode 100644
index 0000000..1ec33f3
--- /dev/null
+++ b/rust/leap/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"leap","id":"bc3b9538660b445abd5c2ee1398141db","url":"https://exercism.io/my/solutions/bc3b9538660b445abd5c2ee1398141db","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/leap/.gitignore b/rust/leap/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/leap/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/leap/Cargo.toml b/rust/leap/Cargo.toml
new file mode 100644
index 0000000..c125e67
--- /dev/null
+++ b/rust/leap/Cargo.toml
@@ -0,0 +1,4 @@
1[package]
2edition = "2018"
3name = "leap"
4version = "1.6.0"
diff --git a/rust/leap/README.md b/rust/leap/README.md
new file mode 100644
index 0000000..6a6bac4
--- /dev/null
+++ b/rust/leap/README.md
@@ -0,0 +1,105 @@
1# Leap Given a year, report if it is a leap year.
2
3The tricky thing here is that a leap year in the Gregorian calendar occurs:
4
5```text
6on every year that is evenly divisible by 4
7except every year that is evenly divisible by 100
8 unless the year is also evenly divisible by 400
9```
10
11For example, 1997 is not a leap year, but 1996 is. 1900 is not a leap
12year, but 2000 is.
13
14## Notes
15
16Though our exercise adopts some very simple rules, there is more to
17learn!
18
19For a delightful, four minute explanation of the whole leap year
20phenomenon, go watch [this youtube video][video].
21
22[video]: http://www.youtube.com/watch?v=xX96xng7sAE
23
24You may use the [`arithmetic remainder` operator](https://doc.rust-lang.org/book/appendix-02-operators.html) to test for divisibility.
25
26
27## Rust Installation
28
29Refer to the [exercism help page][help-page] for Rust installation and learning
30resources.
31
32## Writing the Code
33
34Execute the tests with:
35
36```bash
37$ cargo test
38```
39
40All but the first test have been ignored. After you get the first test to
41pass, open the tests source file which is located in the `tests` directory
42and remove the `#[ignore]` flag from the next test and get the tests to pass
43again. Each separate test is a function with `#[test]` flag above it.
44Continue, until you pass every test.
45
46If you wish to run all ignored tests without editing the tests source file, use:
47
48```bash
49$ cargo test -- --ignored
50```
51
52To run a specific test, for example `some_test`, you can use:
53
54```bash
55$ cargo test some_test
56```
57
58If the specific test is ignored use:
59
60```bash
61$ cargo test some_test -- --ignored
62```
63
64To learn more about Rust tests refer to the [online test documentation][rust-tests]
65
66Make sure to read the [Modules][modules] chapter if you
67haven't already, it will help you with organizing your files.
68
69## Further improvements
70
71After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
72
73To format your solution, inside the solution directory use
74
75```bash
76cargo fmt
77```
78
79To see, if your solution contains some common ineffective use cases, inside the solution directory use
80
81```bash
82cargo clippy --all-targets
83```
84
85## Submitting the solution
86
87Generally 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.
88
89## Feedback, Issues, Pull Requests
90
91The [exercism/rust](https://github.com/exercism/rust) repository on 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!
92
93If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
94
95[help-page]: https://exercism.io/tracks/rust/learning
96[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
97[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
98[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
99
100## Source
101
102JavaRanch Cattle Drive, exercise 3 [http://www.javaranch.com/leap.jsp](http://www.javaranch.com/leap.jsp)
103
104## Submitting Incomplete Solutions
105It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/leap/src/lib.rs b/rust/leap/src/lib.rs
new file mode 100644
index 0000000..1b40300
--- /dev/null
+++ b/rust/leap/src/lib.rs
@@ -0,0 +1,3 @@
1pub fn is_leap_year(year: u64) -> bool {
2 year % 4 == 0 && year % 100 != 0 || year % 400 == 0
3}
diff --git a/rust/leap/tests/leap.rs b/rust/leap/tests/leap.rs
new file mode 100644
index 0000000..88d2c77
--- /dev/null
+++ b/rust/leap/tests/leap.rs
@@ -0,0 +1,89 @@
1use leap;
2
3fn process_leapyear_case(year: u64, expected: bool) {
4 assert_eq!(leap::is_leap_year(year), expected);
5}
6
7#[test]
8fn test_year_not_divisible_by_4_common_year() {
9 process_leapyear_case(2015, false);
10}
11
12#[test]
13fn test_year_divisible_by_2_not_divisible_by_4_in_common_year() {
14 process_leapyear_case(1970, false);
15}
16
17#[test]
18fn test_year_divisible_by_4_not_divisible_by_100_leap_year() {
19 process_leapyear_case(1996, true);
20}
21
22#[test]
23fn test_year_divisible_by_4_and_5_is_still_a_leap_year() {
24 process_leapyear_case(1960, true);
25}
26
27#[test]
28fn test_year_divisible_by_100_not_divisible_by_400_common_year() {
29 process_leapyear_case(2100, false);
30}
31
32#[test]
33fn test_year_divisible_by_100_but_not_by_3_is_still_not_a_leap_year() {
34 process_leapyear_case(1900, false);
35}
36
37#[test]
38fn test_year_divisible_by_400_leap_year() {
39 process_leapyear_case(2000, true);
40}
41
42#[test]
43fn test_year_divisible_by_400_but_not_by_125_is_still_a_leap_year() {
44 process_leapyear_case(2400, true);
45}
46
47#[test]
48fn test_year_divisible_by_200_not_divisible_by_400_common_year() {
49 process_leapyear_case(1800, false);
50}
51
52#[test]
53fn test_any_old_year() {
54 assert_eq!(leap::is_leap_year(1997), false);
55}
56
57#[test]
58fn test_early_years() {
59 assert_eq!(leap::is_leap_year(1), false);
60 assert_eq!(leap::is_leap_year(4), true);
61 assert_eq!(leap::is_leap_year(100), false);
62 assert_eq!(leap::is_leap_year(400), true);
63 assert_eq!(leap::is_leap_year(900), false);
64}
65
66#[test]
67fn test_century() {
68 assert_eq!(leap::is_leap_year(1700), false);
69 assert_eq!(leap::is_leap_year(1800), false);
70 assert_eq!(leap::is_leap_year(1900), false);
71}
72
73#[test]
74fn test_exceptional_centuries() {
75 assert_eq!(leap::is_leap_year(1600), true);
76 assert_eq!(leap::is_leap_year(2000), true);
77 assert_eq!(leap::is_leap_year(2400), true);
78}
79
80#[test]
81fn test_years_1600_to_1699() {
82 let incorrect_years = (1600..1700)
83 .filter(|&year| leap::is_leap_year(year) != (year % 4 == 0))
84 .collect::<Vec<_>>();
85
86 if !incorrect_years.is_empty() {
87 panic!("incorrect result for years: {:?}", incorrect_years);
88 }
89}
diff --git a/rust/matching-brackets/.exercism/metadata.json b/rust/matching-brackets/.exercism/metadata.json
new file mode 100644
index 0000000..7b5495d
--- /dev/null
+++ b/rust/matching-brackets/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"matching-brackets","id":"568307886f5d4f38afb0394b1e981c76","url":"https://exercism.io/my/solutions/568307886f5d4f38afb0394b1e981c76","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/matching-brackets/.gitignore b/rust/matching-brackets/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/matching-brackets/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/matching-brackets/Cargo.toml b/rust/matching-brackets/Cargo.toml
new file mode 100644
index 0000000..2e7dafa
--- /dev/null
+++ b/rust/matching-brackets/Cargo.toml
@@ -0,0 +1,4 @@
1[package]
2edition = "2018"
3name = "matching-brackets"
4version = "2.0.0"
diff --git a/rust/matching-brackets/README.md b/rust/matching-brackets/README.md
new file mode 100644
index 0000000..049e3fa
--- /dev/null
+++ b/rust/matching-brackets/README.md
@@ -0,0 +1,85 @@
1# Matching Brackets
2
3Given a string containing brackets `[]`, braces `{}`, parentheses `()`,
4or any combination thereof, verify that any and all pairs are matched
5and nested correctly.
6
7## Rust Installation
8
9Refer to the [exercism help page][help-page] for Rust installation and learning
10resources.
11
12## Writing the Code
13
14Execute the tests with:
15
16```bash
17$ cargo test
18```
19
20All but the first test have been ignored. After you get the first test to
21pass, open the tests source file which is located in the `tests` directory
22and remove the `#[ignore]` flag from the next test and get the tests to pass
23again. Each separate test is a function with `#[test]` flag above it.
24Continue, until you pass every test.
25
26If you wish to run all ignored tests without editing the tests source file, use:
27
28```bash
29$ cargo test -- --ignored
30```
31
32To run a specific test, for example `some_test`, you can use:
33
34```bash
35$ cargo test some_test
36```
37
38If the specific test is ignored use:
39
40```bash
41$ cargo test some_test -- --ignored
42```
43
44To learn more about Rust tests refer to the [online test documentation][rust-tests]
45
46Make sure to read the [Modules][modules] chapter if you
47haven't already, it will help you with organizing your files.
48
49## Further improvements
50
51After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
52
53To format your solution, inside the solution directory use
54
55```bash
56cargo fmt
57```
58
59To see, if your solution contains some common ineffective use cases, inside the solution directory use
60
61```bash
62cargo clippy --all-targets
63```
64
65## Submitting the solution
66
67Generally 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.
68
69## Feedback, Issues, Pull Requests
70
71The [exercism/rust](https://github.com/exercism/rust) repository on 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!
72
73If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
74
75[help-page]: https://exercism.io/tracks/rust/learning
76[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
77[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
78[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
79
80## Source
81
82Ginna Baker
83
84## Submitting Incomplete Solutions
85It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/matching-brackets/src/lib.rs b/rust/matching-brackets/src/lib.rs
new file mode 100644
index 0000000..03e39ca
--- /dev/null
+++ b/rust/matching-brackets/src/lib.rs
@@ -0,0 +1,12 @@
1pub fn brackets_are_balanced(string: &str) -> bool {
2 let mut stack = vec![];
3 for c in string.chars() {
4 match c {
5 '(' => stack.push(((c as u8) + 1) as char),
6 '[' | '{' => stack.push(((c as u8) + 2) as char),
7 ')' | ']' | '}' if stack.pop() != Some(c) => return false,
8 _ => ()
9 }
10 }
11 stack.is_empty()
12}
diff --git a/rust/matching-brackets/tests/matching-brackets.rs b/rust/matching-brackets/tests/matching-brackets.rs
new file mode 100644
index 0000000..0826dad
--- /dev/null
+++ b/rust/matching-brackets/tests/matching-brackets.rs
@@ -0,0 +1,98 @@
1use matching_brackets::brackets_are_balanced;
2
3#[test]
4fn paired_square_brackets() {
5 assert!(brackets_are_balanced("[]"));
6}
7
8#[test]
9fn empty_string() {
10 assert!(brackets_are_balanced(""));
11}
12
13#[test]
14fn unpaired_brackets() {
15 assert!(!brackets_are_balanced("[["));
16}
17
18#[test]
19fn wrong_ordered_brackets() {
20 assert!(!brackets_are_balanced("}{"));
21}
22
23#[test]
24fn wrong_closing_bracket() {
25 assert!(!brackets_are_balanced("{]"));
26}
27
28#[test]
29fn paired_with_whitespace() {
30 assert!(brackets_are_balanced("{ }"));
31}
32
33#[test]
34fn partially_paired_brackets() {
35 assert!(!brackets_are_balanced("{[])"));
36}
37
38#[test]
39fn simple_nested_brackets() {
40 assert!(brackets_are_balanced("{[]}"));
41}
42
43#[test]
44fn several_paired_brackets() {
45 assert!(brackets_are_balanced("{}[]"));
46}
47
48#[test]
49fn paired_and_nested_brackets() {
50 assert!(brackets_are_balanced("([{}({}[])])"));
51}
52
53#[test]
54fn unopened_closing_brackets() {
55 assert!(!brackets_are_balanced("{[)][]}"));
56}
57
58#[test]
59fn unpaired_and_nested_brackets() {
60 assert!(!brackets_are_balanced("([{])"));
61}
62
63#[test]
64fn paired_and_wrong_nested_brackets() {
65 assert!(!brackets_are_balanced("[({]})"));
66}
67
68#[test]
69fn paired_and_incomplete_brackets() {
70 assert!(!brackets_are_balanced("{}["));
71}
72
73#[test]
74fn too_many_closing_brackets() {
75 assert!(!brackets_are_balanced("[]]"));
76}
77
78#[test]
79fn early_incomplete_brackets() {
80 assert!(!brackets_are_balanced(")()"));
81}
82
83#[test]
84fn early_mismatched_brackets() {
85 assert!(!brackets_are_balanced("{)()"));
86}
87
88#[test]
89fn math_expression() {
90 assert!(brackets_are_balanced("(((185 + 223.85) * 15) - 543)/2"));
91}
92
93#[test]
94fn complex_latex_expression() {
95 let input = "\\left(\\begin{array}{cc} \\frac{1}{3} & x\\\\ \\mathrm{e}^{x} &... x^2 \
96 \\end{array}\\right)";
97 assert!(brackets_are_balanced(input));
98}
diff --git a/rust/nth-prime/.exercism/metadata.json b/rust/nth-prime/.exercism/metadata.json
new file mode 100644
index 0000000..5c5337e
--- /dev/null
+++ b/rust/nth-prime/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"nth-prime","id":"7ed3faca556f4c23a55b30fae8b69047","url":"https://exercism.io/my/solutions/7ed3faca556f4c23a55b30fae8b69047","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/nth-prime/.gitignore b/rust/nth-prime/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/nth-prime/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/nth-prime/Cargo.toml b/rust/nth-prime/Cargo.toml
new file mode 100644
index 0000000..fc1c776
--- /dev/null
+++ b/rust/nth-prime/Cargo.toml
@@ -0,0 +1,6 @@
1[package]
2edition = "2018"
3name = "nth_prime"
4version = "2.1.0"
5
6[dependencies]
diff --git a/rust/nth-prime/README.md b/rust/nth-prime/README.md
new file mode 100644
index 0000000..425abde
--- /dev/null
+++ b/rust/nth-prime/README.md
@@ -0,0 +1,92 @@
1# Nth Prime
2
3Given a number n, determine what the nth prime is.
4
5By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that
6the 6th prime is 13.
7
8If your language provides methods in the standard library to deal with prime
9numbers, pretend they don't exist and implement them yourself.
10
11Remember that while people commonly count with 1-based indexing (i.e. "the 6th prime is 13"), many programming languages, including Rust, use 0-based indexing (i.e. `primes[5] == 13`). Use 0-based indexing for your implementation.
12
13
14## Rust Installation
15
16Refer to the [exercism help page][help-page] for Rust installation and learning
17resources.
18
19## Writing the Code
20
21Execute the tests with:
22
23```bash
24$ cargo test
25```
26
27All but the first test have been ignored. After you get the first test to
28pass, open the tests source file which is located in the `tests` directory
29and remove the `#[ignore]` flag from the next test and get the tests to pass
30again. Each separate test is a function with `#[test]` flag above it.
31Continue, until you pass every test.
32
33If you wish to run all ignored tests without editing the tests source file, use:
34
35```bash
36$ cargo test -- --ignored
37```
38
39To run a specific test, for example `some_test`, you can use:
40
41```bash
42$ cargo test some_test
43```
44
45If the specific test is ignored use:
46
47```bash
48$ cargo test some_test -- --ignored
49```
50
51To learn more about Rust tests refer to the [online test documentation][rust-tests]
52
53Make sure to read the [Modules][modules] chapter if you
54haven't already, it will help you with organizing your files.
55
56## Further improvements
57
58After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
59
60To format your solution, inside the solution directory use
61
62```bash
63cargo fmt
64```
65
66To see, if your solution contains some common ineffective use cases, inside the solution directory use
67
68```bash
69cargo clippy --all-targets
70```
71
72## Submitting the solution
73
74Generally 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.
75
76## Feedback, Issues, Pull Requests
77
78The [exercism/rust](https://github.com/exercism/rust) repository on 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!
79
80If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
81
82[help-page]: https://exercism.io/tracks/rust/learning
83[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
84[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
85[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
86
87## Source
88
89A variation on Problem 7 at Project Euler [http://projecteuler.net/problem=7](http://projecteuler.net/problem=7)
90
91## Submitting Incomplete Solutions
92It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/nth-prime/src/lib.rs b/rust/nth-prime/src/lib.rs
new file mode 100644
index 0000000..ef9d7ea
--- /dev/null
+++ b/rust/nth-prime/src/lib.rs
@@ -0,0 +1,8 @@
1fn is_prime(n: u32) -> bool {
2 let limit = (n as f64).sqrt() as u32;
3 (2..=limit).all(|x| n % x != 0)
4}
5
6pub fn nth(n: u32) -> u32 {
7 (2..).filter(|x| is_prime(*x)).nth(n as usize).unwrap()
8}
diff --git a/rust/nth-prime/tests/nth-prime.rs b/rust/nth-prime/tests/nth-prime.rs
new file mode 100644
index 0000000..b313ff2
--- /dev/null
+++ b/rust/nth-prime/tests/nth-prime.rs
@@ -0,0 +1,21 @@
1use nth_prime as np;
2
3#[test]
4fn test_first_prime() {
5 assert_eq!(np::nth(0), 2);
6}
7
8#[test]
9fn test_second_prime() {
10 assert_eq!(np::nth(1), 3);
11}
12
13#[test]
14fn test_sixth_prime() {
15 assert_eq!(np::nth(5), 13);
16}
17
18#[test]
19fn test_big_prime() {
20 assert_eq!(np::nth(10_000), 104_743);
21}
diff --git a/rust/nucleotide-count/.exercism/metadata.json b/rust/nucleotide-count/.exercism/metadata.json
new file mode 100644
index 0000000..3cb94c8
--- /dev/null
+++ b/rust/nucleotide-count/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"nucleotide-count","id":"2e44b94b9e1648c2876e1882f15bd9de","url":"https://exercism.io/my/solutions/2e44b94b9e1648c2876e1882f15bd9de","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/nucleotide-count/.gitignore b/rust/nucleotide-count/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/nucleotide-count/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/nucleotide-count/Cargo.toml b/rust/nucleotide-count/Cargo.toml
new file mode 100644
index 0000000..3eb8759
--- /dev/null
+++ b/rust/nucleotide-count/Cargo.toml
@@ -0,0 +1,7 @@
1[package]
2edition = "2018"
3name = "nucleotide-count"
4version = "1.3.0"
5
6[dependencies]
7maplit = "1.0.1"
diff --git a/rust/nucleotide-count/README.md b/rust/nucleotide-count/README.md
new file mode 100644
index 0000000..9a85942
--- /dev/null
+++ b/rust/nucleotide-count/README.md
@@ -0,0 +1,110 @@
1# Nucleotide Count
2
3Each of us inherits from our biological parents a set of chemical
4instructions known as DNA that influence how our bodies are constructed.
5All known life depends on DNA!
6
7> Note: You do not need to understand anything about nucleotides or DNA
8> to complete this exercise.
9
10DNA is a long chain of other chemicals and the most important are the
11four nucleotides, adenine, cytosine, guanine and thymine. A single DNA
12chain can contain billions of these four nucleotides and the order in
13which they occur is important! We call the order of these nucleotides in
14a bit of DNA a "DNA sequence".
15
16We represent a DNA sequence as an ordered collection of these four
17nucleotides and a common way to do that is with a string of characters
18such as "ATTACG" for a DNA sequence of 6 nucleotides. 'A' for adenine,
19'C' for cytosine, 'G' for guanine, and 'T' for thymine.
20
21Given a string representing a DNA sequence, count how many of each
22nucleotide is present. If the string contains characters that aren't A,
23C, G, or T then it is invalid and you should signal an error.
24
25For example:
26
27```
28"GATTACA" -> 'A': 3, 'C': 1, 'G': 1, 'T': 2
29"INVALID" -> error
30```
31
32## Rust Installation
33
34Refer to the [exercism help page][help-page] for Rust installation and learning
35resources.
36
37## Writing the Code
38
39Execute the tests with:
40
41```bash
42$ cargo test
43```
44
45All but the first test have been ignored. After you get the first test to
46pass, open the tests source file which is located in the `tests` directory
47and remove the `#[ignore]` flag from the next test and get the tests to pass
48again. Each separate test is a function with `#[test]` flag above it.
49Continue, until you pass every test.
50
51If you wish to run all ignored tests without editing the tests source file, use:
52
53```bash
54$ cargo test -- --ignored
55```
56
57To run a specific test, for example `some_test`, you can use:
58
59```bash
60$ cargo test some_test
61```
62
63If the specific test is ignored use:
64
65```bash
66$ cargo test some_test -- --ignored
67```
68
69To learn more about Rust tests refer to the [online test documentation][rust-tests]
70
71Make sure to read the [Modules][modules] chapter if you
72haven't already, it will help you with organizing your files.
73
74## Further improvements
75
76After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
77
78To format your solution, inside the solution directory use
79
80```bash
81cargo fmt
82```
83
84To see, if your solution contains some common ineffective use cases, inside the solution directory use
85
86```bash
87cargo clippy --all-targets
88```
89
90## Submitting the solution
91
92Generally 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.
93
94## Feedback, Issues, Pull Requests
95
96The [exercism/rust](https://github.com/exercism/rust) repository on 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!
97
98If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
99
100[help-page]: https://exercism.io/tracks/rust/learning
101[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
102[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
103[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
104
105## Source
106
107The Calculating DNA Nucleotides_problem at Rosalind [http://rosalind.info/problems/dna/](http://rosalind.info/problems/dna/)
108
109## Submitting Incomplete Solutions
110It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/nucleotide-count/src/lib.rs b/rust/nucleotide-count/src/lib.rs
new file mode 100644
index 0000000..98b0c38
--- /dev/null
+++ b/rust/nucleotide-count/src/lib.rs
@@ -0,0 +1,21 @@
1use maplit::hashmap;
2use std::collections::HashMap;
3
4pub fn count(nucleotide: char, dna: &str) -> Result<usize, char> {
5 nucleotide_counts(dna)?
6 .remove(&nucleotide)
7 .ok_or(nucleotide)
8}
9
10pub fn nucleotide_counts(dna: &str) -> Result<HashMap<char, usize>, char> {
11 dna.chars().fold(
12 Ok(hashmap![ 'A' => 0, 'C' => 0, 'G' => 0, 'T' => 0 ]),
13 |acc, n| match n {
14 'A' | 'C' | 'G' | 'T' => acc.map(|mut hmap| {
15 hmap.entry(n).and_modify(|e| *e += 1).or_insert(0);
16 hmap
17 }),
18 _ => Err(n),
19 },
20 )
21}
diff --git a/rust/nucleotide-count/tests/nucleotide-count.rs b/rust/nucleotide-count/tests/nucleotide-count.rs
new file mode 100644
index 0000000..8190580
--- /dev/null
+++ b/rust/nucleotide-count/tests/nucleotide-count.rs
@@ -0,0 +1,88 @@
1use nucleotide_count as dna;
2
3use std::collections::HashMap;
4
5fn process_nucleotidecounts_case(s: &str, pairs: &[(char, usize)]) {
6 // The reason for the awkward code in here is to ensure that the failure
7 // message for assert_eq! is as informative as possible. A simpler
8 // solution would simply check the length of the map, and then
9 // check for the presence and value of each key in the given pairs vector.
10 let mut m: HashMap<char, usize> = dna::nucleotide_counts(s).unwrap();
11 for &(k, v) in pairs.iter() {
12 assert_eq!((k, m.remove(&k)), (k, Some(v)));
13 }
14
15 // may fail with a message that clearly shows all extra pairs in the map
16 assert_eq!(m.iter().collect::<Vec<(&char, &usize)>>(), vec![]);
17}
18
19#[test]
20fn count_returns_result() {
21 assert!(dna::count('A', "").is_ok());
22}
23
24#[test]
25fn test_count_empty() {
26 assert_eq!(dna::count('A', ""), Ok(0));
27}
28
29#[test]
30fn count_invalid_nucleotide() {
31 assert_eq!(dna::count('X', "A"), Err('X'));
32}
33
34#[test]
35fn count_invalid_dna() {
36 assert_eq!(dna::count('A', "AX"), Err('X'));
37}
38
39#[test]
40fn test_count_repetitive_cytosine() {
41 assert_eq!(dna::count('C', "CCCCC"), Ok(5));
42}
43
44#[test]
45fn test_count_only_thymine() {
46 assert_eq!(dna::count('T', "GGGGGTAACCCGG"), Ok(1));
47}
48
49#[test]
50fn counts_returns_result() {
51 assert!(dna::nucleotide_counts("ACGT").is_ok());
52}
53
54#[test]
55fn test_empty_strand() {
56 process_nucleotidecounts_case("", &[('A', 0), ('T', 0), ('C', 0), ('G', 0)]);
57}
58
59#[test]
60/// can count one nucleotide in single-character input
61fn test_can_count_one_nucleotide_in_singlecharacter_input() {
62 process_nucleotidecounts_case("G", &[('A', 0), ('C', 0), ('G', 1), ('T', 0)]);
63}
64
65#[test]
66fn test_strand_with_repeated_nucleotide() {
67 process_nucleotidecounts_case("GGGGGGG", &[('A', 0), ('T', 0), ('C', 0), ('G', 7)]);
68}
69
70#[test]
71/// strand with multiple nucleotides
72fn test_strand_with_multiple_nucleotides() {
73 process_nucleotidecounts_case(
74 "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC",
75 &[('A', 20), ('T', 21), ('C', 12), ('G', 17)],
76 );
77}
78
79#[test]
80fn counts_invalid_nucleotide_results_in_err() {
81 assert_eq!(dna::nucleotide_counts("GGXXX"), Err('X'));
82}
83
84#[test]
85/// strand with invalid nucleotides
86fn test_strand_with_invalid_nucleotides() {
87 assert_eq!(dna::nucleotide_counts("AGXXACT"), Err('X'),);
88}
diff --git a/rust/paasio/.exercism/metadata.json b/rust/paasio/.exercism/metadata.json
new file mode 100644
index 0000000..e6e8012
--- /dev/null
+++ b/rust/paasio/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"paasio","id":"6ac29a8082a94a0a91b43185846bcfe7","url":"https://exercism.io/my/solutions/6ac29a8082a94a0a91b43185846bcfe7","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/paasio/.gitignore b/rust/paasio/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/paasio/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/paasio/Cargo.toml b/rust/paasio/Cargo.toml
new file mode 100644
index 0000000..83a8e73
--- /dev/null
+++ b/rust/paasio/Cargo.toml
@@ -0,0 +1,4 @@
1[package]
2edition = "2018"
3name = "paasio"
4version = "0.0.0"
diff --git a/rust/paasio/README.md b/rust/paasio/README.md
new file mode 100644
index 0000000..03e5a4d
--- /dev/null
+++ b/rust/paasio/README.md
@@ -0,0 +1,102 @@
1# PaaS I/O
2
3Report network IO statistics.
4
5You are writing a [PaaS][], and you need a way to bill customers based
6on network and filesystem usage.
7
8Create a wrapper for network connections and files that can report IO
9statistics. The wrapper must report:
10
11- The total number of bytes read/written.
12- The total number of read/write operations.
13
14[PaaS]: http://en.wikipedia.org/wiki/Platform_as_a_service
15
16## Abstraction over Networks and Files
17
18Network and file operations are implemented in terms of the [`io::Read`][read] and [`io::Write`][write] traits. It will therefore be necessary to implement those traits for your types.
19
20[read]: https://doc.rust-lang.org/std/io/trait.Read.html
21[write]: https://doc.rust-lang.org/std/io/trait.Write.html
22
23
24## Rust Installation
25
26Refer to the [exercism help page][help-page] for Rust installation and learning
27resources.
28
29## Writing the Code
30
31Execute the tests with:
32
33```bash
34$ cargo test
35```
36
37All but the first test have been ignored. After you get the first test to
38pass, open the tests source file which is located in the `tests` directory
39and remove the `#[ignore]` flag from the next test and get the tests to pass
40again. Each separate test is a function with `#[test]` flag above it.
41Continue, until you pass every test.
42
43If you wish to run all ignored tests without editing the tests source file, use:
44
45```bash
46$ cargo test -- --ignored
47```
48
49To run a specific test, for example `some_test`, you can use:
50
51```bash
52$ cargo test some_test
53```
54
55If the specific test is ignored use:
56
57```bash
58$ cargo test some_test -- --ignored
59```
60
61To learn more about Rust tests refer to the [online test documentation][rust-tests]
62
63Make sure to read the [Modules][modules] chapter if you
64haven't already, it will help you with organizing your files.
65
66## Further improvements
67
68After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
69
70To format your solution, inside the solution directory use
71
72```bash
73cargo fmt
74```
75
76To see, if your solution contains some common ineffective use cases, inside the solution directory use
77
78```bash
79cargo clippy --all-targets
80```
81
82## Submitting the solution
83
84Generally 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.
85
86## Feedback, Issues, Pull Requests
87
88The [exercism/rust](https://github.com/exercism/rust) repository on 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!
89
90If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
91
92[help-page]: https://exercism.io/tracks/rust/learning
93[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
94[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
95[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
96
97## Source
98
99Brian Matsuo [https://github.com/bmatsuo](https://github.com/bmatsuo)
100
101## Submitting Incomplete Solutions
102It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/paasio/src/lib.rs b/rust/paasio/src/lib.rs
new file mode 100644
index 0000000..71f4c9d
--- /dev/null
+++ b/rust/paasio/src/lib.rs
@@ -0,0 +1,82 @@
1use std::io::{Read, Result, Write};
2
3pub struct ReadStats<R> {
4 source: R,
5 reads: usize,
6 bytes: usize,
7}
8
9impl<R: Read> ReadStats<R> {
10 pub fn new(wrapped: R) -> ReadStats<R> {
11 ReadStats {
12 source: wrapped,
13 reads: 0,
14 bytes: 0,
15 }
16 }
17
18 pub fn get_ref(&self) -> &R {
19 &self.source
20 }
21
22 pub fn bytes_through(&self) -> usize {
23 self.bytes
24 }
25
26 pub fn reads(&self) -> usize {
27 self.reads
28 }
29}
30
31impl<R: Read> Read for ReadStats<R> {
32 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
33 let bytes = self.source.read(buf)?;
34 self.reads += 1;
35 self.bytes += bytes;
36 Ok(bytes)
37 }
38}
39
40pub struct WriteStats<W> {
41 sink: W,
42 writes: usize,
43 bytes: usize,
44}
45
46impl<W: Write> WriteStats<W> {
47 // _wrapped is ignored because W is not bounded on Debug or Display and therefore
48 // can't be passed through format!(). For actual implementation you will likely
49 // wish to remove the leading underscore so the variable is not ignored.
50 pub fn new(wrapped: W) -> WriteStats<W> {
51 WriteStats {
52 sink: wrapped,
53 writes: 0,
54 bytes: 0,
55 }
56 }
57
58 pub fn get_ref(&self) -> &W {
59 &self.sink
60 }
61
62 pub fn bytes_through(&self) -> usize {
63 self.bytes
64 }
65
66 pub fn writes(&self) -> usize {
67 self.writes
68 }
69}
70
71impl<W: Write> Write for WriteStats<W> {
72 fn write(&mut self, buf: &[u8]) -> Result<usize> {
73 let bytes = self.sink.write(buf)?;
74 self.writes += 1;
75 self.bytes += bytes;
76 Ok(bytes)
77 }
78
79 fn flush(&mut self) -> Result<()> {
80 self.sink.flush()
81 }
82}
diff --git a/rust/paasio/tests/paasio.rs b/rust/paasio/tests/paasio.rs
new file mode 100644
index 0000000..6b44199
--- /dev/null
+++ b/rust/paasio/tests/paasio.rs
@@ -0,0 +1,192 @@
1/// test a few read scenarios
2macro_rules! test_read {
3 ($(#[$attr:meta])* $modname:ident ($input:expr, $len:expr)) => {
4 mod $modname {
5 use std::io::{Read, BufReader};
6 use paasio::*;
7
8 const CHUNK_SIZE: usize = 2;
9
10 $(#[$attr])*
11 #[test]
12 fn test_read_passthrough() {
13 let data = $input;
14 let size = $len(&data);
15 let mut reader = ReadStats::new(data);
16
17 let mut buffer = Vec::with_capacity(size);
18 let qty_read = reader.read_to_end(&mut buffer);
19
20 assert!(qty_read.is_ok());
21 assert_eq!(size, qty_read.unwrap());
22 assert_eq!(size, buffer.len());
23 // 2: first to read all the data, second to check that
24 // there wasn't any more pending data which simply didn't
25 // fit into the existing buffer
26 assert_eq!(2, reader.reads());
27 assert_eq!(size, reader.bytes_through());
28 }
29
30 $(#[$attr])*
31 #[test]
32 fn test_read_chunks() {
33 let data = $input;
34 let size = $len(&data);
35 let mut reader = ReadStats::new(data);
36
37 let mut buffer = [0_u8; CHUNK_SIZE];
38 let mut chunks_read = 0;
39 while reader.read(&mut buffer[..]).unwrap_or_else(|_| panic!("read failed at chunk {}", chunks_read+1)) > 0 {
40 chunks_read += 1;
41 }
42
43 assert_eq!(size / CHUNK_SIZE + std::cmp::min(1, size % CHUNK_SIZE), chunks_read);
44 // we read once more than the number of chunks, because the final
45 // read returns 0 new bytes
46 assert_eq!(1+chunks_read, reader.reads());
47 assert_eq!(size, reader.bytes_through());
48 }
49
50 $(#[$attr])*
51 #[test]
52 fn test_read_buffered_chunks() {
53 let data = $input;
54 let size = $len(&data);
55 let mut reader = BufReader::new(ReadStats::new(data));
56
57 let mut buffer = [0_u8; CHUNK_SIZE];
58 let mut chunks_read = 0;
59 while reader.read(&mut buffer[..]).unwrap_or_else(|_| panic!("read failed at chunk {}", chunks_read+1)) > 0 {
60 chunks_read += 1;
61 }
62
63 assert_eq!(size / CHUNK_SIZE + std::cmp::min(1, size % CHUNK_SIZE), chunks_read);
64 // the BufReader should smooth out the reads, collecting into
65 // a buffer and performing only two read operations:
66 // the first collects everything into the buffer,
67 // and the second ensures that no data remains
68 assert_eq!(2, reader.get_ref().reads());
69 assert_eq!(size, reader.get_ref().bytes_through());
70 }
71 }
72 };
73}
74
75/// test a few write scenarios
76macro_rules! test_write {
77 ($(#[$attr:meta])* $modname:ident ($input:expr, $len:expr)) => {
78 mod $modname {
79 use std::io::{self, Write, BufWriter};
80 use paasio::*;
81
82 const CHUNK_SIZE: usize = 2;
83 $(#[$attr])*
84 #[test]
85 fn test_write_passthrough() {
86 let data = $input;
87 let size = $len(&data);
88 let mut writer = WriteStats::new(Vec::with_capacity(size));
89 let written = writer.write(data);
90 assert!(written.is_ok());
91 assert_eq!(size, written.unwrap());
92 assert_eq!(size, writer.bytes_through());
93 assert_eq!(1, writer.writes());
94 assert_eq!(data, writer.get_ref().as_slice());
95 }
96
97 $(#[$attr])*
98 #[test]
99 fn test_sink_oneshot() {
100 let data = $input;
101 let size = $len(&data);
102 let mut writer = WriteStats::new(io::sink());
103 let written = writer.write(data);
104 assert!(written.is_ok());
105 assert_eq!(size, written.unwrap());
106 assert_eq!(size, writer.bytes_through());
107 assert_eq!(1, writer.writes());
108 }
109
110 $(#[$attr])*
111 #[test]
112 fn test_sink_windowed() {
113 let data = $input;
114 let size = $len(&data);
115 let mut writer = WriteStats::new(io::sink());
116
117 let mut chunk_count = 0;
118 for chunk in data.chunks(CHUNK_SIZE) {
119 chunk_count += 1;
120 let written = writer.write(chunk);
121 assert!(written.is_ok());
122 assert_eq!(CHUNK_SIZE, written.unwrap());
123 }
124 assert_eq!(size, writer.bytes_through());
125 assert_eq!(chunk_count, writer.writes());
126 }
127
128 $(#[$attr])*
129 #[test]
130 fn test_sink_buffered_windowed() {
131 let data = $input;
132 let size = $len(&data);
133 let mut writer = BufWriter::new(WriteStats::new(io::sink()));
134
135 for chunk in data.chunks(CHUNK_SIZE) {
136 let written = writer.write(chunk);
137 assert!(written.is_ok());
138 assert_eq!(CHUNK_SIZE, written.unwrap());
139 }
140 // at this point, nothing should have yet been passed through to
141 // our writer
142 assert_eq!(0, writer.get_ref().bytes_through());
143 assert_eq!(0, writer.get_ref().writes());
144
145 // after flushing, everything should pass through in one go
146 assert!(writer.flush().is_ok());
147 assert_eq!(size, writer.get_ref().bytes_through());
148 assert_eq!(1, writer.get_ref().writes());
149 }
150 }
151 };
152}
153
154#[test]
155fn test_create_stats() {
156 let mut data: Vec<u8> = Vec::new();
157 let _ = paasio::ReadStats::new(data.as_slice());
158 let _ = paasio::WriteStats::new(data.as_mut_slice());
159}
160
161test_read!(read_string (
162 "Twas brillig, and the slithy toves/Did gyre and gimble in the wabe:/All mimsy were the borogoves,/And the mome raths outgrabe.".as_bytes(),
163 |d: &[u8]| d.len()
164));
165test_write!(write_string (
166 "Beware the Jabberwock, my son!/The jaws that bite, the claws that catch!/Beware the Jubjub bird, and shun/The frumious Bandersnatch!".as_bytes(),
167 |d: &[u8]| d.len()
168));
169
170test_read!(read_byte_literal(
171 &[1_u8, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144][..],
172 |d: &[u8]| d.len()
173));
174test_write!(write_byte_literal(
175 &[2_u8, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,][..],
176 |d: &[u8]| d.len()
177));
178
179test_read!(read_file(
180 ::std::fs::File::open("README.md").expect("readme must be present"),
181 |f: &::std::fs::File| f.metadata().expect("metadata must be present").len() as usize
182));
183
184#[test]
185fn read_stats_by_ref_returns_wrapped_reader() {
186 use paasio::ReadStats;
187
188 let input =
189 "Why, sometimes I've believed as many as six impossible things before breakfast".as_bytes();
190 let reader = ReadStats::new(input);
191 assert_eq!(reader.get_ref(), &input);
192}
diff --git a/rust/pascals-triangle/.exercism/metadata.json b/rust/pascals-triangle/.exercism/metadata.json
new file mode 100644
index 0000000..7352c3c
--- /dev/null
+++ b/rust/pascals-triangle/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"pascals-triangle","id":"1186776428ea49b494e3cd0bd68308bc","url":"https://exercism.io/my/solutions/1186776428ea49b494e3cd0bd68308bc","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/pascals-triangle/.gitignore b/rust/pascals-triangle/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/pascals-triangle/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/pascals-triangle/Cargo.toml b/rust/pascals-triangle/Cargo.toml
new file mode 100644
index 0000000..d308b66
--- /dev/null
+++ b/rust/pascals-triangle/Cargo.toml
@@ -0,0 +1,4 @@
1[package]
2edition = "2018"
3name = "pascals-triangle"
4version = "1.5.0"
diff --git a/rust/pascals-triangle/README.md b/rust/pascals-triangle/README.md
new file mode 100644
index 0000000..504b0b3
--- /dev/null
+++ b/rust/pascals-triangle/README.md
@@ -0,0 +1,95 @@
1# Pascal's Triangle
2
3Compute Pascal's triangle up to a given number of rows.
4
5In Pascal's Triangle each number is computed by adding the numbers to
6the right and left of the current position in the previous row.
7
8```text
9 1
10 1 1
11 1 2 1
12 1 3 3 1
131 4 6 4 1
14# ... etc
15```
16
17## Rust Installation
18
19Refer to the [exercism help page][help-page] for Rust installation and learning
20resources.
21
22## Writing the Code
23
24Execute the tests with:
25
26```bash
27$ cargo test
28```
29
30All but the first test have been ignored. After you get the first test to
31pass, open the tests source file which is located in the `tests` directory
32and remove the `#[ignore]` flag from the next test and get the tests to pass
33again. Each separate test is a function with `#[test]` flag above it.
34Continue, until you pass every test.
35
36If you wish to run all ignored tests without editing the tests source file, use:
37
38```bash
39$ cargo test -- --ignored
40```
41
42To run a specific test, for example `some_test`, you can use:
43
44```bash
45$ cargo test some_test
46```
47
48If the specific test is ignored use:
49
50```bash
51$ cargo test some_test -- --ignored
52```
53
54To learn more about Rust tests refer to the [online test documentation][rust-tests]
55
56Make sure to read the [Modules][modules] chapter if you
57haven't already, it will help you with organizing your files.
58
59## Further improvements
60
61After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
62
63To format your solution, inside the solution directory use
64
65```bash
66cargo fmt
67```
68
69To see, if your solution contains some common ineffective use cases, inside the solution directory use
70
71```bash
72cargo clippy --all-targets
73```
74
75## Submitting the solution
76
77Generally 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.
78
79## Feedback, Issues, Pull Requests
80
81The [exercism/rust](https://github.com/exercism/rust) repository on 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!
82
83If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
84
85[help-page]: https://exercism.io/tracks/rust/learning
86[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
87[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
88[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
89
90## Source
91
92Pascal's Triangle at Wolfram Math World [http://mathworld.wolfram.com/PascalsTriangle.html](http://mathworld.wolfram.com/PascalsTriangle.html)
93
94## Submitting Incomplete Solutions
95It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/pascals-triangle/src/lib.rs b/rust/pascals-triangle/src/lib.rs
new file mode 100644
index 0000000..7b2145b
--- /dev/null
+++ b/rust/pascals-triangle/src/lib.rs
@@ -0,0 +1,34 @@
1#[derive(Debug)]
2pub struct PascalsTriangle {
3 rows: Vec<Vec<u32>>,
4}
5
6impl PascalsTriangle {
7 fn next_row(row: &[u32]) -> Vec<u32> {
8 let mut next = Vec::new();
9 let last = row.iter().fold(0, |p, n| {
10 next.push(p + n);
11 *n
12 });
13 next.push(last);
14 next
15 }
16}
17
18impl PascalsTriangle {
19 pub fn new(row_count: u32) -> Self {
20 let mut rows = Vec::new();
21 if row_count > 0 {
22 rows.push(vec![1]);
23 (1..row_count).for_each(|i| {
24 let irow = Self::next_row(&rows[(i as usize) - 1]);
25 rows.push(irow);
26 })
27 }
28 PascalsTriangle { rows }
29 }
30
31 pub fn rows(&self) -> Vec<Vec<u32>> {
32 self.rows.clone()
33 }
34}
diff --git a/rust/pascals-triangle/tests/pascals-triangle.rs b/rust/pascals-triangle/tests/pascals-triangle.rs
new file mode 100644
index 0000000..64d2c2e
--- /dev/null
+++ b/rust/pascals-triangle/tests/pascals-triangle.rs
@@ -0,0 +1,96 @@
1use pascals_triangle::*;
2
3#[test]
4fn no_rows() {
5 let pt = PascalsTriangle::new(0);
6 let expected: Vec<Vec<u32>> = Vec::new();
7 assert_eq!(expected, pt.rows());
8}
9
10#[test]
11fn one_row() {
12 let pt = PascalsTriangle::new(1);
13 let expected: Vec<Vec<u32>> = vec![vec![1]];
14 assert_eq!(expected, pt.rows());
15}
16
17#[test]
18fn two_rows() {
19 let pt = PascalsTriangle::new(2);
20 let expected: Vec<Vec<u32>> = vec![vec![1], vec![1, 1]];
21 assert_eq!(expected, pt.rows());
22}
23
24#[test]
25fn three_rows() {
26 let pt = PascalsTriangle::new(3);
27 let expected: Vec<Vec<u32>> = vec![vec![1], vec![1, 1], vec![1, 2, 1]];
28 assert_eq!(expected, pt.rows());
29}
30
31#[test]
32fn last_of_four_rows() {
33 let pt = PascalsTriangle::new(4);
34 let expected: Vec<u32> = vec![1, 3, 3, 1];
35 assert_eq!(Some(expected), pt.rows().pop());
36}
37
38#[test]
39fn five_rows() {
40 let pt = PascalsTriangle::new(5);
41 let expected: Vec<Vec<u32>> = vec![
42 vec![1],
43 vec![1, 1],
44 vec![1, 2, 1],
45 vec![1, 3, 3, 1],
46 vec![1, 4, 6, 4, 1],
47 ];
48 assert_eq!(expected, pt.rows());
49}
50
51#[test]
52fn six_rows() {
53 let pt = PascalsTriangle::new(6);
54 let expected: Vec<Vec<u32>> = vec![
55 vec![1],
56 vec![1, 1],
57 vec![1, 2, 1],
58 vec![1, 3, 3, 1],
59 vec![1, 4, 6, 4, 1],
60 vec![1, 5, 10, 10, 5, 1],
61 ];
62 assert_eq!(expected, pt.rows());
63}
64
65#[test]
66fn seven_rows() {
67 let pt = PascalsTriangle::new(7);
68 let expected: Vec<Vec<u32>> = vec![
69 vec![1],
70 vec![1, 1],
71 vec![1, 2, 1],
72 vec![1, 3, 3, 1],
73 vec![1, 4, 6, 4, 1],
74 vec![1, 5, 10, 10, 5, 1],
75 vec![1, 6, 15, 20, 15, 6, 1],
76 ];
77 assert_eq!(expected, pt.rows());
78}
79
80#[test]
81fn ten_rows() {
82 let pt = PascalsTriangle::new(10);
83 let expected: Vec<Vec<u32>> = vec![
84 vec![1],
85 vec![1, 1],
86 vec![1, 2, 1],
87 vec![1, 3, 3, 1],
88 vec![1, 4, 6, 4, 1],
89 vec![1, 5, 10, 10, 5, 1],
90 vec![1, 6, 15, 20, 15, 6, 1],
91 vec![1, 7, 21, 35, 35, 21, 7, 1],
92 vec![1, 8, 28, 56, 70, 56, 28, 8, 1],
93 vec![1, 9, 36, 84, 126, 126, 84, 36, 9, 1],
94 ];
95 assert_eq!(expected, pt.rows());
96}
diff --git a/rust/prime-factors/.exercism/metadata.json b/rust/prime-factors/.exercism/metadata.json
new file mode 100644
index 0000000..293742a
--- /dev/null
+++ b/rust/prime-factors/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"prime-factors","id":"a0a637c86ddc4aa2b63cfe05a163292d","url":"https://exercism.io/my/solutions/a0a637c86ddc4aa2b63cfe05a163292d","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/prime-factors/.gitignore b/rust/prime-factors/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/prime-factors/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/prime-factors/Cargo.toml b/rust/prime-factors/Cargo.toml
new file mode 100644
index 0000000..70727e6
--- /dev/null
+++ b/rust/prime-factors/Cargo.toml
@@ -0,0 +1,6 @@
1[package]
2edition = "2018"
3name = "prime_factors"
4version = "1.1.0"
5
6[dependencies]
diff --git a/rust/prime-factors/README.md b/rust/prime-factors/README.md
new file mode 100644
index 0000000..f106dde
--- /dev/null
+++ b/rust/prime-factors/README.md
@@ -0,0 +1,110 @@
1# Prime Factors
2
3Compute the prime factors of a given natural number.
4
5A prime number is only evenly divisible by itself and 1.
6
7Note that 1 is not a prime number.
8
9## Example
10
11What are the prime factors of 60?
12
13- Our first divisor is 2. 2 goes into 60, leaving 30.
14- 2 goes into 30, leaving 15.
15 - 2 doesn't go cleanly into 15. So let's move on to our next divisor, 3.
16- 3 goes cleanly into 15, leaving 5.
17 - 3 does not go cleanly into 5. The next possible factor is 4.
18 - 4 does not go cleanly into 5. The next possible factor is 5.
19- 5 does go cleanly into 5.
20- We're left only with 1, so now, we're done.
21
22Our successful divisors in that computation represent the list of prime
23factors of 60: 2, 2, 3, and 5.
24
25You can check this yourself:
26
27- 2 * 2 * 3 * 5
28- = 4 * 15
29- = 60
30- Success!
31
32## Rust Installation
33
34Refer to the [exercism help page][help-page] for Rust installation and learning
35resources.
36
37## Writing the Code
38
39Execute the tests with:
40
41```bash
42$ cargo test
43```
44
45All but the first test have been ignored. After you get the first test to
46pass, open the tests source file which is located in the `tests` directory
47and remove the `#[ignore]` flag from the next test and get the tests to pass
48again. Each separate test is a function with `#[test]` flag above it.
49Continue, until you pass every test.
50
51If you wish to run all ignored tests without editing the tests source file, use:
52
53```bash
54$ cargo test -- --ignored
55```
56
57To run a specific test, for example `some_test`, you can use:
58
59```bash
60$ cargo test some_test
61```
62
63If the specific test is ignored use:
64
65```bash
66$ cargo test some_test -- --ignored
67```
68
69To learn more about Rust tests refer to the [online test documentation][rust-tests]
70
71Make sure to read the [Modules][modules] chapter if you
72haven't already, it will help you with organizing your files.
73
74## Further improvements
75
76After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
77
78To format your solution, inside the solution directory use
79
80```bash
81cargo fmt
82```
83
84To see, if your solution contains some common ineffective use cases, inside the solution directory use
85
86```bash
87cargo clippy --all-targets
88```
89
90## Submitting the solution
91
92Generally 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.
93
94## Feedback, Issues, Pull Requests
95
96The [exercism/rust](https://github.com/exercism/rust) repository on 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!
97
98If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
99
100[help-page]: https://exercism.io/tracks/rust/learning
101[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
102[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
103[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
104
105## Source
106
107The Prime Factors Kata by Uncle Bob [http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata](http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata)
108
109## Submitting Incomplete Solutions
110It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/prime-factors/src/lib.rs b/rust/prime-factors/src/lib.rs
new file mode 100644
index 0000000..3d7b41f
--- /dev/null
+++ b/rust/prime-factors/src/lib.rs
@@ -0,0 +1,18 @@
1
2fn factors_aux(mut vec: Vec<u64>, n: u64) -> Vec<u64> {
3 match n {
4 1 => vec,
5 n if n % 2 == 0 => {
6 factors_aux({ vec.push(2); vec }, n / 2)
7 },
8 _ => {
9 let mut i: u64 = 3;
10 while n % i != 0 { i += 2 }
11 factors_aux({ vec.push(i); vec }, n / i)
12 }
13 }
14}
15
16pub fn factors(n: u64) -> Vec<u64> {
17 factors_aux(vec![],n)
18}
diff --git a/rust/prime-factors/tests/prime-factors.rs b/rust/prime-factors/tests/prime-factors.rs
new file mode 100644
index 0000000..1042415
--- /dev/null
+++ b/rust/prime-factors/tests/prime-factors.rs
@@ -0,0 +1,36 @@
1use prime_factors::factors;
2
3#[test]
4fn test_no_factors() {
5 assert_eq!(factors(1), vec![]);
6}
7
8#[test]
9fn test_prime_number() {
10 assert_eq!(factors(2), vec![2]);
11}
12
13#[test]
14fn test_square_of_a_prime() {
15 assert_eq!(factors(9), vec![3, 3]);
16}
17
18#[test]
19fn test_cube_of_a_prime() {
20 assert_eq!(factors(8), vec![2, 2, 2]);
21}
22
23#[test]
24fn test_product_of_primes_and_non_primes() {
25 assert_eq!(factors(12), vec![2, 2, 3]);
26}
27
28#[test]
29fn test_product_of_primes() {
30 assert_eq!(factors(901_255), vec![5, 17, 23, 461]);
31}
32
33#[test]
34fn test_factors_include_large_prime() {
35 assert_eq!(factors(93_819_012_551), vec![11, 9539, 894_119]);
36}
diff --git a/rust/proverb/.exercism/metadata.json b/rust/proverb/.exercism/metadata.json
new file mode 100644
index 0000000..92c8e56
--- /dev/null
+++ b/rust/proverb/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"proverb","id":"df96008ca5da43758fca9ac1ee80607e","url":"https://exercism.io/my/solutions/df96008ca5da43758fca9ac1ee80607e","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/proverb/.gitignore b/rust/proverb/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/proverb/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/proverb/Cargo.toml b/rust/proverb/Cargo.toml
new file mode 100644
index 0000000..4e09ea1
--- /dev/null
+++ b/rust/proverb/Cargo.toml
@@ -0,0 +1,6 @@
1[package]
2edition = "2018"
3name = "proverb"
4version = "1.1.0"
5
6[dependencies]
diff --git a/rust/proverb/README.md b/rust/proverb/README.md
new file mode 100644
index 0000000..b9efe0b
--- /dev/null
+++ b/rust/proverb/README.md
@@ -0,0 +1,97 @@
1# Proverb
2
3For want of a horseshoe nail, a kingdom was lost, or so the saying goes.
4
5Given a list of inputs, generate the relevant proverb. For example, given the list `["nail", "shoe", "horse", "rider", "message", "battle", "kingdom"]`, you will output the full text of this proverbial rhyme:
6
7```text
8For want of a nail the shoe was lost.
9For want of a shoe the horse was lost.
10For want of a horse the rider was lost.
11For want of a rider the message was lost.
12For want of a message the battle was lost.
13For want of a battle the kingdom was lost.
14And all for the want of a nail.
15```
16
17Note that the list of inputs may vary; your solution should be able to handle lists of arbitrary length and content. No line of the output text should be a static, unchanging string; all should vary according to the input given.
18
19## Rust Installation
20
21Refer to the [exercism help page][help-page] for Rust installation and learning
22resources.
23
24## Writing the Code
25
26Execute the tests with:
27
28```bash
29$ cargo test
30```
31
32All but the first test have been ignored. After you get the first test to
33pass, open the tests source file which is located in the `tests` directory
34and remove the `#[ignore]` flag from the next test and get the tests to pass
35again. Each separate test is a function with `#[test]` flag above it.
36Continue, until you pass every test.
37
38If you wish to run all ignored tests without editing the tests source file, use:
39
40```bash
41$ cargo test -- --ignored
42```
43
44To run a specific test, for example `some_test`, you can use:
45
46```bash
47$ cargo test some_test
48```
49
50If the specific test is ignored use:
51
52```bash
53$ cargo test some_test -- --ignored
54```
55
56To learn more about Rust tests refer to the [online test documentation][rust-tests]
57
58Make sure to read the [Modules][modules] chapter if you
59haven't already, it will help you with organizing your files.
60
61## Further improvements
62
63After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
64
65To format your solution, inside the solution directory use
66
67```bash
68cargo fmt
69```
70
71To see, if your solution contains some common ineffective use cases, inside the solution directory use
72
73```bash
74cargo clippy --all-targets
75```
76
77## Submitting the solution
78
79Generally 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.
80
81## Feedback, Issues, Pull Requests
82
83The [exercism/rust](https://github.com/exercism/rust) repository on 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!
84
85If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
86
87[help-page]: https://exercism.io/tracks/rust/learning
88[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
89[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
90[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
91
92## Source
93
94Wikipedia [http://en.wikipedia.org/wiki/For_Want_of_a_Nail](http://en.wikipedia.org/wiki/For_Want_of_a_Nail)
95
96## Submitting Incomplete Solutions
97It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/proverb/src/lib.rs b/rust/proverb/src/lib.rs
new file mode 100644
index 0000000..1046553
--- /dev/null
+++ b/rust/proverb/src/lib.rs
@@ -0,0 +1,15 @@
1use std::iter;
2
3pub fn build_proverb(list: &[&str]) -> String {
4 if list.is_empty() {
5 String::new()
6 } else {
7 let reason = |(a, b)| format!("For want of a {} the {} was lost.\n", a, b);
8 let bitter_end = format!("And all for the want of a {}.", list[0]);
9 list.iter()
10 .zip(list.iter().skip(1)) // .window(2) also works here
11 .map(reason)
12 .chain(iter::once(bitter_end))
13 .collect()
14 }
15}
diff --git a/rust/proverb/tests/proverb.rs b/rust/proverb/tests/proverb.rs
new file mode 100644
index 0000000..220de45
--- /dev/null
+++ b/rust/proverb/tests/proverb.rs
@@ -0,0 +1,70 @@
1use proverb::build_proverb;
2
3#[test]
4fn test_two_pieces() {
5 let input = vec!["nail", "shoe"];
6 let expected = vec![
7 "For want of a nail the shoe was lost.",
8 "And all for the want of a nail.",
9 ]
10 .join("\n");
11 assert_eq!(build_proverb(&input), expected);
12}
13
14// Notice the change in the last line at three pieces.
15#[test]
16fn test_three_pieces() {
17 let input = vec!["nail", "shoe", "horse"];
18 let expected = vec![
19 "For want of a nail the shoe was lost.",
20 "For want of a shoe the horse was lost.",
21 "And all for the want of a nail.",
22 ]
23 .join("\n");
24 assert_eq!(build_proverb(&input), expected);
25}
26
27#[test]
28fn test_one_piece() {
29 let input = vec!["nail"];
30 let expected = String::from("And all for the want of a nail.");
31 assert_eq!(build_proverb(&input), expected);
32}
33
34#[test]
35fn test_zero_pieces() {
36 let input: Vec<&str> = vec![];
37 let expected = String::new();
38 assert_eq!(build_proverb(&input), expected);
39}
40
41#[test]
42fn test_full() {
43 let input = vec![
44 "nail", "shoe", "horse", "rider", "message", "battle", "kingdom",
45 ];
46 let expected = vec![
47 "For want of a nail the shoe was lost.",
48 "For want of a shoe the horse was lost.",
49 "For want of a horse the rider was lost.",
50 "For want of a rider the message was lost.",
51 "For want of a message the battle was lost.",
52 "For want of a battle the kingdom was lost.",
53 "And all for the want of a nail.",
54 ]
55 .join("\n");
56 assert_eq!(build_proverb(&input), expected);
57}
58
59#[test]
60fn test_three_pieces_modernized() {
61 let input = vec!["pin", "gun", "soldier", "battle"];
62 let expected = vec![
63 "For want of a pin the gun was lost.",
64 "For want of a gun the soldier was lost.",
65 "For want of a soldier the battle was lost.",
66 "And all for the want of a pin.",
67 ]
68 .join("\n");
69 assert_eq!(build_proverb(&input), expected);
70}
diff --git a/rust/raindrops/.exercism/metadata.json b/rust/raindrops/.exercism/metadata.json
new file mode 100644
index 0000000..edfef77
--- /dev/null
+++ b/rust/raindrops/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"raindrops","id":"b8fea8a14bc4457f8f0f4f3d152c54c1","url":"https://exercism.io/my/solutions/b8fea8a14bc4457f8f0f4f3d152c54c1","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/raindrops/.gitignore b/rust/raindrops/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/raindrops/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/raindrops/Cargo.toml b/rust/raindrops/Cargo.toml
new file mode 100644
index 0000000..f37aa78
--- /dev/null
+++ b/rust/raindrops/Cargo.toml
@@ -0,0 +1,4 @@
1[package]
2edition = "2018"
3name = "raindrops"
4version = "1.1.0"
diff --git a/rust/raindrops/README.md b/rust/raindrops/README.md
new file mode 100644
index 0000000..3a30435
--- /dev/null
+++ b/rust/raindrops/README.md
@@ -0,0 +1,96 @@
1# Raindrops
2
3Your task is to convert a number into a string that contains raindrop sounds corresponding to certain potential factors. A factor is a number that evenly divides into another number, leaving no remainder. The simplest way to test if a one number is a factor of another is to use the [modulo operation](https://en.wikipedia.org/wiki/Modulo_operation).
4
5The rules of `raindrops` are that if a given number:
6
7- has 3 as a factor, add 'Pling' to the result.
8- has 5 as a factor, add 'Plang' to the result.
9- has 7 as a factor, add 'Plong' to the result.
10- _does not_ have any of 3, 5, or 7 as a factor, the result should be the digits of the number.
11
12## Examples
13
14- 28 has 7 as a factor, but not 3 or 5, so the result would be "Plong".
15- 30 has both 3 and 5 as factors, but not 7, so the result would be "PlingPlang".
16- 34 is not factored by 3, 5, or 7, so the result would be "34".
17
18## Rust Installation
19
20Refer to the [exercism help page][help-page] for Rust installation and learning
21resources.
22
23## Writing the Code
24
25Execute the tests with:
26
27```bash
28$ cargo test
29```
30
31All but the first test have been ignored. After you get the first test to
32pass, open the tests source file which is located in the `tests` directory
33and remove the `#[ignore]` flag from the next test and get the tests to pass
34again. Each separate test is a function with `#[test]` flag above it.
35Continue, until you pass every test.
36
37If you wish to run all ignored tests without editing the tests source file, use:
38
39```bash
40$ cargo test -- --ignored
41```
42
43To run a specific test, for example `some_test`, you can use:
44
45```bash
46$ cargo test some_test
47```
48
49If the specific test is ignored use:
50
51```bash
52$ cargo test some_test -- --ignored
53```
54
55To learn more about Rust tests refer to the [online test documentation][rust-tests]
56
57Make sure to read the [Modules][modules] chapter if you
58haven't already, it will help you with organizing your files.
59
60## Further improvements
61
62After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
63
64To format your solution, inside the solution directory use
65
66```bash
67cargo fmt
68```
69
70To see, if your solution contains some common ineffective use cases, inside the solution directory use
71
72```bash
73cargo clippy --all-targets
74```
75
76## Submitting the solution
77
78Generally 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.
79
80## Feedback, Issues, Pull Requests
81
82The [exercism/rust](https://github.com/exercism/rust) repository on 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!
83
84If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
85
86[help-page]: https://exercism.io/tracks/rust/learning
87[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
88[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
89[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
90
91## Source
92
93A variation on FizzBuzz, a famous technical interview question that is intended to weed out potential candidates. That question is itself derived from Fizz Buzz, a popular children's game for teaching division. [https://en.wikipedia.org/wiki/Fizz_buzz](https://en.wikipedia.org/wiki/Fizz_buzz)
94
95## Submitting Incomplete Solutions
96It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/raindrops/src/lib.rs b/rust/raindrops/src/lib.rs
new file mode 100644
index 0000000..811c569
--- /dev/null
+++ b/rust/raindrops/src/lib.rs
@@ -0,0 +1,28 @@
1struct Drops {
2 num: u32,
3 drops: Option<String>
4}
5
6impl Drops {
7 pub fn new(num: u32) -> Drops {
8 Drops { num, drops: None }
9 }
10
11 pub fn add_if_factor(&mut self, div: u32, suffix: &str) {
12 if self.num % div == 0 {
13 self.drops.get_or_insert(String::new()).push_str(suffix);
14 }
15 }
16
17 pub fn get(self) -> String {
18 self.drops.unwrap_or(self.num.to_string())
19 }
20}
21
22pub fn raindrops(n: u32) -> String {
23 let mut drops = Drops::new(n);
24 drops.add_if_factor(3, "Pling");
25 drops.add_if_factor(5, "Plang");
26 drops.add_if_factor(7, "Plong");
27 drops.get()
28}
diff --git a/rust/raindrops/tests/raindrops.rs b/rust/raindrops/tests/raindrops.rs
new file mode 100644
index 0000000..000c639
--- /dev/null
+++ b/rust/raindrops/tests/raindrops.rs
@@ -0,0 +1,96 @@
1use raindrops;
2
3#[test]
4fn test_1() {
5 assert_eq!("1", raindrops::raindrops(1));
6}
7
8#[test]
9fn test_3() {
10 assert_eq!("Pling", raindrops::raindrops(3));
11}
12
13#[test]
14fn test_5() {
15 assert_eq!("Plang", raindrops::raindrops(5));
16}
17
18#[test]
19fn test_7() {
20 assert_eq!("Plong", raindrops::raindrops(7));
21}
22
23#[test]
24fn test_6() {
25 assert_eq!("Pling", raindrops::raindrops(6));
26}
27
28#[test]
29fn test_8() {
30 assert_eq!("8", raindrops::raindrops(8));
31}
32
33#[test]
34fn test_9() {
35 assert_eq!("Pling", raindrops::raindrops(9));
36}
37
38#[test]
39fn test_10() {
40 assert_eq!("Plang", raindrops::raindrops(10));
41}
42
43#[test]
44fn test_14() {
45 assert_eq!("Plong", raindrops::raindrops(14));
46}
47
48#[test]
49fn test_15() {
50 assert_eq!("PlingPlang", raindrops::raindrops(15));
51}
52
53#[test]
54fn test_21() {
55 assert_eq!("PlingPlong", raindrops::raindrops(21));
56}
57
58#[test]
59fn test_25() {
60 assert_eq!("Plang", raindrops::raindrops(25));
61}
62
63#[test]
64fn test_27() {
65 assert_eq!("Pling", raindrops::raindrops(27));
66}
67
68#[test]
69fn test_35() {
70 assert_eq!("PlangPlong", raindrops::raindrops(35));
71}
72
73#[test]
74fn test_49() {
75 assert_eq!("Plong", raindrops::raindrops(49));
76}
77
78#[test]
79fn test_52() {
80 assert_eq!("52", raindrops::raindrops(52));
81}
82
83#[test]
84fn test_105() {
85 assert_eq!("PlingPlangPlong", raindrops::raindrops(105));
86}
87
88#[test]
89fn test_3125() {
90 assert_eq!("Plang", raindrops::raindrops(3125));
91}
92
93#[test]
94fn test_12121() {
95 assert_eq!("12121", raindrops::raindrops(12_121));
96}
diff --git a/rust/reverse-string/.exercism/metadata.json b/rust/reverse-string/.exercism/metadata.json
new file mode 100644
index 0000000..667d0ed
--- /dev/null
+++ b/rust/reverse-string/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"reverse-string","id":"f735abfd7ff5444fb0f6c68c5fbef1b9","url":"https://exercism.io/my/solutions/f735abfd7ff5444fb0f6c68c5fbef1b9","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/reverse-string/.gitignore b/rust/reverse-string/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/reverse-string/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/reverse-string/Cargo.toml b/rust/reverse-string/Cargo.toml
new file mode 100644
index 0000000..bdf501c
--- /dev/null
+++ b/rust/reverse-string/Cargo.toml
@@ -0,0 +1,10 @@
1[dependencies]
2unicode-segmentation = "1.3.0"
3
4[features]
5grapheme = []
6
7[package]
8edition = "2018"
9name = "reverse_string"
10version = "1.2.0"
diff --git a/rust/reverse-string/README.md b/rust/reverse-string/README.md
new file mode 100644
index 0000000..78e9753
--- /dev/null
+++ b/rust/reverse-string/README.md
@@ -0,0 +1,103 @@
1# Reverse String
2
3Reverse a string
4
5For example:
6input: "cool"
7output: "looc"
8
9## Bonus
10Test your function on this string: `uüu` and see what happens. Try to write a function that properly
11reverses this string. Hint: grapheme clusters
12
13To get the bonus test to run, remove the ignore flag (`#[ignore]`) from the
14last test, and execute the tests with:
15
16```bash
17$ cargo test --features grapheme
18```
19
20You will need to use external libraries (a `crate` in rust lingo) for the bonus task. A good place to look for those is [crates.io](https://crates.io/), the official repository of crates.
21
22[Check the documentation](https://doc.rust-lang.org/cargo/guide/dependencies.html) for instructions on how to use external crates in your projects.
23
24
25## Rust Installation
26
27Refer to the [exercism help page][help-page] for Rust installation and learning
28resources.
29
30## Writing the Code
31
32Execute the tests with:
33
34```bash
35$ cargo test
36```
37
38All but the first test have been ignored. After you get the first test to
39pass, open the tests source file which is located in the `tests` directory
40and remove the `#[ignore]` flag from the next test and get the tests to pass
41again. Each separate test is a function with `#[test]` flag above it.
42Continue, until you pass every test.
43
44If you wish to run all ignored tests without editing the tests source file, use:
45
46```bash
47$ cargo test -- --ignored
48```
49
50To run a specific test, for example `some_test`, you can use:
51
52```bash
53$ cargo test some_test
54```
55
56If the specific test is ignored use:
57
58```bash
59$ cargo test some_test -- --ignored
60```
61
62To learn more about Rust tests refer to the [online test documentation][rust-tests]
63
64Make sure to read the [Modules][modules] chapter if you
65haven't already, it will help you with organizing your files.
66
67## Further improvements
68
69After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
70
71To format your solution, inside the solution directory use
72
73```bash
74cargo fmt
75```
76
77To see, if your solution contains some common ineffective use cases, inside the solution directory use
78
79```bash
80cargo clippy --all-targets
81```
82
83## Submitting the solution
84
85Generally 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.
86
87## Feedback, Issues, Pull Requests
88
89The [exercism/rust](https://github.com/exercism/rust) repository on 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!
90
91If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
92
93[help-page]: https://exercism.io/tracks/rust/learning
94[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
95[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
96[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
97
98## Source
99
100Introductory challenge to reverse an input string [https://medium.freecodecamp.org/how-to-reverse-a-string-in-javascript-in-3-different-ways-75e4763c68cb](https://medium.freecodecamp.org/how-to-reverse-a-string-in-javascript-in-3-different-ways-75e4763c68cb)
101
102## Submitting Incomplete Solutions
103It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/reverse-string/src/lib.rs b/rust/reverse-string/src/lib.rs
new file mode 100644
index 0000000..f488a6e
--- /dev/null
+++ b/rust/reverse-string/src/lib.rs
@@ -0,0 +1,5 @@
1use unicode_segmentation::UnicodeSegmentation;
2
3pub fn reverse(input: &str) -> String {
4 UnicodeSegmentation::graphemes(input, true).rev().collect()
5}
diff --git a/rust/reverse-string/tests/reverse-string.rs b/rust/reverse-string/tests/reverse-string.rs
new file mode 100644
index 0000000..9b17bb0
--- /dev/null
+++ b/rust/reverse-string/tests/reverse-string.rs
@@ -0,0 +1,62 @@
1//! Tests for reverse-string
2//!
3//! Generated by [script][script] using [canonical data][canonical-data]
4//!
5//! [script]: https://github.com/exercism/rust/blob/b829ce2/bin/init_exercise.py
6//! [canonical-data]: https://raw.githubusercontent.com/exercism/problem-specifications/master/exercises/reverse-string/canonical_data.json
7
8use reverse_string::*;
9
10/// Process a single test case for the property `reverse`
11fn process_reverse_case(input: &str, expected: &str) {
12 assert_eq!(&reverse(input), expected)
13}
14
15#[test]
16/// empty string
17fn test_an_empty_string() {
18 process_reverse_case("", "");
19}
20
21#[test]
22/// a word
23fn test_a_word() {
24 process_reverse_case("robot", "tobor");
25}
26
27#[test]
28/// a capitalized word
29fn test_a_capitalized_word() {
30 process_reverse_case("Ramen", "nemaR");
31}
32
33#[test]
34/// a sentence with punctuation
35fn test_a_sentence_with_punctuation() {
36 process_reverse_case("I'm hungry!", "!yrgnuh m'I");
37}
38
39#[test]
40/// a palindrome
41fn test_a_palindrome() {
42 process_reverse_case("racecar", "racecar");
43}
44
45#[test]
46/// an even-sized word
47fn test_an_even_sized_word() {
48 process_reverse_case("drawer", "reward");
49}
50
51#[test]
52/// wide characters
53fn test_wide_characters() {
54 process_reverse_case("子猫", "猫子");
55}
56
57#[test]
58#[cfg(feature = "grapheme")]
59/// grapheme clusters
60fn test_grapheme_clusters() {
61 process_reverse_case("uüu", "uüu");
62}
diff --git a/rust/saddle-points/.exercism/metadata.json b/rust/saddle-points/.exercism/metadata.json
new file mode 100644
index 0000000..cb44aa3
--- /dev/null
+++ b/rust/saddle-points/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"saddle-points","id":"18964e9c5971482790e97a569346a40d","url":"https://exercism.io/my/solutions/18964e9c5971482790e97a569346a40d","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/saddle-points/.gitignore b/rust/saddle-points/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/saddle-points/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/saddle-points/Cargo.toml b/rust/saddle-points/Cargo.toml
new file mode 100644
index 0000000..5f262e2
--- /dev/null
+++ b/rust/saddle-points/Cargo.toml
@@ -0,0 +1,6 @@
1[package]
2edition = "2018"
3name = "saddle-points"
4version = "1.3.0"
5
6[dependencies]
diff --git a/rust/saddle-points/README.md b/rust/saddle-points/README.md
new file mode 100644
index 0000000..84647d0
--- /dev/null
+++ b/rust/saddle-points/README.md
@@ -0,0 +1,132 @@
1# Saddle Points
2
3Detect saddle points in a matrix.
4
5So say you have a matrix like so:
6
7```text
8 1 2 3
9 |---------
101 | 9 8 7
112 | 5 3 2 <--- saddle point at column 1, row 2, with value 5
123 | 6 6 7
13```
14
15It has a saddle point at column 1, row 2.
16
17It's called a "saddle point" because it is greater than or equal to
18every element in its row and less than or equal to every element in
19its column.
20
21A matrix may have zero or more saddle points.
22
23Your code should be able to provide the (possibly empty) list of all the
24saddle points for any given matrix.
25
26The matrix can have a different number of rows and columns (Non square).
27
28Note that you may find other definitions of matrix saddle points online,
29but the tests for this exercise follow the above unambiguous definition.
30
31## Rust Indices Start At 0
32
33By convention, ordered sequences of values in Rust have their contents numbered
34("indexed") starting from 0. This applies regardless of what the rest of the
35exercise description in this README says, such as references to indices that
36start at 1, so you will have to subtract 1 to translate those index numbers
37to Rust index numbers.
38
39## Efficiency Notice
40
41This exercise uses a _vector of vectors_ to store the content of matrices. While
42this exercise is designed to help students understand basic concepts about
43vectors, such as indexing, and that nested data types are legal, _vector of
44vectors_ is a suboptimal choice for high-performance matrix algebra and any
45similar efficient processing of larger amounts of data.
46
47The detailed explanation of this inefficiency is beyond the scope of this
48exercise and this learning track in general. This aspect is known as
49[cache locality](https://stackoverflow.com/questions/12065774/why-does-cache-locality-matter-for-array-performance)
50and you can find a good introduction to it by clicking that link if you'd like
51to learn more about details of a modern computer architecture.
52
53
54## Rust Installation
55
56Refer to the [exercism help page][help-page] for Rust installation and learning
57resources.
58
59## Writing the Code
60
61Execute the tests with:
62
63```bash
64$ cargo test
65```
66
67All but the first test have been ignored. After you get the first test to
68pass, open the tests source file which is located in the `tests` directory
69and remove the `#[ignore]` flag from the next test and get the tests to pass
70again. Each separate test is a function with `#[test]` flag above it.
71Continue, until you pass every test.
72
73If you wish to run all ignored tests without editing the tests source file, use:
74
75```bash
76$ cargo test -- --ignored
77```
78
79To run a specific test, for example `some_test`, you can use:
80
81```bash
82$ cargo test some_test
83```
84
85If the specific test is ignored use:
86
87```bash
88$ cargo test some_test -- --ignored
89```
90
91To learn more about Rust tests refer to the [online test documentation][rust-tests]
92
93Make sure to read the [Modules][modules] chapter if you
94haven't already, it will help you with organizing your files.
95
96## Further improvements
97
98After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
99
100To format your solution, inside the solution directory use
101
102```bash
103cargo fmt
104```
105
106To see, if your solution contains some common ineffective use cases, inside the solution directory use
107
108```bash
109cargo clippy --all-targets
110```
111
112## Submitting the solution
113
114Generally 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.
115
116## Feedback, Issues, Pull Requests
117
118The [exercism/rust](https://github.com/exercism/rust) repository on 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!
119
120If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
121
122[help-page]: https://exercism.io/tracks/rust/learning
123[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
124[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
125[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
126
127## Source
128
129J Dalbey's Programming Practice problems [http://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html](http://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html)
130
131## Submitting Incomplete Solutions
132It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/saddle-points/src/lib.rs b/rust/saddle-points/src/lib.rs
new file mode 100644
index 0000000..7123243
--- /dev/null
+++ b/rust/saddle-points/src/lib.rs
@@ -0,0 +1,16 @@
1fn is_min(mat: &[Vec<u64>], col: usize, row: usize) -> bool {
2 (0..mat.len()).all(|r| mat[r][col] >= mat[row][col])
3}
4
5pub fn find_saddle_points(input: &[Vec<u64>]) -> Vec<(usize, usize)> {
6 let mut res = vec![];
7 for (row,relem) in input.iter().enumerate() {
8 let m = relem.iter().max();
9 for (col,celem) in relem.iter().enumerate() {
10 if (m == Some(celem)) && is_min(input,col,row) {
11 res.push((row,col));
12 }
13 }
14 }
15 res
16}
diff --git a/rust/saddle-points/tests/saddle-points.rs b/rust/saddle-points/tests/saddle-points.rs
new file mode 100644
index 0000000..1fbc2de
--- /dev/null
+++ b/rust/saddle-points/tests/saddle-points.rs
@@ -0,0 +1,98 @@
1use saddle_points;
2
3use saddle_points::find_saddle_points;
4
5// We don't care about order
6fn find_sorted_saddle_points(input: &[Vec<u64>]) -> Vec<(usize, usize)> {
7 let mut result = saddle_points::find_saddle_points(input);
8 result.sort();
9 result
10}
11
12#[test]
13fn identify_single_saddle_point() {
14 let input = vec![vec![9, 8, 7], vec![5, 3, 2], vec![6, 6, 7]];
15 assert_eq!(vec![(1, 0)], find_saddle_points(&input));
16}
17
18#[test]
19fn identify_empty_matrix() {
20 let input = vec![vec![], vec![], vec![]];
21 let expected: Vec<(usize, usize)> = Vec::new();
22 assert_eq!(expected, find_saddle_points(&input));
23}
24
25#[test]
26fn identify_lack_of_saddle_point() {
27 let input = vec![vec![1, 2, 3], vec![3, 1, 2], vec![2, 3, 1]];
28 let expected: Vec<(usize, usize)> = Vec::new();
29 assert_eq!(expected, find_saddle_points(&input));
30}
31
32#[test]
33fn multiple_saddle_points_in_col() {
34 let input = vec![vec![4, 5, 4], vec![3, 5, 5], vec![1, 5, 4]];
35 assert_eq!(
36 vec![(0, 1), (1, 1), (2, 1)],
37 find_sorted_saddle_points(&input)
38 );
39}
40
41#[test]
42fn multiple_saddle_points_in_row() {
43 let input = vec![vec![6, 7, 8], vec![5, 5, 5], vec![7, 5, 6]];
44 assert_eq!(
45 vec![(1, 0), (1, 1), (1, 2)],
46 find_sorted_saddle_points(&input)
47 );
48}
49
50#[test]
51fn identify_bottom_right_saddle_point() {
52 let input = vec![vec![8, 7, 9], vec![6, 7, 6], vec![3, 2, 5]];
53 assert_eq!(vec![(2, 2)], find_saddle_points(&input));
54}
55
56// track specific as of v1.3
57#[test]
58fn non_square_matrix_high() {
59 let input = vec![vec![1, 5], vec![3, 6], vec![2, 7], vec![3, 8]];
60 assert_eq!(vec![(0, 1)], find_saddle_points(&input));
61}
62
63#[test]
64fn non_square_matrix_wide() {
65 let input = vec![vec![3, 1, 3], vec![3, 2, 4]];
66 assert_eq!(vec![(0, 0), (0, 2)], find_sorted_saddle_points(&input));
67}
68
69#[test]
70fn single_column_matrix() {
71 let input = vec![vec![2], vec![1], vec![4], vec![1]];
72 assert_eq!(vec![(1, 0), (3, 0)], find_sorted_saddle_points(&input));
73}
74
75#[test]
76fn single_row_matrix() {
77 let input = vec![vec![2, 5, 3, 5]];
78 assert_eq!(vec![(0, 1), (0, 3)], find_sorted_saddle_points(&input));
79}
80
81#[test]
82fn identify_all_saddle_points() {
83 let input = vec![vec![5, 5, 5], vec![5, 5, 5], vec![5, 5, 5]];
84 assert_eq!(
85 vec![
86 (0, 0),
87 (0, 1),
88 (0, 2),
89 (1, 0),
90 (1, 1),
91 (1, 2),
92 (2, 0),
93 (2, 1),
94 (2, 2)
95 ],
96 find_sorted_saddle_points(&input)
97 );
98}
diff --git a/rust/simple-linked-list/.exercism/metadata.json b/rust/simple-linked-list/.exercism/metadata.json
new file mode 100644
index 0000000..4c7e1a6
--- /dev/null
+++ b/rust/simple-linked-list/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"simple-linked-list","id":"a0e2dbad46184d6a8ee961fff5e6c497","url":"https://exercism.io/my/solutions/a0e2dbad46184d6a8ee961fff5e6c497","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/simple-linked-list/.gitignore b/rust/simple-linked-list/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/simple-linked-list/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/simple-linked-list/Cargo.toml b/rust/simple-linked-list/Cargo.toml
new file mode 100644
index 0000000..25a62e7
--- /dev/null
+++ b/rust/simple-linked-list/Cargo.toml
@@ -0,0 +1,6 @@
1[package]
2edition = "2018"
3name = "simple_linked_list"
4version = "0.1.0"
5
6[dependencies]
diff --git a/rust/simple-linked-list/README.md b/rust/simple-linked-list/README.md
new file mode 100644
index 0000000..47178e8
--- /dev/null
+++ b/rust/simple-linked-list/README.md
@@ -0,0 +1,137 @@
1# Simple Linked List
2
3Write a simple linked list implementation that uses Elements and a List.
4
5The linked list is a fundamental data structure in computer science,
6often used in the implementation of other data structures. They're
7pervasive in functional programming languages, such as Clojure, Erlang,
8or Haskell, but far less common in imperative languages such as Ruby or
9Python.
10
11The simplest kind of linked list is a singly linked list. Each element in the
12list contains data and a "next" field pointing to the next element in the list
13of elements.
14
15This variant of linked lists is often used to represent sequences or
16push-down stacks (also called a LIFO stack; Last In, First Out).
17
18As a first take, lets create a singly linked list to contain the range (1..10),
19and provide functions to reverse a linked list and convert to and from arrays.
20
21When implementing this in a language with built-in linked lists,
22implement your own abstract data type.
23
24## Implementation Hints
25
26Do not implement the struct `SimpleLinkedList` as a wrapper around a `Vec`. Instead, allocate nodes on the heap.
27This might be implemented as:
28```
29pub struct SimpleLinkedList<T> {
30 head: Option<Box<Node<T>>>,
31}
32```
33The `head` field points to the first element (Node) of this linked list.
34This implementation also requires a struct `Node` with the following fields:
35```
36struct Node<T> {
37 data: T,
38 next: Option<Box<Node<T>>>,
39}
40```
41`data` contains the stored data, and `next` points to the following node (if available) or None.
42
43### Why `Option<Box<Node<T>>>` and not just `Option<Node<T>>`?
44Try it on your own. You will get the following error.
45
46```
47| struct Node<T>
48| ^^^^^^^^^^^^^^ recursive type has infinite size
49...
50| next: Option<Node<T>>,
51| --------------------- recursive without indirection
52 ```
53
54 The problem is that at compile time the size of next must be known.
55 Since `next` is recursive ("a node has a node has a node..."), the compiler does not know how much memory is to be allocated.
56 In contrast, [Box](https://doc.rust-lang.org/std/boxed/) is a heap pointer with a defined size.
57
58
59## Rust Installation
60
61Refer to the [exercism help page][help-page] for Rust installation and learning
62resources.
63
64## Writing the Code
65
66Execute the tests with:
67
68```bash
69$ cargo test
70```
71
72All but the first test have been ignored. After you get the first test to
73pass, open the tests source file which is located in the `tests` directory
74and remove the `#[ignore]` flag from the next test and get the tests to pass
75again. Each separate test is a function with `#[test]` flag above it.
76Continue, until you pass every test.
77
78If you wish to run all ignored tests without editing the tests source file, use:
79
80```bash
81$ cargo test -- --ignored
82```
83
84To run a specific test, for example `some_test`, you can use:
85
86```bash
87$ cargo test some_test
88```
89
90If the specific test is ignored use:
91
92```bash
93$ cargo test some_test -- --ignored
94```
95
96To learn more about Rust tests refer to the [online test documentation][rust-tests]
97
98Make sure to read the [Modules][modules] chapter if you
99haven't already, it will help you with organizing your files.
100
101## Further improvements
102
103After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
104
105To format your solution, inside the solution directory use
106
107```bash
108cargo fmt
109```
110
111To see, if your solution contains some common ineffective use cases, inside the solution directory use
112
113```bash
114cargo clippy --all-targets
115```
116
117## Submitting the solution
118
119Generally 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.
120
121## Feedback, Issues, Pull Requests
122
123The [exercism/rust](https://github.com/exercism/rust) repository on 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!
124
125If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
126
127[help-page]: https://exercism.io/tracks/rust/learning
128[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
129[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
130[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
131
132## Source
133
134Inspired by 'Data Structures and Algorithms with Object-Oriented Design Patterns in Ruby', singly linked-lists. [https://web.archive.org/web/20160731005714/http://brpreiss.com/books/opus8/html/page96.html](https://web.archive.org/web/20160731005714/http://brpreiss.com/books/opus8/html/page96.html)
135
136## Submitting Incomplete Solutions
137It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/simple-linked-list/src/lib.rs b/rust/simple-linked-list/src/lib.rs
new file mode 100644
index 0000000..75e82f5
--- /dev/null
+++ b/rust/simple-linked-list/src/lib.rs
@@ -0,0 +1,109 @@
1use std::iter::FromIterator;
2
3#[derive(Debug)]
4struct Node<T> {
5 data: T,
6 next: Option<Box<Node<T>>>,
7}
8
9impl<T> Node<T> {
10 pub fn new(data: T, next: Option<Box<Node<T>>>) -> Self {
11 Node { data, next }
12 }
13
14 pub fn len(&self) -> usize {
15 1 + self.next.as_ref().map(|n| n.len()).unwrap_or(0)
16 }
17}
18
19#[derive(Debug)]
20pub struct SimpleLinkedList<T> {
21 head: Option<Box<Node<T>>>,
22}
23
24impl<T> SimpleLinkedList<T> {
25 pub fn new() -> Self {
26 SimpleLinkedList { head: None }
27 }
28
29 // You may be wondering why it's necessary to have is_empty()
30 // when it can easily be determined from len().
31 // It's good custom to have both because len() can be expensive for some types,
32 // whereas is_empty() is almost always cheap.
33 // (Also ask yourself whether len() is expensive for SimpleLinkedList)
34 pub fn is_empty(&self) -> bool {
35 self.head.is_none()
36 }
37
38 pub fn len(&self) -> usize {
39 self.head.as_ref().map(|n| n.len()).unwrap_or(0)
40 }
41
42 pub fn push(&mut self, _element: T) {
43 // let node = Box::new(Node::new(_element, self.head.take()));
44 // self.head.replace(node);
45 self.head = Some(Box::new(Node::new(_element, self.head.take())));
46 }
47
48 pub fn pop(&mut self) -> Option<T> {
49 self.head.take().map(|n| {
50 // n.next.map(|n1| self.head.replace(n1));
51 self.head = n.next;
52 n.data
53 })
54 }
55
56 pub fn peek(&self) -> Option<&T> {
57 self.head.as_ref().map(|n| &n.data)
58 }
59
60 pub fn rev(self) -> SimpleLinkedList<T> {
61 self.rev_aux(SimpleLinkedList::new())
62 }
63
64 pub fn rev_aux(mut self, mut acc: SimpleLinkedList<T>) -> SimpleLinkedList<T> {
65 if let Some(e) = self.pop() {
66 acc.push(e);
67 self.rev_aux(acc)
68 } else {
69 acc
70 }
71 }
72
73 fn into_aux(mut self, mut acc: Vec<T>) -> Vec<T> {
74 if let Some(e) = self.pop() {
75 acc.push(e);
76 self.into_aux(acc)
77 } else {
78 acc
79 }
80 }
81}
82
83impl<T> FromIterator<T> for SimpleLinkedList<T> {
84 fn from_iter<I: IntoIterator<Item = T>>(_iter: I) -> Self {
85 _iter
86 .into_iter()
87 .fold(SimpleLinkedList::new(), |mut acc, n| {
88 acc.push(n);
89 acc
90 })
91 }
92}
93
94// In general, it would be preferable to implement IntoIterator for SimpleLinkedList<T>
95// instead of implementing an explicit conversion to a vector. This is because, together,
96// FromIterator and IntoIterator enable conversion between arbitrary collections.
97// Given that implementation, converting to a vector is trivial:
98//
99// let vec: Vec<_> = simple_linked_list.into_iter().collect();
100//
101// The reason this exercise's API includes an explicit conversion to Vec<T> instead
102// of IntoIterator is that implementing that interface is fairly complicated, and
103// demands more of the student than we expect at this point in the track.
104
105impl<T> Into<Vec<T>> for SimpleLinkedList<T> {
106 fn into(self) -> Vec<T> {
107 self.rev().into_aux(Vec::new())
108 }
109}
diff --git a/rust/simple-linked-list/tests/simple-linked-list.rs b/rust/simple-linked-list/tests/simple-linked-list.rs
new file mode 100644
index 0000000..c89f8b5
--- /dev/null
+++ b/rust/simple-linked-list/tests/simple-linked-list.rs
@@ -0,0 +1,118 @@
1use simple_linked_list::SimpleLinkedList;
2
3#[test]
4fn test_new_list_is_empty() {
5 let list: SimpleLinkedList<u32> = SimpleLinkedList::new();
6 assert_eq!(list.len(), 0, "list's length must be 0");
7}
8
9#[test]
10fn test_push_increments_length() {
11 let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new();
12 list.push(1);
13 assert_eq!(list.len(), 1, "list's length must be 1");
14 list.push(2);
15 assert_eq!(list.len(), 2, "list's length must be 2");
16}
17
18#[test]
19fn test_pop_decrements_length() {
20 let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new();
21 list.push(1);
22 list.push(2);
23 list.pop();
24 assert_eq!(list.len(), 1, "list's length must be 1");
25 list.pop();
26 assert_eq!(list.len(), 0, "list's length must be 0");
27}
28
29#[test]
30fn test_is_empty() {
31 let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new();
32 assert!(list.is_empty(), "List wasn't empty on creation");
33 for inserts in 0..100 {
34 for i in 0..inserts {
35 list.push(i);
36 assert!(
37 !list.is_empty(),
38 "List was empty after having inserted {}/{} elements",
39 i,
40 inserts
41 );
42 }
43 for i in 0..inserts {
44 assert!(
45 !list.is_empty(),
46 "List was empty before removing {}/{} elements",
47 i,
48 inserts
49 );
50 list.pop();
51 }
52 assert!(
53 list.is_empty(),
54 "List wasn't empty after having removed {} elements",
55 inserts
56 );
57 }
58}
59
60#[test]
61fn test_pop_returns_head_element_and_removes_it() {
62 let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new();
63 list.push(1);
64 list.push(2);
65 assert_eq!(list.pop(), Some(2), "Element must be 2");
66 assert_eq!(list.pop(), Some(1), "Element must be 1");
67 assert_eq!(list.pop(), None, "No element should be contained in list");
68}
69
70#[test]
71fn test_peek_returns_reference_to_head_element_but_does_not_remove_it() {
72 let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new();
73 assert_eq!(list.peek(), None, "No element should be contained in list");
74 list.push(2);
75 assert_eq!(list.peek(), Some(&2), "Element must be 2");
76 assert_eq!(list.peek(), Some(&2), "Element must be still 2");
77 list.push(3);
78 assert_eq!(list.peek(), Some(&3), "Head element is now 3");
79 assert_eq!(list.pop(), Some(3), "Element must be 3");
80 assert_eq!(list.peek(), Some(&2), "Head element is now 2");
81 assert_eq!(list.pop(), Some(2), "Element must be 2");
82 assert_eq!(list.peek(), None, "No element should be contained in list");
83}
84
85#[test]
86fn test_from_slice() {
87 let mut array = vec!["1", "2", "3", "4"];
88 let mut list: SimpleLinkedList<_> = array.drain(..).collect();
89 assert_eq!(list.pop(), Some("4"));
90 assert_eq!(list.pop(), Some("3"));
91 assert_eq!(list.pop(), Some("2"));
92 assert_eq!(list.pop(), Some("1"));
93}
94
95#[test]
96fn test_reverse() {
97 let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new();
98 list.push(1);
99 list.push(2);
100 list.push(3);
101 let mut rev_list = list.rev();
102 assert_eq!(rev_list.pop(), Some(1));
103 assert_eq!(rev_list.pop(), Some(2));
104 assert_eq!(rev_list.pop(), Some(3));
105 assert_eq!(rev_list.pop(), None);
106}
107
108#[test]
109fn test_into_vector() {
110 let mut v = Vec::new();
111 let mut s = SimpleLinkedList::new();
112 for i in 1..4 {
113 v.push(i);
114 s.push(i);
115 }
116 let s_as_vec: Vec<i32> = s.into();
117 assert_eq!(v, s_as_vec);
118}
diff --git a/rust/sum-of-multiples/.exercism/metadata.json b/rust/sum-of-multiples/.exercism/metadata.json
new file mode 100644
index 0000000..98ef3f1
--- /dev/null
+++ b/rust/sum-of-multiples/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"sum-of-multiples","id":"9f1716859ebb4e38b10e5dfbd3858ad3","url":"https://exercism.io/my/solutions/9f1716859ebb4e38b10e5dfbd3858ad3","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/rust/sum-of-multiples/.gitignore b/rust/sum-of-multiples/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/rust/sum-of-multiples/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/rust/sum-of-multiples/Cargo.toml b/rust/sum-of-multiples/Cargo.toml
new file mode 100644
index 0000000..a006459
--- /dev/null
+++ b/rust/sum-of-multiples/Cargo.toml
@@ -0,0 +1,4 @@
1[package]
2edition = "2018"
3name = "sum-of-multiples"
4version = "1.5.0"
diff --git a/rust/sum-of-multiples/README.md b/rust/sum-of-multiples/README.md
new file mode 100644
index 0000000..72bb481
--- /dev/null
+++ b/rust/sum-of-multiples/README.md
@@ -0,0 +1,89 @@
1# Sum Of Multiples
2
3Given a number, find the sum of all the unique multiples of particular numbers up to
4but not including that number.
5
6If we list all the natural numbers below 20 that are multiples of 3 or 5,
7we get 3, 5, 6, 9, 10, 12, 15, and 18.
8
9The sum of these multiples is 78.
10
11## Rust Installation
12
13Refer to the [exercism help page][help-page] for Rust installation and learning
14resources.
15
16## Writing the Code
17
18Execute the tests with:
19
20```bash
21$ cargo test
22```
23
24All but the first test have been ignored. After you get the first test to
25pass, open the tests source file which is located in the `tests` directory
26and remove the `#[ignore]` flag from the next test and get the tests to pass
27again. Each separate test is a function with `#[test]` flag above it.
28Continue, until you pass every test.
29
30If you wish to run all ignored tests without editing the tests source file, use:
31
32```bash
33$ cargo test -- --ignored
34```
35
36To run a specific test, for example `some_test`, you can use:
37
38```bash
39$ cargo test some_test
40```
41
42If the specific test is ignored use:
43
44```bash
45$ cargo test some_test -- --ignored
46```
47
48To learn more about Rust tests refer to the [online test documentation][rust-tests]
49
50Make sure to read the [Modules][modules] chapter if you
51haven't already, it will help you with organizing your files.
52
53## Further improvements
54
55After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
56
57To format your solution, inside the solution directory use
58
59```bash
60cargo fmt
61```
62
63To see, if your solution contains some common ineffective use cases, inside the solution directory use
64
65```bash
66cargo clippy --all-targets
67```
68
69## Submitting the solution
70
71Generally 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.
72
73## Feedback, Issues, Pull Requests
74
75The [exercism/rust](https://github.com/exercism/rust) repository on 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!
76
77If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
78
79[help-page]: https://exercism.io/tracks/rust/learning
80[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
81[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
82[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
83
84## Source
85
86A variation on Problem 1 at Project Euler [http://projecteuler.net/problem=1](http://projecteuler.net/problem=1)
87
88## Submitting Incomplete Solutions
89It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/rust/sum-of-multiples/src/lib.rs b/rust/sum-of-multiples/src/lib.rs
new file mode 100644
index 0000000..148419d
--- /dev/null
+++ b/rust/sum-of-multiples/src/lib.rs
@@ -0,0 +1,3 @@
1pub fn sum_of_multiples(limit: u32, factors: &[u32]) -> u32 {
2 (1..limit).filter(|x| factors.iter().filter(|&&x| x != 0).any(|y| x % y == 0)).sum()
3}
diff --git a/rust/sum-of-multiples/tests/sum-of-multiples.rs b/rust/sum-of-multiples/tests/sum-of-multiples.rs
new file mode 100644
index 0000000..369289c
--- /dev/null
+++ b/rust/sum-of-multiples/tests/sum-of-multiples.rs
@@ -0,0 +1,81 @@
1use sum_of_multiples::*;
2
3#[test]
4fn no_multiples_within_limit() {
5 assert_eq!(0, sum_of_multiples(1, &[3, 5]))
6}
7
8#[test]
9fn one_factor_has_multiples_within_limit() {
10 assert_eq!(3, sum_of_multiples(4, &[3, 5]))
11}
12
13#[test]
14fn more_than_one_multiple_within_limit() {
15 assert_eq!(9, sum_of_multiples(7, &[3]))
16}
17
18#[test]
19fn more_than_one_factor_with_multiples_within_limit() {
20 assert_eq!(23, sum_of_multiples(10, &[3, 5]))
21}
22
23#[test]
24fn each_multiple_is_only_counted_once() {
25 assert_eq!(2318, sum_of_multiples(100, &[3, 5]))
26}
27
28#[test]
29fn a_much_larger_limit() {
30 assert_eq!(233_168, sum_of_multiples(1000, &[3, 5]))
31}
32
33#[test]
34fn three_factors() {
35 assert_eq!(51, sum_of_multiples(20, &[7, 13, 17]))
36}
37
38#[test]
39fn factors_not_relatively_prime() {
40 assert_eq!(30, sum_of_multiples(15, &[4, 6]))
41}
42
43#[test]
44fn some_pairs_of_factors_relatively_prime_and_some_not() {
45 assert_eq!(4419, sum_of_multiples(150, &[5, 6, 8]))
46}
47
48#[test]
49fn one_factor_is_a_multiple_of_another() {
50 assert_eq!(275, sum_of_multiples(51, &[5, 25]))
51}
52
53#[test]
54fn much_larger_factors() {
55 assert_eq!(2_203_160, sum_of_multiples(10_000, &[43, 47]))
56}
57
58#[test]
59fn all_numbers_are_multiples_of_1() {
60 assert_eq!(4950, sum_of_multiples(100, &[1]))
61}
62
63#[test]
64fn no_factors_means_an_empty_sum() {
65 assert_eq!(0, sum_of_multiples(10_000, &[]))
66}
67
68#[test]
69fn the_only_multiple_of_0_is_0() {
70 assert_eq!(0, sum_of_multiples(1, &[0]))
71}
72
73#[test]
74fn the_factor_0_does_not_affect_the_sum_of_multiples_of_other_factors() {
75 assert_eq!(3, sum_of_multiples(4, &[3, 0]))
76}
77
78#[test]
79fn solutions_using_include_exclude_must_extend_to_cardinality_greater_than_3() {
80 assert_eq!(39_614_537, sum_of_multiples(10_000, &[2, 3, 5, 7, 11]))
81}