aboutsummaryrefslogtreecommitdiff
path: root/beer-song
diff options
context:
space:
mode:
authorFederico I <git@federicoigne.com>2020-03-17 00:53:30 +0000
committerFederico Igne <git@federicoigne.com>2021-11-03 18:54:45 +0000
commitac194ed95d6b97eef6dd60f8a3524f63fa408553 (patch)
treea7e5ae82dc02475ff711cd5e39ae1e4817276624 /beer-song
parenta4b6e4b2e898b7efa0b44b490bd731557b0cc41b (diff)
downloadexercism-ac194ed95d6b97eef6dd60f8a3524f63fa408553.tar.gz
exercism-ac194ed95d6b97eef6dd60f8a3524f63fa408553.zip
[rust] Beer Song
Diffstat (limited to 'beer-song')
-rw-r--r--beer-song/.exercism/metadata.json1
-rw-r--r--beer-song/.gitignore8
-rw-r--r--beer-song/Cargo.toml7
-rw-r--r--beer-song/README.md401
-rw-r--r--beer-song/src/intersperse.rs52
-rw-r--r--beer-song/src/lib.rs20
-rw-r--r--beer-song/tests/beer-song.rs31
7 files changed, 520 insertions, 0 deletions
diff --git a/beer-song/.exercism/metadata.json b/beer-song/.exercism/metadata.json
new file mode 100644
index 0000000..640fbbc
--- /dev/null
+++ b/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/beer-song/.gitignore b/beer-song/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/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/beer-song/Cargo.toml b/beer-song/Cargo.toml
new file mode 100644
index 0000000..ff6683e
--- /dev/null
+++ b/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/beer-song/README.md b/beer-song/README.md
new file mode 100644
index 0000000..2ed305c
--- /dev/null
+++ b/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/beer-song/src/intersperse.rs b/beer-song/src/intersperse.rs
new file mode 100644
index 0000000..51580e6
--- /dev/null
+++ b/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/beer-song/src/lib.rs b/beer-song/src/lib.rs
new file mode 100644
index 0000000..990fbbf
--- /dev/null
+++ b/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/beer-song/tests/beer-song.rs b/beer-song/tests/beer-song.rs
new file mode 100644
index 0000000..2f2ad11
--- /dev/null
+++ b/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}