diff --git a/config.json b/config.json index 57b5646d..d0e20ac9 100644 --- a/config.json +++ b/config.json @@ -857,6 +857,14 @@ "prerequisites": [], "difficulty": 4 }, + { + "slug": "food-chain", + "name": "Food Chain", + "uuid": "ba92a70f-788f-4a4c-b16c-4577d60b048e", + "practices": [], + "prerequisites": [], + "difficulty": 2 + }, { "slug": "clock", "name": "Clock", 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..a6603274 --- /dev/null +++ b/exercises/practice/food-chain/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "erikschierboom" + ], + "files": { + "solution": [ + "food-chain.R" + ], + "test": [ + "test_food-chain.R" + ], + "example": [ + ".meta/example.R" + ] + }, + "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.R b/exercises/practice/food-chain/.meta/example.R new file mode 100644 index 00000000..c50ea3de --- /dev/null +++ b/exercises/practice/food-chain/.meta/example.R @@ -0,0 +1,70 @@ +subjects <- data.frame( + Animal = c("fly", "spider", "bird", "cat", "dog", "goat", "cow", "horse"), + Phrase = c( + "", + "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!", + "" + ) +) + +recite <- function(begin_idx, end_idx) { + lapply(begin_idx:end_idx, verse) |> + lapply(FUN = \(verse) c(verse, "")) |> + unlist() |> + head(n = -1) +} + +verse <- function(number) { + c(verse_begin(number), verse_middle(number), verse_end(number)) +} + +verse_begin <- function(number) { + paste( + "I know an old lady who swallowed a ", + subjects$Animal[number], + ".", + sep = "" + ) +} + +verse_swallow <- function(swallowed, caught) { + if (caught == "spider") { + caught <- paste(caught, "that wriggled and jiggled and tickled inside her") + } + + paste( + "She swallowed the ", + swallowed, + " to catch the ", + caught, + ".", + sep = "" + ) +} + +verse_swallows <- function(number) { + swallowed_animals <- subjects$Animal[number:2] + caught_animals <- c(subjects$Animal[(number - 1):1], NA)[-number] + mapply(verse_swallow, swallowed_animals, caught_animals) |> unname() +} + +verse_middle <- function(number) { + if (number %in% c(1, 8)) { + return(c()) + } + + c(subjects$Phrase[number], verse_swallows(number)) +} + +verse_end <- function(number) { + ifelse( + number == 8, + "She's dead, of course!", + "I don't know why she swallowed the fly. Perhaps she'll die." + ) +} 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/food-chain.R b/exercises/practice/food-chain/food-chain.R new file mode 100644 index 00000000..ef163b58 --- /dev/null +++ b/exercises/practice/food-chain/food-chain.R @@ -0,0 +1,3 @@ +recite <- function(begin_idx, end_idx) { + +} diff --git a/exercises/practice/food-chain/test_food-chain.R b/exercises/practice/food-chain/test_food-chain.R new file mode 100644 index 00000000..af59805a --- /dev/null +++ b/exercises/practice/food-chain/test_food-chain.R @@ -0,0 +1,178 @@ +source("./food-chain.R") +library(testthat) + +test_that("Fly", { + expected <- + c( + "I know an old lady who swallowed a fly.", + "I don't know why she swallowed the fly. Perhaps she'll die." + ) + expect_equal(recite(1, 1), expected) +}) + +test_that("Spider", { + expected <- + c( + "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." + ) + expect_equal(recite(2, 2), expected) +}) + +test_that("Bird", { + expected <- + c( + "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.", # nolint + "She swallowed the spider to catch the fly.", + "I don't know why she swallowed the fly. Perhaps she'll die." + ) + expect_equal(recite(3, 3), expected) +}) + +test_that("Cat", { + expected <- + c( + "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.", # nolint + "She swallowed the spider to catch the fly.", + "I don't know why she swallowed the fly. Perhaps she'll die." + ) + expect_equal(recite(4, 4), expected) +}) + +test_that("Dog", { + expected <- + c( + "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.", # nolint + "She swallowed the spider to catch the fly.", + "I don't know why she swallowed the fly. Perhaps she'll die." + ) + expect_equal(recite(5, 5), expected) +}) + +test_that("Goat", { + expected <- + c( + "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.", # nolint + "She swallowed the spider to catch the fly.", + "I don't know why she swallowed the fly. Perhaps she'll die." + ) + expect_equal(recite(6, 6), expected) +}) + +test_that("Cow", { + expected <- + c( + "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.", # nolint + "She swallowed the spider to catch the fly.", + "I don't know why she swallowed the fly. Perhaps she'll die." + ) + expect_equal(recite(7, 7), expected) +}) + +test_that("Horse", { + expected <- + c( + "I know an old lady who swallowed a horse.", + "She's dead, of course!" + ) + expect_equal(recite(8, 8), expected) +}) + +test_that("Multiple verses", { + expected <- + c( + "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.", # nolint + "She swallowed the spider to catch the fly.", + "I don't know why she swallowed the fly. Perhaps she'll die." + ) + expect_equal(recite(1, 3), expected) +}) + +test_that("Full song", { + expected <- + c( + "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.", # nolint + "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.", # nolint + "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.", # nolint + "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.", # nolint + "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.", # nolint + "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!" + ) + expect_equal(recite(1, 8), expected) +}) diff --git a/exercises/practice/proverb/.meta/example.R b/exercises/practice/proverb/.meta/example.R index c9f58194..61c8b58d 100644 --- a/exercises/practice/proverb/.meta/example.R +++ b/exercises/practice/proverb/.meta/example.R @@ -10,7 +10,7 @@ recite <- function(wanted) { if (is.null(wanted)) { return(c()) } - + lines <- mapply(verse_line, wanted, c(wanted[-1], NA))[-length(wanted)] c(unname(lines), verse_ending(wanted[[1]])) }