diff --git a/rust/bottle-song/.exercism/config.json b/rust/bottle-song/.exercism/config.json new file mode 100644 index 0000000..a0b30d5 --- /dev/null +++ b/rust/bottle-song/.exercism/config.json @@ -0,0 +1,20 @@ +{ + "authors": [ + "ellnix" + ], + "files": { + "solution": [ + "src/lib.rs", + "Cargo.toml" + ], + "test": [ + "tests/bottle_song.rs" + ], + "example": [ + ".meta/example.rs" + ] + }, + "blurb": "Produce the lyrics to the popular children's repetitive song: Ten Green Bottles.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Ten_Green_Bottles" +} diff --git a/rust/bottle-song/.gitignore b/rust/bottle-song/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/rust/bottle-song/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/rust/bottle-song/Cargo.toml b/rust/bottle-song/Cargo.toml new file mode 100644 index 0000000..a133c66 --- /dev/null +++ b/rust/bottle-song/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "bottle_song" +version = "0.1.0" +edition = "2024" + +# Not all libraries from crates.io are available in Exercism's test runner. +# The full list of available libraries is here: +# https://github.com/exercism/rust-test-runner/blob/main/local-registry/Cargo.toml +[dependencies] diff --git a/rust/bottle-song/HELP.md b/rust/bottle-song/HELP.md new file mode 100644 index 0000000..22a6c00 --- /dev/null +++ b/rust/bottle-song/HELP.md @@ -0,0 +1,89 @@ +# Help + +## Running the tests + +Execute the tests with: + +```bash +$ cargo test +``` + +All but the first test have been ignored. After you get the first test to +pass, open the tests source file which is located in the `tests` directory +and remove the `#[ignore]` flag from the next test and get the tests to pass +again. Each separate test is a function with `#[test]` flag above it. +Continue, until you pass every test. + +If you wish to run _only ignored_ tests without editing the tests source file, use: + +```bash +$ cargo test -- --ignored +``` + +If you are using Rust 1.51 or later, you can run _all_ tests with + +```bash +$ cargo test -- --include-ignored +``` + +To run a specific test, for example `some_test`, you can use: + +```bash +$ cargo test some_test +``` + +If the specific test is ignored, use: + +```bash +$ cargo test some_test -- --ignored +``` + +To learn more about Rust tests refer to the online [test documentation][rust-tests]. + +[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html + +## Submitting your solution + +You can submit your solution using the `exercism submit src/lib.rs Cargo.toml` command. +This command will upload your solution to the Exercism website and print the solution page's URL. + +It's possible to submit an incomplete solution which allows you to: + +- See how others have completed the exercise +- Request help from a mentor + +## Need to get help? + +If you'd like help solving the exercise, check the following pages: + +- The [Rust track's documentation](https://exercism.org/docs/tracks/rust) +- The [Rust track's programming category on the forum](https://forum.exercism.org/c/programming/rust) +- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5) +- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs) + +Should those resources not suffice, you could submit your (incomplete) solution to request mentoring. + +## Rust Installation + +Refer to the [exercism help page][help-page] for Rust installation and learning +resources. + +## Submitting the solution + +Generally you should submit all files in which you implemented your solution (`src/lib.rs` in most cases). If you are using any external crates, please consider submitting the `Cargo.toml` file. This will make the review process faster and clearer. + +## Feedback, Issues, Pull Requests + +Head to [the forum](https://forum.exercism.org/c/programming/rust/) and create a post to provide feedback about an exercise or if you want to help implement new exercises. +Members of the rust track team are happy to help! + +The GitHub [track repository][github] is the home for all of the Rust exercises. + +If you want to know more about Exercism, take a look at the [contribution guide]. + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. + +[help-page]: https://exercism.org/tracks/rust/learning +[github]: https://github.com/exercism/rust +[contribution guide]: https://exercism.org/docs/community/contributors \ No newline at end of file diff --git a/rust/bottle-song/README.md b/rust/bottle-song/README.md new file mode 100644 index 0000000..4099644 --- /dev/null +++ b/rust/bottle-song/README.md @@ -0,0 +1,72 @@ +# Bottle Song + +Welcome to Bottle Song on Exercism's Rust Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Instructions + +Recite the lyrics to that popular children's repetitive song: Ten Green Bottles. + +Note that not all verses are identical. + +```text +Ten green bottles hanging on the wall, +Ten green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be nine green bottles hanging on the wall. + +Nine green bottles hanging on the wall, +Nine green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be eight green bottles hanging on the wall. + +Eight green bottles hanging on the wall, +Eight green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be seven green bottles hanging on the wall. + +Seven green bottles hanging on the wall, +Seven green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be six green bottles hanging on the wall. + +Six green bottles hanging on the wall, +Six green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be five green bottles hanging on the wall. + +Five green bottles hanging on the wall, +Five green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be four green bottles hanging on the wall. + +Four green bottles hanging on the wall, +Four green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be three green bottles hanging on the wall. + +Three green bottles hanging on the wall, +Three green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be two green bottles hanging on the wall. + +Two green bottles hanging on the wall, +Two green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be one green bottle hanging on the wall. + +One green bottle hanging on the wall, +One green bottle hanging on the wall, +And if one green bottle should accidentally fall, +There'll be no green bottles hanging on the wall. +``` + +## Source + +### Created by + +- @ellnix + +### Based on + +Wikipedia - https://en.wikipedia.org/wiki/Ten_Green_Bottles \ No newline at end of file diff --git a/rust/bottle-song/src/lib.rs b/rust/bottle-song/src/lib.rs new file mode 100644 index 0000000..9bf7a95 --- /dev/null +++ b/rust/bottle-song/src/lib.rs @@ -0,0 +1,34 @@ +pub fn recite(start_bottles: u32, take_down: u32) -> String { + let end_bottles = start_bottles - take_down; + + ((end_bottles + 1)..=start_bottles) + .rev() + .map(|n| verse(n)) + .collect::>() + .join("\n\n") +} + +fn verse(n: u32) -> String { + let current_bottle = bottle_str(n); + let next_bottle = bottle_str(n - 1).to_lowercase(); + + format!( + "{0} hanging on the wall,\n\ + {0} hanging on the wall,\n\ + And if one green bottle should accidentally fall,\n\ + There'll be {1} hanging on the wall.", + current_bottle, next_bottle + ) +} + +fn bottle_str(n: u32) -> String { + let count_str = match n { + 10 => "Ten", 9 => "Nine", 8 => "Eight", 7 => "Seven", 6 => "Six", + 5 => "Five", 4 => "Four", 3 => "Three", 2 => "Two", 1 => "One", + _ => "No", + }; + + let plural = if n == 1 { "bottle" } else { "bottles" }; + + format!("{count_str} green {plural}") +} diff --git a/rust/bottle-song/tests/bottle_song.rs b/rust/bottle-song/tests/bottle_song.rs new file mode 100644 index 0000000..3027523 --- /dev/null +++ b/rust/bottle-song/tests/bottle_song.rs @@ -0,0 +1,152 @@ +use bottle_song::*; + +#[test] +fn first_generic_verse() { + assert_eq!( + recite(10, 1).trim(), + concat!( + "Ten green bottles hanging on the wall,\n", + "Ten green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be nine green bottles hanging on the wall.", + ) + ); +} + +#[test] +fn last_generic_verse() { + assert_eq!( + recite(3, 1).trim(), + concat!( + "Three green bottles hanging on the wall,\n", + "Three green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be two green bottles hanging on the wall.", + ) + ); +} + +#[test] +fn verse_with_2_bottles() { + assert_eq!( + recite(2, 1).trim(), + concat!( + "Two green bottles hanging on the wall,\n", + "Two green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be one green bottle hanging on the wall.", + ) + ); +} + +#[test] +fn verse_with_1_bottle() { + assert_eq!( + recite(1, 1).trim(), + concat!( + "One green bottle hanging on the wall,\n", + "One green bottle hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be no green bottles hanging on the wall.", + ) + ); +} + +#[test] +fn first_two_verses() { + assert_eq!( + recite(10, 2).trim(), + concat!( + "Ten green bottles hanging on the wall,\n", + "Ten green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be nine green bottles hanging on the wall.\n", + "\n", + "Nine green bottles hanging on the wall,\n", + "Nine green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be eight green bottles hanging on the wall.", + ) + ); +} + +#[test] +fn last_three_verses() { + assert_eq!( + recite(3, 3).trim(), + concat!( + "Three green bottles hanging on the wall,\n", + "Three green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be two green bottles hanging on the wall.\n", + "\n", + "Two green bottles hanging on the wall,\n", + "Two green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be one green bottle hanging on the wall.\n", + "\n", + "One green bottle hanging on the wall,\n", + "One green bottle hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be no green bottles hanging on the wall.", + ) + ); +} + +#[test] +fn all_verses() { + assert_eq!( + recite(10, 10).trim(), + concat!( + "Ten green bottles hanging on the wall,\n", + "Ten green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be nine green bottles hanging on the wall.\n", + "\n", + "Nine green bottles hanging on the wall,\n", + "Nine green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be eight green bottles hanging on the wall.\n", + "\n", + "Eight green bottles hanging on the wall,\n", + "Eight green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be seven green bottles hanging on the wall.\n", + "\n", + "Seven green bottles hanging on the wall,\n", + "Seven green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be six green bottles hanging on the wall.\n", + "\n", + "Six green bottles hanging on the wall,\n", + "Six green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be five green bottles hanging on the wall.\n", + "\n", + "Five green bottles hanging on the wall,\n", + "Five green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be four green bottles hanging on the wall.\n", + "\n", + "Four green bottles hanging on the wall,\n", + "Four green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be three green bottles hanging on the wall.\n", + "\n", + "Three green bottles hanging on the wall,\n", + "Three green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be two green bottles hanging on the wall.\n", + "\n", + "Two green bottles hanging on the wall,\n", + "Two green bottles hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be one green bottle hanging on the wall.\n", + "\n", + "One green bottle hanging on the wall,\n", + "One green bottle hanging on the wall,\n", + "And if one green bottle should accidentally fall,\n", + "There'll be no green bottles hanging on the wall.", + ) + ); +}