diff --git a/config.json b/config.json index 6c03c900..d8542afd 100644 --- a/config.json +++ b/config.json @@ -785,6 +785,14 @@ "prerequisites": [], "difficulty": 2 }, + { + "slug": "zebra-puzzle", + "name": "Zebra Puzzle", + "uuid": "59e952d7-81bb-4f43-9fba-bdd7322befd0", + "practices": [], + "prerequisites": [], + "difficulty": 8 + }, { "slug": "twelve-days", "name": "Twelve Days", diff --git a/exercises/practice/zebra-puzzle/.docs/instructions.md b/exercises/practice/zebra-puzzle/.docs/instructions.md new file mode 100644 index 00000000..aedce9b2 --- /dev/null +++ b/exercises/practice/zebra-puzzle/.docs/instructions.md @@ -0,0 +1,32 @@ +# Instructions + +Your task is to solve the Zebra Puzzle to find the answer to these two questions: + +- Which of the residents drinks water? +- Who owns the zebra? + +## Puzzle + +The following 15 statements are all known to be true: + +1. There are five houses. +2. The Englishman lives in the red house. +3. The Spaniard owns the dog. +4. The person in the green house drinks coffee. +5. The Ukrainian drinks tea. +6. The green house is immediately to the right of the ivory house. +7. The snail owner likes to go dancing. +8. The person in the yellow house is a painter. +9. The person in the middle house drinks milk. +10. The Norwegian lives in the first house. +11. The person who enjoys reading lives in the house next to the person with the fox. +12. The painter's house is next to the house with the horse. +13. The person who plays football drinks orange juice. +14. The Japanese person plays chess. +15. The Norwegian lives next to the blue house. + +Additionally, each of the five houses is painted a different color, and their inhabitants are of different national extractions, own different pets, drink different beverages and engage in different hobbies. + +~~~~exercism/note +There are 24 billion (5!⁵ = 24,883,200,000) possible solutions, so try ruling out as many solutions as possible. +~~~~ diff --git a/exercises/practice/zebra-puzzle/.docs/introduction.md b/exercises/practice/zebra-puzzle/.docs/introduction.md new file mode 100644 index 00000000..bbcaa6fd --- /dev/null +++ b/exercises/practice/zebra-puzzle/.docs/introduction.md @@ -0,0 +1,15 @@ +# Introduction + +The Zebra Puzzle is a famous logic puzzle in which there are five houses, each painted a different color. +The houses have different inhabitants, who have different nationalities, own different pets, drink different beverages and enjoy different hobbies. + +To help you solve the puzzle, you're given 15 statements describing the solution. +However, only by combining the information in _all_ statements will you be able to find the solution to the puzzle. + +~~~~exercism/note +The Zebra Puzzle is a [Constraint satisfaction problem (CSP)][constraint-satisfaction-problem]. +In such a problem, you have a set of possible values and a set of constraints that limit which values are valid. +Another well-known CSP is Sudoku. + +[constraint-satisfaction-problem]: https://en.wikipedia.org/wiki/Constraint_satisfaction_problem +~~~~ diff --git a/exercises/practice/zebra-puzzle/.meta/config.json b/exercises/practice/zebra-puzzle/.meta/config.json new file mode 100644 index 00000000..84e5a1a2 --- /dev/null +++ b/exercises/practice/zebra-puzzle/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "erikschierboom" + ], + "files": { + "solution": [ + "zebra-puzzle.R" + ], + "test": [ + "test_zebra-puzzle.R" + ], + "example": [ + ".meta/example.R" + ] + }, + "blurb": "Solve the zebra puzzle.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Zebra_Puzzle" +} diff --git a/exercises/practice/zebra-puzzle/.meta/example.R b/exercises/practice/zebra-puzzle/.meta/example.R new file mode 100644 index 00000000..34725da1 --- /dev/null +++ b/exercises/practice/zebra-puzzle/.meta/example.R @@ -0,0 +1,73 @@ +colors <- c("Red", "Green", "Ivory", "Yellow", "Blue") +nationalities <- c("Englishman", "Spaniard", "Ukrainian", "Japanese", "Norwegian") # nolint +pets <- c("Dog", "Snails", "Fox", "Horse", "Zebra") +drinks <- c("Coffee", "Tea", "Milk", "OrangeJuice", "Water") +hobbies <- c("Dancing", "Painting", "Reading", "Football", "Chess") + +drinks_water <- function() { + solution <- solve() + solution$Nation[match("Water", solution$Drink)] +} + +owns_zebra <- function() { + solution <- solve() + solution$Nation[match("Zebra", solution$Pet)] +} + +solve <- function() { # nolint + for (nation in permute(nationalities)) { + if (nation[1] != "Norwegian") next + + for (color in permute(colors)) { + if (match("Englishman", nation) != match("Red", color)) next + if (abs(match("Norwegian", nation) - match("Blue", color)) != 1) next + if ((match("Ivory", color) + 1) != match("Green", color)) next + + for (hobby in permute(hobbies)) { + if (match("Painting", hobby) != match("Yellow", color)) next + if (match("Chess", hobby) != match("Japanese", nation)) next + + for (pet in permute(pets)) { + if (abs(match("Reading", hobby) - match("Fox", pet)) != 1) next + if (abs(match("Painting", hobby) - match("Horse", pet)) != 1) next + if (match("Spaniard", nation) != match("Dog", pet)) next + if (match("Dancing", hobby) != match("Snails", pet)) next + + for (drink in permute(drinks)) { + if (drink[3] != "Milk") next + if (match("Ukrainian", nation) != match("Tea", drink)) next + if (match("Green", color) != match("Coffee", drink)) next + if (match("Football", hobby) != match("OrangeJuice", drink)) next + + return( + data.frame( + Nation = nation, + Color = color, + hobby = hobby, + Pet = pet, + Drink = drink + ) + ) + } + } + } + } + } + + stop("Could not find solution") +} + +permute <- function(x) { + if (length(x) == 1) { + return(list(x)) + } + + result <- list() + for (i in seq_along(x)) { + sub_perms <- permute(x[-i]) + for (sub_perm in sub_perms) { + result <- append(result, list(c(x[i], sub_perm))) + } + } + return(result) +} diff --git a/exercises/practice/zebra-puzzle/.meta/tests.toml b/exercises/practice/zebra-puzzle/.meta/tests.toml new file mode 100644 index 00000000..56c21c7a --- /dev/null +++ b/exercises/practice/zebra-puzzle/.meta/tests.toml @@ -0,0 +1,16 @@ +# 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. + +[16efb4e4-8ad7-4d5e-ba96-e5537b66fd42] +description = "resident who drinks water" + +[084d5b8b-24e2-40e6-b008-c800da8cd257] +description = "resident who owns zebra" diff --git a/exercises/practice/zebra-puzzle/test_zebra-puzzle.R b/exercises/practice/zebra-puzzle/test_zebra-puzzle.R new file mode 100644 index 00000000..adcaab26 --- /dev/null +++ b/exercises/practice/zebra-puzzle/test_zebra-puzzle.R @@ -0,0 +1,10 @@ +source("./zebra-puzzle.R") +library(testthat) + +test_that("Resident who drinks water", { + expect_equal(drinks_water(), "Norwegian") +}) + +test_that("Resident who owns zebra", { + expect_equal(owns_zebra(), "Japanese") +}) diff --git a/exercises/practice/zebra-puzzle/zebra-puzzle.R b/exercises/practice/zebra-puzzle/zebra-puzzle.R new file mode 100644 index 00000000..72cd1bca --- /dev/null +++ b/exercises/practice/zebra-puzzle/zebra-puzzle.R @@ -0,0 +1,7 @@ +drinks_water <- function() { + +} + +owns_zebra <- function() { + +}