From 8be1ec30338bd06ad722fc43759c7e581ebea09b Mon Sep 17 00:00:00 2001 From: Erik Schierboom <erik_schierboom@hotmail.com> Date: Sat, 18 Jan 2025 19:01:57 +0100 Subject: [PATCH] Add `food-chain` exercise --- config.json | 12 ++ .../practice/food-chain/.docs/instructions.md | 64 ++++++++ .../practice/food-chain/.meta/config.json | 19 +++ .../practice/food-chain/.meta/example.clj | 50 ++++++ .../practice/food-chain/.meta/generator.tpl | 12 ++ .../practice/food-chain/.meta/tests.toml | 40 +++++ exercises/practice/food-chain/deps.edn | 6 + exercises/practice/food-chain/project.clj | 4 + .../practice/food-chain/src/food_chain.clj | 7 + .../food-chain/test/food_chain_test.clj | 150 ++++++++++++++++++ 10 files changed, 364 insertions(+) create mode 100644 exercises/practice/food-chain/.docs/instructions.md create mode 100644 exercises/practice/food-chain/.meta/config.json create mode 100644 exercises/practice/food-chain/.meta/example.clj create mode 100644 exercises/practice/food-chain/.meta/generator.tpl create mode 100644 exercises/practice/food-chain/.meta/tests.toml create mode 100644 exercises/practice/food-chain/deps.edn create mode 100644 exercises/practice/food-chain/project.clj create mode 100644 exercises/practice/food-chain/src/food_chain.clj create mode 100644 exercises/practice/food-chain/test/food_chain_test.clj diff --git a/config.json b/config.json index b109f13e6..86e782de4 100644 --- a/config.json +++ b/config.json @@ -1253,6 +1253,18 @@ "time" ] }, + { + "slug": "food-chain", + "name": "Food Chain", + "uuid": "188f12ad-e6ed-40d4-b515-d2b4d49cbb69", + "practices": [], + "prerequisites": [ + "strings", + "conditionals", + "vectors" + ], + "difficulty": 5 + }, { "slug": "list-ops", "name": "List Ops", diff --git a/exercises/practice/food-chain/.docs/instructions.md b/exercises/practice/food-chain/.docs/instructions.md new file mode 100644 index 000000000..125820e32 --- /dev/null +++ b/exercises/practice/food-chain/.docs/instructions.md @@ -0,0 +1,64 @@ +# Instructions + +Generate the lyrics of the song 'I Know an Old Lady Who Swallowed a Fly'. + +While you could copy/paste the lyrics, or read them from a file, this problem is much more interesting if you approach it algorithmically. + +This is a [cumulative song][cumulative-song] of unknown origin. + +This is one of many common variants. + +```text +I know an old lady who swallowed a fly. +I don't know why she swallowed the fly. Perhaps she'll die. + +I know an old lady who swallowed a spider. +It wriggled and jiggled and tickled inside her. +She swallowed the spider to catch the fly. +I don't know why she swallowed the fly. Perhaps she'll die. + +I know an old lady who swallowed a bird. +How absurd to swallow a bird! +She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her. +She swallowed the spider to catch the fly. +I don't know why she swallowed the fly. Perhaps she'll die. + +I know an old lady who swallowed a cat. +Imagine that, to swallow a cat! +She swallowed the cat to catch the bird. +She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her. +She swallowed the spider to catch the fly. +I don't know why she swallowed the fly. Perhaps she'll die. + +I know an old lady who swallowed a dog. +What a hog, to swallow a dog! +She swallowed the dog to catch the cat. +She swallowed the cat to catch the bird. +She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her. +She swallowed the spider to catch the fly. +I don't know why she swallowed the fly. Perhaps she'll die. + +I know an old lady who swallowed a goat. +Just opened her throat and swallowed a goat! +She swallowed the goat to catch the dog. +She swallowed the dog to catch the cat. +She swallowed the cat to catch the bird. +She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her. +She swallowed the spider to catch the fly. +I don't know why she swallowed the fly. Perhaps she'll die. + +I know an old lady who swallowed a cow. +I don't know how she swallowed a cow! +She swallowed the cow to catch the goat. +She swallowed the goat to catch the dog. +She swallowed the dog to catch the cat. +She swallowed the cat to catch the bird. +She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her. +She swallowed the spider to catch the fly. +I don't know why she swallowed the fly. Perhaps she'll die. + +I know an old lady who swallowed a horse. +She's dead, of course! +``` + +[cumulative-song]: https://en.wikipedia.org/wiki/Cumulative_song diff --git a/exercises/practice/food-chain/.meta/config.json b/exercises/practice/food-chain/.meta/config.json new file mode 100644 index 000000000..c53956222 --- /dev/null +++ b/exercises/practice/food-chain/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "erikschierboom" + ], + "files": { + "solution": [ + "src/food_chain.clj" + ], + "test": [ + "test/food_chain_test.clj" + ], + "example": [ + ".meta/example.clj" + ] + }, + "blurb": "Generate the lyrics of the song 'I Know an Old Lady Who Swallowed a Fly'.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/There_Was_an_Old_Lady_Who_Swallowed_a_Fly" +} diff --git a/exercises/practice/food-chain/.meta/example.clj b/exercises/practice/food-chain/.meta/example.clj new file mode 100644 index 000000000..9d1e8c94c --- /dev/null +++ b/exercises/practice/food-chain/.meta/example.clj @@ -0,0 +1,50 @@ +(ns food-chain + (:require [clojure.string :as str])) + +(def animals ["fly" "spider" "bird" "cat" "dog" "goat" "cow" "horse"]) + +(def phrases [nil + "It wriggled and jiggled and tickled inside her." + "How absurd to swallow a bird!" + "Imagine that, to swallow a cat!" + "What a hog, to swallow a dog!" + "Just opened her throat and swallowed a goat!" + "I don't know how she swallowed a cow!" + nil]) + +(defn verse-begin [n] + (let [first (str "I know an old lady who swallowed a " (get animals n) ".") + second (get phrases n)] + (remove nil? [first second]))) + +(defn verse-caught [caught] + (if (= "spider" caught) + (str caught " that wriggled and jiggled and tickled inside her") + caught)) + +(defn verse-swallow [[swallowed caught]] + (str "She swallowed the " swallowed " to catch the " (verse-caught caught) ".")) + +(defn verse-swallows [n] + (mapv verse-swallow (partition 2 1 (reverse (take (inc n) animals))))) + +(defn verse-middle [n] + (if (< 0 n 7) + (verse-swallows n) + [])) + +(defn verse-end [n] + (if (< n 7) + "I don't know why she swallowed the fly. Perhaps she'll die." + "She's dead, of course!")) + +(defn verse [n] + (->> (cons (verse-begin n) (conj (verse-middle n) (verse-end n))) + (flatten) + (str/join "\n"))) + +(defn recite [start-verse end-verse] + (->> (range (dec start-verse) end-verse) + (map verse) + (interpose "") + (str/join "\n"))) diff --git a/exercises/practice/food-chain/.meta/generator.tpl b/exercises/practice/food-chain/.meta/generator.tpl new file mode 100644 index 000000000..610414ac6 --- /dev/null +++ b/exercises/practice/food-chain/.meta/generator.tpl @@ -0,0 +1,12 @@ +(ns food-chain-test + (:require [clojure.test :refer [deftest testing is]] + [clojure.string :as str] + food-chain)) + +{{#test_cases.recite}} +(deftest recite_test_{{idx}} + (testing {{description}} + (is (= (str/join "\n" [{{#expected~}}{{.}}{{#if @last}}]){{else}} + {{/if}}{{/expected}} + (food-chain/recite {{input.startVerse}} {{input.endVerse}}))))) +{{/test_cases.recite}} diff --git a/exercises/practice/food-chain/.meta/tests.toml b/exercises/practice/food-chain/.meta/tests.toml new file mode 100644 index 000000000..30c5b980b --- /dev/null +++ b/exercises/practice/food-chain/.meta/tests.toml @@ -0,0 +1,40 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[751dce68-9412-496e-b6e8-855998c56166] +description = "fly" + +[6c56f861-0c5e-4907-9a9d-b2efae389379] +description = "spider" + +[3edf5f33-bef1-4e39-ae67-ca5eb79203fa] +description = "bird" + +[e866a758-e1ff-400e-9f35-f27f28cc288f] +description = "cat" + +[3f02c30e-496b-4b2a-8491-bc7e2953cafb] +description = "dog" + +[4b3fd221-01ea-46e0-825b-5734634fbc59] +description = "goat" + +[1b707da9-7001-4fac-941f-22ad9c7a65d4] +description = "cow" + +[3cb10d46-ae4e-4d2c-9296-83c9ffc04cdc] +description = "horse" + +[22b863d5-17e4-4d1e-93e4-617329a5c050] +description = "multiple verses" + +[e626b32b-745c-4101-bcbd-3b13456893db] +description = "full song" diff --git a/exercises/practice/food-chain/deps.edn b/exercises/practice/food-chain/deps.edn new file mode 100644 index 000000000..561c3e2da --- /dev/null +++ b/exercises/practice/food-chain/deps.edn @@ -0,0 +1,6 @@ +{:aliases {:test {:extra-paths ["test"] + :extra-deps {io.github.cognitect-labs/test-runner + {:git/url "https://github.com/cognitect-labs/test-runner.git" + :sha "705ad25bbf0228b1c38d0244a36001c2987d7337"}} + :main-opts ["-m" "cognitect.test-runner"] + :exec-fn cognitect.test-runner.api/test}}} \ No newline at end of file diff --git a/exercises/practice/food-chain/project.clj b/exercises/practice/food-chain/project.clj new file mode 100644 index 000000000..ab6f9b02f --- /dev/null +++ b/exercises/practice/food-chain/project.clj @@ -0,0 +1,4 @@ +(defproject food-chain "0.1.0-SNAPSHOT" + :description "food-chain exercise." + :url "https://github.com/exercism/clojure/tree/main/exercises/practice/food-chain" + :dependencies [[org.clojure/clojure "1.11.1"]]) diff --git a/exercises/practice/food-chain/src/food_chain.clj b/exercises/practice/food-chain/src/food_chain.clj new file mode 100644 index 000000000..6cee30796 --- /dev/null +++ b/exercises/practice/food-chain/src/food_chain.clj @@ -0,0 +1,7 @@ +(ns food-chain) + +(defn recite + "Returns the lyrics of the song: 'I Know an Old Lady Who Swallowed a Fly.'" + [start-verse end-verse] + ;; function body + ) diff --git a/exercises/practice/food-chain/test/food_chain_test.clj b/exercises/practice/food-chain/test/food_chain_test.clj new file mode 100644 index 000000000..33224150a --- /dev/null +++ b/exercises/practice/food-chain/test/food_chain_test.clj @@ -0,0 +1,150 @@ +(ns food-chain-test + (:require [clojure.test :refer [deftest testing is]] + [clojure.string :as str] + food-chain)) + +(deftest recite_test_1 + (testing "fly" + (is (= (str/join "\n" ["I know an old lady who swallowed a fly." + "I don't know why she swallowed the fly. Perhaps she'll die."]) + (food-chain/recite 1 1))))) + +(deftest recite_test_2 + (testing "spider" + (is (= (str/join "\n" ["I know an old lady who swallowed a spider." + "It wriggled and jiggled and tickled inside her." + "She swallowed the spider to catch the fly." + "I don't know why she swallowed the fly. Perhaps she'll die."]) + (food-chain/recite 2 2))))) + +(deftest recite_test_3 + (testing "bird" + (is (= (str/join "\n" ["I know an old lady who swallowed a bird." + "How absurd to swallow a bird!" + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her." + "She swallowed the spider to catch the fly." + "I don't know why she swallowed the fly. Perhaps she'll die."]) + (food-chain/recite 3 3))))) + +(deftest recite_test_4 + (testing "cat" + (is (= (str/join "\n" ["I know an old lady who swallowed a cat." + "Imagine that, to swallow a cat!" + "She swallowed the cat to catch the bird." + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her." + "She swallowed the spider to catch the fly." + "I don't know why she swallowed the fly. Perhaps she'll die."]) + (food-chain/recite 4 4))))) + +(deftest recite_test_5 + (testing "dog" + (is (= (str/join "\n" ["I know an old lady who swallowed a dog." + "What a hog, to swallow a dog!" + "She swallowed the dog to catch the cat." + "She swallowed the cat to catch the bird." + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her." + "She swallowed the spider to catch the fly." + "I don't know why she swallowed the fly. Perhaps she'll die."]) + (food-chain/recite 5 5))))) + +(deftest recite_test_6 + (testing "goat" + (is (= (str/join "\n" ["I know an old lady who swallowed a goat." + "Just opened her throat and swallowed a goat!" + "She swallowed the goat to catch the dog." + "She swallowed the dog to catch the cat." + "She swallowed the cat to catch the bird." + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her." + "She swallowed the spider to catch the fly." + "I don't know why she swallowed the fly. Perhaps she'll die."]) + (food-chain/recite 6 6))))) + +(deftest recite_test_7 + (testing "cow" + (is (= (str/join "\n" ["I know an old lady who swallowed a cow." + "I don't know how she swallowed a cow!" + "She swallowed the cow to catch the goat." + "She swallowed the goat to catch the dog." + "She swallowed the dog to catch the cat." + "She swallowed the cat to catch the bird." + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her." + "She swallowed the spider to catch the fly." + "I don't know why she swallowed the fly. Perhaps she'll die."]) + (food-chain/recite 7 7))))) + +(deftest recite_test_8 + (testing "horse" + (is (= (str/join "\n" ["I know an old lady who swallowed a horse." + "She's dead, of course!"]) + (food-chain/recite 8 8))))) + +(deftest recite_test_9 + (testing "multiple verses" + (is (= (str/join "\n" ["I know an old lady who swallowed a fly." + "I don't know why she swallowed the fly. Perhaps she'll die." + "" + "I know an old lady who swallowed a spider." + "It wriggled and jiggled and tickled inside her." + "She swallowed the spider to catch the fly." + "I don't know why she swallowed the fly. Perhaps she'll die." + "" + "I know an old lady who swallowed a bird." + "How absurd to swallow a bird!" + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her." + "She swallowed the spider to catch the fly." + "I don't know why she swallowed the fly. Perhaps she'll die."]) + (food-chain/recite 1 3))))) + +(deftest recite_test_10 + (testing "full song" + (is (= (str/join "\n" ["I know an old lady who swallowed a fly." + "I don't know why she swallowed the fly. Perhaps she'll die." + "" + "I know an old lady who swallowed a spider." + "It wriggled and jiggled and tickled inside her." + "She swallowed the spider to catch the fly." + "I don't know why she swallowed the fly. Perhaps she'll die." + "" + "I know an old lady who swallowed a bird." + "How absurd to swallow a bird!" + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her." + "She swallowed the spider to catch the fly." + "I don't know why she swallowed the fly. Perhaps she'll die." + "" + "I know an old lady who swallowed a cat." + "Imagine that, to swallow a cat!" + "She swallowed the cat to catch the bird." + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her." + "She swallowed the spider to catch the fly." + "I don't know why she swallowed the fly. Perhaps she'll die." + "" + "I know an old lady who swallowed a dog." + "What a hog, to swallow a dog!" + "She swallowed the dog to catch the cat." + "She swallowed the cat to catch the bird." + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her." + "She swallowed the spider to catch the fly." + "I don't know why she swallowed the fly. Perhaps she'll die." + "" + "I know an old lady who swallowed a goat." + "Just opened her throat and swallowed a goat!" + "She swallowed the goat to catch the dog." + "She swallowed the dog to catch the cat." + "She swallowed the cat to catch the bird." + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her." + "She swallowed the spider to catch the fly." + "I don't know why she swallowed the fly. Perhaps she'll die." + "" + "I know an old lady who swallowed a cow." + "I don't know how she swallowed a cow!" + "She swallowed the cow to catch the goat." + "She swallowed the goat to catch the dog." + "She swallowed the dog to catch the cat." + "She swallowed the cat to catch the bird." + "She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her." + "She swallowed the spider to catch the fly." + "I don't know why she swallowed the fly. Perhaps she'll die." + "" + "I know an old lady who swallowed a horse." + "She's dead, of course!"]) + (food-chain/recite 1 8)))))