From 4f34d7ef90c82af2091c28118fb519481b4ecea9 Mon Sep 17 00:00:00 2001 From: Tomas Norre Mikkelsen Date: Fri, 23 Feb 2024 17:45:22 +0100 Subject: [PATCH 1/4] Add Food Chain Exercise --- config.json | 8 + .../practice/food-chain/.docs/instructions.md | 64 +++++ .../practice/food-chain/.meta/config.json | 17 ++ .../practice/food-chain/.meta/example.php | 62 +++++ .../practice/food-chain/.meta/tests.toml | 40 ++++ exercises/practice/food-chain/FoodChain.php | 43 ++++ .../practice/food-chain/FoodChainTest.php | 225 ++++++++++++++++++ 7 files changed, 459 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.php create mode 100644 exercises/practice/food-chain/.meta/tests.toml create mode 100644 exercises/practice/food-chain/FoodChain.php create mode 100644 exercises/practice/food-chain/FoodChainTest.php diff --git a/config.json b/config.json index 9bd0ab9b..f0369b48 100644 --- a/config.json +++ b/config.json @@ -1188,6 +1188,14 @@ "prerequisites": [], "difficulty": 6 }, + { + "slug": "food-chain", + "name": "Food Chain", + "uuid": "9fa82e62-1dd3-45c4-ae33-6c854a7b92b5", + "practices": [], + "prerequisites": [], + "difficulty": 4 + }, { "slug": "kindergarten-garden", "name": "Kindergarten Garden", diff --git a/exercises/practice/food-chain/.docs/instructions.md b/exercises/practice/food-chain/.docs/instructions.md new file mode 100644 index 00000000..125820e3 --- /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 00000000..804fae1d --- /dev/null +++ b/exercises/practice/food-chain/.meta/config.json @@ -0,0 +1,17 @@ +{ + "authors": [], + "files": { + "solution": [ + "FoodChain.php" + ], + "test": [ + "FoodChainTest.php" + ], + "example": [ + ".meta/example.php" + ] + }, + "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.php b/exercises/practice/food-chain/.meta/example.php new file mode 100644 index 00000000..2be2fbcd --- /dev/null +++ b/exercises/practice/food-chain/.meta/example.php @@ -0,0 +1,62 @@ + 1; $verseNumber--) { + $text = sprintf( + "She swallowed the %s to catch the %s%s", + self::$verse[$verseNumber][0], + self::$verse[$verseNumber - 1][0], + $verseNumber !== 3 ? "." : "" + ); + if ($verseNumber === 3) { + $text .= " that wriggled and jiggled and tickled inside her."; + } + $result[] = $text; + } + $result[] = self::$verse[$verseNumber][1]; + return $result; + } + + public static function verses(int $start, int $end): array + { + if ($start < 1 || $start > $end || $end > 8) { + return self::verse(0); + } + $s = self::verse($start); + while ($start < $end) { + $start++; + $s[] = ""; + $s = array_merge($s, self::verse($start)); + } + return $s; + } + + public static function song(): array + { + return self::verses(1, 8); + } +} diff --git a/exercises/practice/food-chain/.meta/tests.toml b/exercises/practice/food-chain/.meta/tests.toml new file mode 100644 index 00000000..30c5b980 --- /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/FoodChain.php b/exercises/practice/food-chain/FoodChain.php new file mode 100644 index 00000000..45345cfe --- /dev/null +++ b/exercises/practice/food-chain/FoodChain.php @@ -0,0 +1,43 @@ +. + * + * To disable strict typing, comment out the directive below. + */ + +declare(strict_types=1); + +class FoodChain +{ + public static function verse(int $verseNumber): array + { + throw new \BadMethodCallException(sprintf('Implement the %s method', __FUNCTION__)); + } + + public static function verses(int $start, int $end): array + { + throw new \BadMethodCallException(sprintf('Implement the %s method', __FUNCTION__)); + } + + public static function song(): array + { + throw new \BadMethodCallException(sprintf('Implement the %s method', __FUNCTION__)); + } +} diff --git a/exercises/practice/food-chain/FoodChainTest.php b/exercises/practice/food-chain/FoodChainTest.php new file mode 100644 index 00000000..38de7dba --- /dev/null +++ b/exercises/practice/food-chain/FoodChainTest.php @@ -0,0 +1,225 @@ +foodChain = new FoodChain(); + } + + /** + * uuid: 751dce68-9412-496e-b6e8-855998c56166 + */ + public function testFly(): void + { + $expected = [ + "I know an old lady who swallowed a fly.", + "I don't know why she swallowed the fly. Perhaps she'll die." + ]; + $this->assertEquals($expected, $this->foodChain->verse(1)); + } + + /** + * uuid: 6c56f861-0c5e-4907-9a9d-b2efae389379 + */ + public function testSpider(): void + { + $expected = [ + "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." + ]; + $this->assertEquals($expected, $this->foodChain->verse(2)); + } + + /** + * uuid: 3edf5f33-bef1-4e39-ae67-ca5eb79203fa + */ + public function testBird(): void + { + $expected = [ + "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." + ]; + $this->assertEquals($expected, $this->foodChain->verse(3)); + } + + /** + * uuid: e866a758-e1ff-400e-9f35-f27f28cc288f + */ + public function testCat(): void + { + $expected = [ + "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." + ]; + $this->assertEquals($expected, $this->foodChain->verse(4)); + } + + /** + * uuid: 3f02c30e-496b-4b2a-8491-bc7e2953cafb + */ + public function testDog(): void + { + $expected = [ + "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." + ]; + $this->assertEquals($expected, $this->foodChain->verse(5)); + } + + /** + * uuid: 4b3fd221-01ea-46e0-825b-5734634fbc59 + */ + public function testGoat(): void + { + $expected = [ + "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." + ]; + $this->assertEquals($expected, $this->foodChain->verse(6)); + } + + /** + * uuid: 1b707da9-7001-4fac-941f-22ad9c7a65d4 + */ + public function testCow(): void + { + $expected = [ + "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." + ]; + $this->assertEquals($expected, $this->foodChain->verse(7)); + } + + /** + * uuid: 3cb10d46-ae4e-4d2c-9296-83c9ffc04cdc + */ + public function testHorse(): void + { + $expected = [ + "I know an old lady who swallowed a horse.", + "She's dead, of course!" + ]; + $this->assertEquals($expected, $this->foodChain->verse(8)); + } + + /** + * uuid: 22b863d5-17e4-4d1e-93e4-617329a5c050 + */ + public function testMultipleVerses(): void + { + $expected = [ + "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." + ]; + $this->assertEquals($expected, $this->foodChain->verses(1, 3)); + } + /** + * uuid: e626b32b-745c-4101-bcbd-3b13456893db + */ + public function testFullSong(): void + { + $expected = [ + "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!" + ]; + $this->assertEquals($expected, $this->foodChain->song()); + } +} From d40d80ea6f96b3b2bfa7f95cd4b057f5f5ceea6d Mon Sep 17 00:00:00 2001 From: Tomas Norre Mikkelsen Date: Fri, 23 Feb 2024 17:48:06 +0100 Subject: [PATCH 2/4] Add author to config.json --- exercises/practice/food-chain/.meta/config.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/exercises/practice/food-chain/.meta/config.json b/exercises/practice/food-chain/.meta/config.json index 804fae1d..a740eb34 100644 --- a/exercises/practice/food-chain/.meta/config.json +++ b/exercises/practice/food-chain/.meta/config.json @@ -1,5 +1,7 @@ { - "authors": [], + "authors": [ + "tomasnorre" + ], "files": { "solution": [ "FoodChain.php" From 32c7f62f3f801e2714e8d1b34e20036d40b1bb4b Mon Sep 17 00:00:00 2001 From: Tomas Norre Mikkelsen Date: Fri, 23 Feb 2024 19:05:58 +0100 Subject: [PATCH 3/4] Update after iteration 1 --- .../practice/food-chain/.meta/example.php | 24 +++++++++---------- exercises/practice/food-chain/FoodChain.php | 6 ++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/exercises/practice/food-chain/.meta/example.php b/exercises/practice/food-chain/.meta/example.php index 2be2fbcd..dd39ba58 100644 --- a/exercises/practice/food-chain/.meta/example.php +++ b/exercises/practice/food-chain/.meta/example.php @@ -4,7 +4,7 @@ class FoodChain { - private static array $verse = [ + private const VERSE = [ ["", ""], ["fly", "I don't know why she swallowed the fly. Perhaps she'll die."], ["spider", "It wriggled and jiggled and tickled inside her."], @@ -16,20 +16,20 @@ class FoodChain ["horse", "She's dead, of course!"], ]; - public static function verse(int $verseNumber): array + public function verse(int $verseNumber): array { $result = []; - $result[] = sprintf("I know an old lady who swallowed a %s.", self::$verse[$verseNumber][0]); - $result[] = self::$verse[$verseNumber][1]; + $result[] = sprintf("I know an old lady who swallowed a %s.", self::VERSE[$verseNumber][0]); + $result[] = self::VERSE[$verseNumber][1]; if ($verseNumber === 1 || $verseNumber === 8) { return $result; } for (; $verseNumber > 1; $verseNumber--) { $text = sprintf( "She swallowed the %s to catch the %s%s", - self::$verse[$verseNumber][0], - self::$verse[$verseNumber - 1][0], + self::VERSE[$verseNumber][0], + self::VERSE[$verseNumber - 1][0], $verseNumber !== 3 ? "." : "" ); if ($verseNumber === 3) { @@ -37,26 +37,26 @@ public static function verse(int $verseNumber): array } $result[] = $text; } - $result[] = self::$verse[$verseNumber][1]; + $result[] = self::VERSE[$verseNumber][1]; return $result; } - public static function verses(int $start, int $end): array + public function verses(int $start, int $end): array { if ($start < 1 || $start > $end || $end > 8) { - return self::verse(0); + return $this->verse(0); } $s = self::verse($start); while ($start < $end) { $start++; $s[] = ""; - $s = array_merge($s, self::verse($start)); + $s = array_merge($s, $this->verse($start)); } return $s; } - public static function song(): array + public function song(): array { - return self::verses(1, 8); + return $this->verses(1, 8); } } diff --git a/exercises/practice/food-chain/FoodChain.php b/exercises/practice/food-chain/FoodChain.php index 45345cfe..8cd60bae 100644 --- a/exercises/practice/food-chain/FoodChain.php +++ b/exercises/practice/food-chain/FoodChain.php @@ -26,17 +26,17 @@ class FoodChain { - public static function verse(int $verseNumber): array + public function verse(int $verseNumber): array { throw new \BadMethodCallException(sprintf('Implement the %s method', __FUNCTION__)); } - public static function verses(int $start, int $end): array + public function verses(int $start, int $end): array { throw new \BadMethodCallException(sprintf('Implement the %s method', __FUNCTION__)); } - public static function song(): array + public function song(): array { throw new \BadMethodCallException(sprintf('Implement the %s method', __FUNCTION__)); } From 15623fc9a0c233bc733146137fa0efb196e6c92b Mon Sep 17 00:00:00 2001 From: Tomas Norre Mikkelsen Date: Fri, 23 Feb 2024 20:04:53 +0100 Subject: [PATCH 4/4] Update after iteration 2 --- exercises/practice/food-chain/.meta/example.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/practice/food-chain/.meta/example.php b/exercises/practice/food-chain/.meta/example.php index dd39ba58..ecace289 100644 --- a/exercises/practice/food-chain/.meta/example.php +++ b/exercises/practice/food-chain/.meta/example.php @@ -44,9 +44,9 @@ public function verse(int $verseNumber): array public function verses(int $start, int $end): array { if ($start < 1 || $start > $end || $end > 8) { - return $this->verse(0); + return $this->verse(1); } - $s = self::verse($start); + $s = $this->verse($start); while ($start < $end) { $start++; $s[] = "";