diff --git a/config.json b/config.json index aa27da9f..2c990de2 100644 --- a/config.json +++ b/config.json @@ -777,6 +777,14 @@ "prerequisites": [], "difficulty": 3 }, + { + "slug": "strain", + "name": "Strain", + "uuid": "869fcbef-a5b3-4d79-bc30-e42eeb2fd319", + "practices": [], + "prerequisites": [], + "difficulty": 1 + }, { "slug": "proverb", "name": "Proverb", @@ -824,6 +832,22 @@ "practices": [], "prerequisites": [], "difficulty": 4 + }, + { + "slug": "binary-search", + "name": "Binary Search", + "uuid": "7b4e53cc-44c0-4be3-b036-1e08fb1ae507", + "practices": [], + "prerequisites": [], + "difficulty": 3 + }, + { + "slug": "robot-name", + "name": "Robot Name", + "uuid": "445bd3fd-011d-4a8f-aa83-5acc53225679", + "practices": [], + "prerequisites": [], + "difficulty": 4 } ] }, diff --git a/exercises/concept/annalyns-infiltration/test_annalyns-infiltration.R b/exercises/concept/annalyns-infiltration/test_annalyns-infiltration.R index 68aaa99b..d5976c5d 100644 --- a/exercises/concept/annalyns-infiltration/test_annalyns-infiltration.R +++ b/exercises/concept/annalyns-infiltration/test_annalyns-infiltration.R @@ -5,12 +5,12 @@ library(testthat) test_that("Cannot execute fast attack if knight is awake", { knight_is_awake <- TRUE - expect_equal(can_fast_attack(knight_is_awake), FALSE) + expect_false(can_fast_attack(knight_is_awake)) }) test_that("Can execute fast attack if knight is sleeping", { knight_is_awake <- FALSE - expect_equal(can_fast_attack(knight_is_awake), TRUE) + expect_true(can_fast_attack(knight_is_awake)) }) # 2) can_spy diff --git a/exercises/concept/elyses-enchantments/test_elyses-enchantments.R b/exercises/concept/elyses-enchantments/test_elyses-enchantments.R index f548df5e..412c06b4 100644 --- a/exercises/concept/elyses-enchantments/test_elyses-enchantments.R +++ b/exercises/concept/elyses-enchantments/test_elyses-enchantments.R @@ -145,65 +145,65 @@ test_that("remove the card from the bottom", { test_that("an empty stack of cards", { stack <- c() stack_size <- 0 - expect_equal(check_size_of_stack(stack, stack_size), TRUE) + expect_true(check_size_of_stack(stack, stack_size)) }) test_that("an empty stack of cards", { stack <- c() stack_size <- 1 - expect_equal(check_size_of_stack(stack, stack_size), FALSE) + expect_false(check_size_of_stack(stack, stack_size)) }) test_that("has exactly 1 card", { stack <- c(7) stack_size <- 0 - expect_equal(check_size_of_stack(stack, stack_size), FALSE) + expect_false(check_size_of_stack(stack, stack_size)) }) test_that("has exactly 1 card", { stack <- c(7) stack_size <- 1 - expect_equal(check_size_of_stack(stack, stack_size), TRUE) + expect_true(check_size_of_stack(stack, stack_size)) }) test_that("has exactly 1 card", { stack <- c(7) stack_size <- 2 - expect_equal(check_size_of_stack(stack, stack_size), FALSE) + expect_false(check_size_of_stack(stack, stack_size)) }) test_that("has exactly 4 cards", { stack <- c(2, 4, 6, 8) stack_size <- 3 - expect_equal(check_size_of_stack(stack, stack_size), FALSE) + expect_false(check_size_of_stack(stack, stack_size)) }) test_that("has exactly 4 cards", { stack <- c(2, 4, 6, 8) stack_size <- 4 - expect_equal(check_size_of_stack(stack, stack_size), TRUE) + expect_true(check_size_of_stack(stack, stack_size)) }) test_that("has exactly 4 cards", { stack <- c(2, 4, 6, 8) stack_size <- 15 - expect_equal(check_size_of_stack(stack, stack_size), FALSE) + expect_false(check_size_of_stack(stack, stack_size)) }) test_that("has exactly 5 cards", { stack <- c(1, 3, 5, 7, 9) stack_size <- 3 - expect_equal(check_size_of_stack(stack, stack_size), FALSE) + expect_false(check_size_of_stack(stack, stack_size)) }) test_that("has exactly 5 cards", { stack <- c(1, 3, 5, 7, 9) stack_size <- 4 - expect_equal(check_size_of_stack(stack, stack_size), FALSE) + expect_false(check_size_of_stack(stack, stack_size)) }) test_that("has exactly 5 cards", { stack <- c(1, 3, 5, 7, 9) stack_size <- 5 - expect_equal(check_size_of_stack(stack, stack_size), TRUE) + expect_true(check_size_of_stack(stack, stack_size)) }) diff --git a/exercises/practice/armstrong-numbers/test_armstrong-numbers.R b/exercises/practice/armstrong-numbers/test_armstrong-numbers.R index b6934c0e..9558cdab 100644 --- a/exercises/practice/armstrong-numbers/test_armstrong-numbers.R +++ b/exercises/practice/armstrong-numbers/test_armstrong-numbers.R @@ -2,37 +2,37 @@ source("./armstrong-numbers.R") library(testthat) test_that("Zero is an Armstrong number", { - expect_equal(is_armstrong_number(0), TRUE) + expect_true(is_armstrong_number(0)) }) test_that("Single-digit numbers are Armstrong numbers", { - expect_equal(is_armstrong_number(5), TRUE) + expect_true(is_armstrong_number(5)) }) test_that("There are no two-digit Armstrong numbers", { - expect_equal(is_armstrong_number(10), FALSE) + expect_false(is_armstrong_number(10)) }) test_that("Three-digit number that is an Armstrong number", { - expect_equal(is_armstrong_number(153), TRUE) + expect_true(is_armstrong_number(153)) }) test_that("Three-digit number that is not an Armstrong number", { - expect_equal(is_armstrong_number(100), FALSE) + expect_false(is_armstrong_number(100)) }) test_that("Four-digit number that is an Armstrong number", { - expect_equal(is_armstrong_number(9474), TRUE) + expect_true(is_armstrong_number(9474)) }) test_that("Four-digit number that is not an Armstrong number", { - expect_equal(is_armstrong_number(9475), FALSE) + expect_false(is_armstrong_number(9475)) }) test_that("Seven-digit number that is an Armstrong number", { - expect_equal(is_armstrong_number(9926315), TRUE) + expect_true(is_armstrong_number(9926315)) }) test_that("Seven-digit number that is not an Armstrong number", { - expect_equal(is_armstrong_number(9926314), FALSE) + expect_false(is_armstrong_number(9926314)) }) diff --git a/exercises/practice/binary-search/.docs/instructions.md b/exercises/practice/binary-search/.docs/instructions.md new file mode 100644 index 00000000..12f4358e --- /dev/null +++ b/exercises/practice/binary-search/.docs/instructions.md @@ -0,0 +1,29 @@ +# Instructions + +Your task is to implement a binary search algorithm. + +A binary search algorithm finds an item in a list by repeatedly splitting it in half, only keeping the half which contains the item we're looking for. +It allows us to quickly narrow down the possible locations of our item until we find it, or until we've eliminated all possible locations. + +~~~~exercism/caution +Binary search only works when a list has been sorted. +~~~~ + +The algorithm looks like this: + +- Find the middle element of a _sorted_ list and compare it with the item we're looking for. +- If the middle element is our item, then we're done! +- If the middle element is greater than our item, we can eliminate that element and all the elements **after** it. +- If the middle element is less than our item, we can eliminate that element and all the elements **before** it. +- If every element of the list has been eliminated then the item is not in the list. +- Otherwise, repeat the process on the part of the list that has not been eliminated. + +Here's an example: + +Let's say we're looking for the number 23 in the following sorted list: `[4, 8, 12, 16, 23, 28, 32]`. + +- We start by comparing 23 with the middle element, 16. +- Since 23 is greater than 16, we can eliminate the left half of the list, leaving us with `[23, 28, 32]`. +- We then compare 23 with the new middle element, 28. +- Since 23 is less than 28, we can eliminate the right half of the list: `[23]`. +- We've found our item. diff --git a/exercises/practice/binary-search/.docs/introduction.md b/exercises/practice/binary-search/.docs/introduction.md new file mode 100644 index 00000000..03496599 --- /dev/null +++ b/exercises/practice/binary-search/.docs/introduction.md @@ -0,0 +1,13 @@ +# Introduction + +You have stumbled upon a group of mathematicians who are also singer-songwriters. +They have written a song for each of their favorite numbers, and, as you can imagine, they have a lot of favorite numbers (like [0][zero] or [73][seventy-three] or [6174][kaprekars-constant]). + +You are curious to hear the song for your favorite number, but with so many songs to wade through, finding the right song could take a while. +Fortunately, they have organized their songs in a playlist sorted by the title — which is simply the number that the song is about. + +You realize that you can use a binary search algorithm to quickly find a song given the title. + +[zero]: https://en.wikipedia.org/wiki/0 +[seventy-three]: https://en.wikipedia.org/wiki/73_(number) +[kaprekars-constant]: https://en.wikipedia.org/wiki/6174_(number) diff --git a/exercises/practice/binary-search/.meta/config.json b/exercises/practice/binary-search/.meta/config.json new file mode 100644 index 00000000..46e7be68 --- /dev/null +++ b/exercises/practice/binary-search/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "erikschierboom" + ], + "files": { + "solution": [ + "binary-search.R" + ], + "test": [ + "test_binary-search.R" + ], + "example": [ + ".meta/example.R" + ] + }, + "blurb": "Implement a binary search algorithm.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Binary_search_algorithm" +} diff --git a/exercises/practice/binary-search/.meta/example.R b/exercises/practice/binary-search/.meta/example.R new file mode 100644 index 00000000..d494ad2d --- /dev/null +++ b/exercises/practice/binary-search/.meta/example.R @@ -0,0 +1,15 @@ +find <- function(haystack, needle) { + left <- 1 + right <- length(haystack) + + while (left <= right) { + middle_idx <- (right + left) %/% 2 + middle <- haystack[middle_idx] + + if (middle == needle) return(middle_idx) + if (middle < needle) left <- middle_idx + 1 + else right <- middle_idx - 1 + } + + -1 +} diff --git a/exercises/practice/binary-search/.meta/tests.toml b/exercises/practice/binary-search/.meta/tests.toml new file mode 100644 index 00000000..61e2b068 --- /dev/null +++ b/exercises/practice/binary-search/.meta/tests.toml @@ -0,0 +1,43 @@ +# 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. + +[b55c24a9-a98d-4379-a08c-2adcf8ebeee8] +description = "finds a value in an array with one element" + +[73469346-b0a0-4011-89bf-989e443d503d] +description = "finds a value in the middle of an array" + +[327bc482-ab85-424e-a724-fb4658e66ddb] +description = "finds a value at the beginning of an array" + +[f9f94b16-fe5e-472c-85ea-c513804c7d59] +description = "finds a value at the end of an array" + +[f0068905-26e3-4342-856d-ad153cadb338] +description = "finds a value in an array of odd length" + +[fc316b12-c8b3-4f5e-9e89-532b3389de8c] +description = "finds a value in an array of even length" + +[da7db20a-354f-49f7-a6a1-650a54998aa6] +description = "identifies that a value is not included in the array" + +[95d869ff-3daf-4c79-b622-6e805c675f97] +description = "a value smaller than the array's smallest value is not found" + +[8b24ef45-6e51-4a94-9eac-c2bf38fdb0ba] +description = "a value larger than the array's largest value is not found" + +[f439a0fa-cf42-4262-8ad1-64bf41ce566a] +description = "nothing is found in an empty array" + +[2c353967-b56d-40b8-acff-ce43115eed64] +description = "nothing is found when the left and right bounds cross" diff --git a/exercises/practice/binary-search/binary-search.R b/exercises/practice/binary-search/binary-search.R new file mode 100644 index 00000000..adb14263 --- /dev/null +++ b/exercises/practice/binary-search/binary-search.R @@ -0,0 +1,3 @@ +find <- function(haystack, needle) { + +} diff --git a/exercises/practice/binary-search/test_binary-search.R b/exercises/practice/binary-search/test_binary-search.R new file mode 100644 index 00000000..2f526306 --- /dev/null +++ b/exercises/practice/binary-search/test_binary-search.R @@ -0,0 +1,69 @@ +source("./binary-search.R") +library(testthat) + +test_that("Finds a needle in an haystack with one element", { + haystack <- c(6) + needle <- 6 + expect_equal(find(haystack, needle), 1) +}) + +test_that("Finds a needle in the middle of an haystack", { + haystack <- c(1, 3, 4, 6, 8, 9, 11) + needle <- 6 + expect_equal(find(haystack, needle), 4) +}) + +test_that("Finds a needle at the beginning of an haystack", { + haystack <- c(1, 3, 4, 6, 8, 9, 11) + needle <- 1 + expect_equal(find(haystack, needle), 1) +}) + +test_that("Finds a needle at the end of an haystack", { + haystack <- c(1, 3, 4, 6, 8, 9, 11) + needle <- 11 + expect_equal(find(haystack, needle), 7) +}) + +test_that("Finds a needle in an haystack of odd length", { + haystack <- c(1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 634) + needle <- 144 + expect_equal(find(haystack, needle), 10) +}) + +test_that("Finds a needle in an haystack of even length", { + haystack <- c(1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377) + needle <- 21 + expect_equal(find(haystack, needle), 6) +}) + +test_that("Identifies that a needle is not included in the haystack", { + haystack <- c(1, 3, 4, 6, 8, 9, 11) + needle <- 7 + expect_equal(find(haystack, needle), -1) +}) + +test_that("A needle smaller than the haystack's smallest needle is not found", { + haystack <- c(1, 3, 4, 6, 8, 9, 11) + needle <- 0 + expect_equal(find(haystack, needle), -1) +}) + +test_that("A needle larger than the haystack's largest needle is not found", { + haystack <- c(1, 3, 4, 6, 8, 9, 11) + needle <- 13 + expect_equal(find(haystack, needle), -1) +}) + +test_that("Nothing is found in an empty haystack", { + haystack <- c() + needle <- 1 + expected <- -1 + expect_equal(find(haystack, needle), -1) +}) + +test_that("Nothing is found when the left and right bounds cross", { + haystack <- c(1, 2) + needle <- 0 + expect_equal(find(haystack, needle), -1) +}) diff --git a/exercises/practice/isbn-verifier/test_isbn-verifier.R b/exercises/practice/isbn-verifier/test_isbn-verifier.R index 5481a6fc..e8b3bd06 100644 --- a/exercises/practice/isbn-verifier/test_isbn-verifier.R +++ b/exercises/practice/isbn-verifier/test_isbn-verifier.R @@ -2,78 +2,77 @@ source("./isbn-verifier.R") library(testthat) test_that("Valid isbn", { - expect_equal(is_valid("3-598-21508-8"), TRUE) + expect_true(is_valid("3-598-21508-8")) }) test_that("Invalid isbn check digit", { - expect_equal(is_valid("3-598-21508-9"), FALSE) + expect_false(is_valid("3-598-21508-9")) }) test_that("Valid isbn with a check digit of 10", { - expect_equal(is_valid("3-598-21507-X"), TRUE) + expect_true(is_valid("3-598-21507-X")) }) test_that("Check digit is a character other than X", { - expect_equal(is_valid("3-598-21507-A"), FALSE) + expect_false(is_valid("3-598-21507-A")) }) test_that("Invalid check digit in isbn is not treated as zero", { - expect_equal(is_valid("4-598-21507-B"), FALSE) + expect_false(is_valid("4-598-21507-B")) }) test_that("Invalid character in isbn is not treated as zero", { - expect_equal(is_valid("3-598-P1581-X"), FALSE) + expect_false(is_valid("3-598-P1581-X")) }) test_that("X is only valid as a check digit", { - expect_equal(is_valid("3-598-2X507-9"), FALSE) + expect_false(is_valid("3-598-2X507-9")) }) test_that("Valid isbn without separating dashes", { - expect_equal(is_valid("3598215088"), TRUE) + expect_true(is_valid("3598215088")) }) test_that("Isbn without separating dashes and X as check digit", { - expect_equal(is_valid("359821507X"), TRUE) + expect_true(is_valid("359821507X")) }) test_that("Isbn without check digit and dashes", { - expect_equal(is_valid("359821507"), FALSE) + expect_false(is_valid("359821507")) }) test_that("Too long isbn and no dashes", { - expect_equal(is_valid("3598215078X"), FALSE) + expect_false(is_valid("3598215078X")) }) test_that("Too short isbn", { - expect_equal(is_valid("00"), FALSE) + expect_false(is_valid("00")) }) test_that("Isbn without check digit", { - expect_equal(is_valid("3-598-21507"), FALSE) + expect_false(is_valid("3-598-21507")) }) test_that("Check digit of X should not be used for 0", { - expect_equal(is_valid("3-598-21515-X"), FALSE) + expect_false(is_valid("3-598-21515-X")) }) test_that("Empty isbn", { - expect_equal(is_valid(""), FALSE) + expect_false(is_valid("")) }) test_that("Input is 9 characters", { - expect_equal(is_valid("134456729"), FALSE) + expect_false(is_valid("134456729")) }) test_that("Invalid characters are not ignored after checking length", { - expect_equal(is_valid("3132P34035"), FALSE) + expect_false(is_valid("3132P34035")) }) test_that("Invalid characters are not ignored before checking length", { - expect_equal(is_valid("3598P215088"), FALSE) + expect_false(is_valid("3598P215088")) }) test_that("Input is too long but contains a valid isbn", { - expect_equal(is_valid("98245726788"), FALSE) + expect_false(is_valid("98245726788")) }) - diff --git a/exercises/practice/isogram/test_isogram.R b/exercises/practice/isogram/test_isogram.R index acc63972..c68501c7 100644 --- a/exercises/practice/isogram/test_isogram.R +++ b/exercises/practice/isogram/test_isogram.R @@ -3,40 +3,40 @@ library(testthat) test_that("empty string", { word <- "" - expect_equal(is_isogram(word), TRUE) + expect_true(is_isogram(word)) }) test_that("isogram with only lower case characters", { word <- "isogram" - expect_equal(is_isogram(word), TRUE) + expect_true(is_isogram(word)) }) test_that("word with one duplicated character", { word <- "eleven" - expect_equal(is_isogram(word), FALSE) + expect_false(is_isogram(word)) }) test_that("longest reported english isogram", { word <- "subdermatoglyphic" - expect_equal(is_isogram(word), TRUE) + expect_true(is_isogram(word)) }) test_that("word with duplicated character in mixed case", { word <- "Alphabet" - expect_equal(is_isogram(word), FALSE) + expect_false(is_isogram(word)) }) test_that("hypothetical isogrammic word with hyphen", { word <- "thumbscrew-japingly" - expect_equal(is_isogram(word), TRUE) + expect_true(is_isogram(word)) }) test_that("isogram with duplicated non letter character", { word <- "Hjelmqvist-Gryb-Zock-Pfund-Wax" - expect_equal(is_isogram(word), TRUE) + expect_true(is_isogram(word)) }) test_that("made-up name that is an isogram", { word <- "Emily Jung Schwartzkopf" - expect_equal(is_isogram(word), TRUE) + expect_true(is_isogram(word)) }) diff --git a/exercises/practice/leap/test_leap.R b/exercises/practice/leap/test_leap.R index 1fb20a43..c9a06350 100644 --- a/exercises/practice/leap/test_leap.R +++ b/exercises/practice/leap/test_leap.R @@ -3,20 +3,20 @@ library(testthat) test_that("year not divisible by 4: common year", { year <- 2015 - expect_equal(leap(year), FALSE) + expect_false(leap(year)) }) test_that("year divisible by 4, not divisible by 100: leap year", { year <- 2016 - expect_equal(leap(year), TRUE) + expect_true(leap(year)) }) test_that("year divisible by 100, not divisible by 400: common year", { year <- 2100 - expect_equal(leap(year), FALSE) + expect_false(leap(year)) }) test_that("year divisible by 400: leap year", { year <- 2000 - expect_equal(leap(year), TRUE) + expect_true(leap(year)) }) diff --git a/exercises/practice/luhn/test_luhn.R b/exercises/practice/luhn/test_luhn.R index 3f639b39..64c4bcd7 100644 --- a/exercises/practice/luhn/test_luhn.R +++ b/exercises/practice/luhn/test_luhn.R @@ -3,70 +3,70 @@ library(testthat) test_that("single digit strings can not be valid", { input <- "1" - expect_equal(is_valid(input), FALSE) + expect_false(is_valid(input)) }) test_that("A single zero is invalid", { input <- "0" - expect_equal(is_valid(input), FALSE) + expect_false(is_valid(input)) }) test_that("a simple valid SIN that remains valid if reversed", { input <- "059" - expect_equal(is_valid(input), TRUE) + expect_true(is_valid(input)) }) test_that("a simple valid SIN that becomes invalid if reversed", { input <- "59" - expect_equal(is_valid(input), TRUE) + expect_true(is_valid(input)) }) test_that("valid Canadian SIN", { input <- "046 454 286" - expect_equal(is_valid(input), TRUE) + expect_true(is_valid(input)) }) test_that("invalid Canadian SIN", { input <- "046 454 287" - expect_equal(is_valid(input), FALSE) + expect_false(is_valid(input)) }) test_that("invalid credit card", { input <- "8273 1232 7352 0569" - expect_equal(is_valid(input), FALSE) + expect_false(is_valid(input)) }) test_that("valid strings with a non-digit added become invalid", { input <- "055a 444 285" - expect_equal(is_valid(input), FALSE) + expect_false(is_valid(input)) }) test_that("punctuation is not allowed", { input <- "055-444-285" - expect_equal(is_valid(input), FALSE) + expect_false(is_valid(input)) }) test_that("symbols are not allowed", { input <- "055£ 444$ 285" - expect_equal(is_valid(input), FALSE) + expect_false(is_valid(input)) }) test_that("single zero with space is invalid", { input <- " 0" - expect_equal(is_valid(input), FALSE) + expect_false(is_valid(input)) }) test_that("more than a single zero is valid", { input <- "0000 0" - expect_equal(is_valid(input), TRUE) + expect_true(is_valid(input)) }) test_that("another valid sin", { input <- "055 444 285" - expect_equal(is_valid(input), TRUE) + expect_true(is_valid(input)) }) test_that("nine doubled is nine", { input <- "091" - expect_equal(is_valid(input), TRUE) + expect_true(is_valid(input)) }) diff --git a/exercises/practice/matching-brackets/test_matching-brackets.R b/exercises/practice/matching-brackets/test_matching-brackets.R index 1d2fdd5a..92de039c 100644 --- a/exercises/practice/matching-brackets/test_matching-brackets.R +++ b/exercises/practice/matching-brackets/test_matching-brackets.R @@ -2,83 +2,83 @@ source("./matching-brackets.R") library(testthat) test_that("Paired square brackets", { - expect_equal(is_paired("[]"), TRUE) + expect_true(is_paired("[]")) }) test_that("Empty string", { - expect_equal(is_paired(""), TRUE) + expect_true(is_paired("")) }) test_that("Unpaired brackets", { - expect_equal(is_paired("[["), FALSE) + expect_false(is_paired("[[")) }) test_that("Wrong ordered brackets", { - expect_equal(is_paired("}{"), FALSE) + expect_false(is_paired("}{")) }) test_that("Wrong closing bracket", { - expect_equal(is_paired("{]"), FALSE) + expect_false(is_paired("{]")) }) test_that("Paired with whitespace", { - expect_equal(is_paired("{ }"), TRUE) + expect_true(is_paired("{ }")) }) test_that("Partially paired brackets", { - expect_equal(is_paired("{[])"), FALSE) + expect_false(is_paired("{[])")) }) test_that("Simple nested brackets", { - expect_equal(is_paired("{[]}"), TRUE) + expect_true(is_paired("{[]}")) }) test_that("Several paired brackets", { - expect_equal(is_paired("{}[]"), TRUE) + expect_true(is_paired("{}[]")) }) test_that("Paired and nested brackets", { - expect_equal(is_paired("([{}({}[])])"), TRUE) + expect_true(is_paired("([{}({}[])])")) }) test_that("Unopened closing brackets", { - expect_equal(is_paired("{[)][]}"), FALSE) + expect_false(is_paired("{[)][]}")) }) test_that("Unpaired and nested brackets", { - expect_equal(is_paired("([{])"), FALSE) + expect_false(is_paired("([{])")) }) test_that("Paired and wrong nested brackets", { - expect_equal(is_paired("[({]})"), FALSE) + expect_false(is_paired("[({]})")) }) test_that("Paired and wrong nested brackets but innermost are correct", { - expect_equal(is_paired("[({}])"), FALSE) + expect_false(is_paired("[({}])")) }) test_that("Paired and incomplete brackets", { - expect_equal(is_paired("{}["), FALSE) + expect_false(is_paired("{}[")) }) test_that("Too many closing brackets", { - expect_equal(is_paired("[]]"), FALSE) + expect_false(is_paired("[]]")) }) test_that("Early unexpected brackets", { - expect_equal(is_paired(")()"), FALSE) + expect_false(is_paired(")()")) }) test_that("Early mismatched brackets", { - expect_equal(is_paired("{)()"), FALSE) + expect_false(is_paired("{)()")) }) test_that("Math expression", { input <- "(((185 + 223.85) * 15) - 543)/2" - expect_equal(is_paired(input), TRUE) + expect_true(is_paired(input)) }) test_that("Complex latex expression", { input <- "\\left(\\begin{array}{cc} \\frac{1}{3} & x\\ \\mathrm{e}^{x} &... x^2 \\end{array}\\right)" # nolint - expect_equal(is_paired(input), TRUE) + expect_true(is_paired(input)) }) diff --git a/exercises/practice/phone-number/test_phone-number.R b/exercises/practice/phone-number/test_phone-number.R index c32440d2..78c5102e 100644 --- a/exercises/practice/phone-number/test_phone-number.R +++ b/exercises/practice/phone-number/test_phone-number.R @@ -14,11 +14,11 @@ test_that("cleans numbers with multiple spaces", { }) test_that("invalid when 9 digits", { - expect_equal(parse_phone_number("123456789"), NULL) + expect_null(parse_phone_number("123456789")) }) test_that("invalid when 11 digits and not starting with a 1", { - expect_equal(parse_phone_number("22234567890"), NULL) + expect_null(parse_phone_number("22234567890")) }) test_that("valid when 11 digits and starting with 1", { @@ -30,46 +30,45 @@ test_that("valid when 11 digits and starting with 1 even with punctuation", { }) test_that("invalid when more than 11 digits", { - expect_equal(parse_phone_number("321234567890"), NULL) + expect_null(parse_phone_number("321234567890")) }) test_that("invalid with letters", { - expect_equal(parse_phone_number("523-abc-7890"), NULL) + expect_null(parse_phone_number("523-abc-7890")) }) test_that("invalid with punctuations", { - expect_equal(parse_phone_number("523-@:!-7890"), NULL) + expect_null(parse_phone_number("523-@:!-7890")) }) test_that("invalid if area code starts with 0", { - expect_equal(parse_phone_number("(023) 456-7890"), NULL) + expect_null(parse_phone_number("(023) 456-7890")) }) test_that("invalid if area code starts with 1", { - expect_equal(parse_phone_number("(123) 456-7890"), NULL) + expect_null(parse_phone_number("(123) 456-7890")) }) test_that("invalid if exchange code starts with 0", { - expect_equal(parse_phone_number("(223) 056-7890"), NULL) + expect_null(parse_phone_number("(223) 056-7890")) }) test_that("invalid if exchange code starts with 1", { - expect_equal(parse_phone_number("(223) 156-7890"), NULL) + expect_null(parse_phone_number("(223) 156-7890")) }) test_that("invalid if area code starts with 0 on valid 11-digit number", { - expect_equal(parse_phone_number("1 (023) 456-7890"), NULL) + expect_null(parse_phone_number("1 (023) 456-7890")) }) test_that("invalid if area code starts with 1 on valid 11-digit number", { - expect_equal(parse_phone_number("1 (123) 456-7890"), NULL) + expect_null(parse_phone_number("1 (123) 456-7890")) }) test_that("invalid if exchange code starts with 0 on valid 11-digit number", { - expect_equal(parse_phone_number("1 (223) 056-7890"), NULL) + expect_null(parse_phone_number("1 (223) 056-7890")) }) test_that("invalid if exchange code starts with 1 on valid 11-digit number", { - expect_equal(parse_phone_number("1 (223) 156-7890"), NULL) + expect_null(parse_phone_number("1 (223) 156-7890")) }) - diff --git a/exercises/practice/protein-translation/test_protein-translation.R b/exercises/practice/protein-translation/test_protein-translation.R index 04ce15fd..cd2a0e4c 100644 --- a/exercises/practice/protein-translation/test_protein-translation.R +++ b/exercises/practice/protein-translation/test_protein-translation.R @@ -1,64 +1,64 @@ -source('./protein-translation.R') +source("./protein-translation.R") library(testthat) test_that("Empty RNA sequence results in no proteins", { - expect_equal(translate(""), NULL) + expect_null(translate("")) }) test_that("Methionine RNA sequence", { - expect_equal(translate("AUG"), 'Methionine') + expect_equal(translate("AUG"), "Methionine") }) test_that("Phenylalanine RNA sequence 1", { - expect_equal(translate("UUU"), 'Phenylalanine') + expect_equal(translate("UUU"), "Phenylalanine") }) test_that("Phenylalanine RNA sequence 2", { - expect_equal(translate("UUC"), 'Phenylalanine') + expect_equal(translate("UUC"), "Phenylalanine") }) test_that("Leucine RNA sequence 1", { - expect_equal(translate("UUA"), 'Leucine') + expect_equal(translate("UUA"), "Leucine") }) test_that("Leucine RNA sequence 2", { - expect_equal(translate("UUG"), 'Leucine') + expect_equal(translate("UUG"), "Leucine") }) test_that("Serine RNA sequence 1", { - expect_equal(translate("UCU"), 'Serine') + expect_equal(translate("UCU"), "Serine") }) test_that("Serine RNA sequence 2", { - expect_equal(translate("UCC"), 'Serine') + expect_equal(translate("UCC"), "Serine") }) test_that("Serine RNA sequence 3", { - expect_equal(translate("UCA"), 'Serine') + expect_equal(translate("UCA"), "Serine") }) test_that("Serine RNA sequence 4", { - expect_equal(translate("UCG"), 'Serine') + expect_equal(translate("UCG"), "Serine") }) test_that("Tyrosine RNA sequence 1", { - expect_equal(translate("UAU"), 'Tyrosine') + expect_equal(translate("UAU"), "Tyrosine") }) test_that("Tyrosine RNA sequence 2", { - expect_equal(translate("UAC"), 'Tyrosine') + expect_equal(translate("UAC"), "Tyrosine") }) test_that("Cysteine RNA sequence 1", { - expect_equal(translate("UGU"), 'Cysteine') + expect_equal(translate("UGU"), "Cysteine") }) test_that("Cysteine RNA sequence 2", { - expect_equal(translate("UGC"), 'Cysteine') + expect_equal(translate("UGC"), "Cysteine") }) test_that("Tryptophan RNA sequence", { - expect_equal(translate("UGG"), 'Tryptophan') + expect_equal(translate("UGG"), "Tryptophan") }) test_that("STOP codon RNA sequence 1", { @@ -74,16 +74,18 @@ test_that("STOP codon RNA sequence 3", { }) test_that("Sequence of two protein codons translates into proteins", { - expect_equal(translate("UUUUUU"), c('Phenylalanine', 'Phenylalanine')) + expect_equal(translate("UUUUUU"), c("Phenylalanine", "Phenylalanine")) }) test_that("Sequence of two different protein codons translates into proteins", { - expect_equal(translate("UUAUUG"), c('Leucine', 'Leucine')) + expect_equal(translate("UUAUUG"), c("Leucine", "Leucine")) }) test_that("Translate RNA strand into correct protein list", { - expect_equal(translate("AUGUUUUGG"), - c('Methionine', 'Phenylalanine', 'Tryptophan')) + expect_equal( + translate("AUGUUUUGG"), + c("Methionine", "Phenylalanine", "Tryptophan") + ) }) test_that("Translation stops if STOP codon at beginning of sequence", { @@ -91,20 +93,22 @@ test_that("Translation stops if STOP codon at beginning of sequence", { }) test_that("Translation stops if STOP codon at end of two-codon sequence", { - expect_equal(translate("UGGUAG"), c('Tryptophan')) + expect_equal(translate("UGGUAG"), c("Tryptophan")) }) test_that("Translation stops if STOP codon at end of three-codon sequence", { - expect_equal(translate("AUGUUUUAA"), c('Methionine', 'Phenylalanine')) + expect_equal(translate("AUGUUUUAA"), c("Methionine", "Phenylalanine")) }) test_that("Translation stops if STOP codon in middle of three-codon sequence", { - expect_equal(translate("UGGUAGUGG"), c('Tryptophan')) + expect_equal(translate("UGGUAGUGG"), c("Tryptophan")) }) test_that("Translation stops if STOP codon in middle of six-codon sequence", { - expect_equal(translate("UGGUGUUAUUAAUGGUUU"), - c('Tryptophan', 'Cysteine', 'Tyrosine')) + expect_equal( + translate("UGGUGUUAUUAAUGGUUU"), + c("Tryptophan", "Cysteine", "Tyrosine") + ) }) test_that("Non-existing codon can't translate", { @@ -120,6 +124,5 @@ test_that("Incomplete RNA sequence can't translate", { }) test_that("Incomplete RNA sequence can translate if valid until a STOP codon", { - expect_equal(translate("UUCUUCUAAUGGU"), c('Phenylalanine', 'Phenylalanine')) + expect_equal(translate("UUCUUCUAAUGGU"), c("Phenylalanine", "Phenylalanine")) }) - diff --git a/exercises/practice/queen-attack/test_queen-attack.R b/exercises/practice/queen-attack/test_queen-attack.R index f1e87585..a178500a 100644 --- a/exercises/practice/queen-attack/test_queen-attack.R +++ b/exercises/practice/queen-attack/test_queen-attack.R @@ -38,43 +38,43 @@ test_that("queen must have column on board", { test_that("cannot attack", { queen1 <- create(2, 4) queen2 <- create(6, 6) - expect_equal(can_attack(queen1, queen2), FALSE) + expect_false(can_attack(queen1, queen2)) }) test_that("can attack on same row", { queen1 <- create(2, 4) queen2 <- create(2, 6) - expect_equal(can_attack(queen1, queen2), TRUE) + expect_true(can_attack(queen1, queen2)) }) test_that("can attack on same column", { queen1 <- create(4, 5) queen2 <- create(2, 5) - expect_equal(can_attack(queen1, queen2), TRUE) + expect_true(can_attack(queen1, queen2)) }) test_that("can attack on first diagonal", { queen1 <- create(2, 2) queen2 <- create(0, 4) - expect_equal(can_attack(queen1, queen2), TRUE) + expect_true(can_attack(queen1, queen2)) }) test_that("can attack on second diagonal", { queen1 <- create(2, 2) queen2 <- create(3, 1) - expect_equal(can_attack(queen1, queen2), TRUE) + expect_true(can_attack(queen1, queen2)) }) test_that("can attack on third diagonal", { queen1 <- create(2, 2) queen2 <- create(1, 1) - expect_equal(can_attack(queen1, queen2), TRUE) + expect_true(can_attack(queen1, queen2)) }) test_that("can attack on fourth diagonal", { queen1 <- create(1, 7) queen2 <- create(0, 6) - expect_equal(can_attack(queen1, queen2), TRUE) + expect_true(can_attack(queen1, queen2)) }) # cannot attack if falling diagonals are only the same when reflected @@ -82,5 +82,5 @@ test_that("can attack on fourth diagonal", { test_that("cannot attack", { queen1 <- create(4, 1) queen2 <- create(2, 5) - expect_equal(can_attack(queen1, queen2), FALSE) + expect_false(can_attack(queen1, queen2)) }) diff --git a/exercises/practice/robot-name/.docs/instructions.md b/exercises/practice/robot-name/.docs/instructions.md new file mode 100644 index 00000000..fca3a41a --- /dev/null +++ b/exercises/practice/robot-name/.docs/instructions.md @@ -0,0 +1,14 @@ +# Instructions + +Manage robot factory settings. + +When a robot comes off the factory floor, it has no name. + +The first time you turn on a robot, a random name is generated in the format of two uppercase letters followed by three digits, such as RX837 or BC811. + +Every once in a while we need to reset a robot to its factory settings, which means that its name gets wiped. +The next time you ask, that robot will respond with a new random name. + +The names must be random: they should not follow a predictable sequence. +Using random names means a risk of collisions. +Your solution must ensure that every existing robot has a unique name. diff --git a/exercises/practice/robot-name/.meta/config.json b/exercises/practice/robot-name/.meta/config.json new file mode 100644 index 00000000..0867167e --- /dev/null +++ b/exercises/practice/robot-name/.meta/config.json @@ -0,0 +1,18 @@ +{ + "authors": [ + "erikschierboom" + ], + "files": { + "solution": [ + "robot-name.R" + ], + "test": [ + "test_robot-name.R" + ], + "example": [ + ".meta/example.R" + ] + }, + "blurb": "Manage robot factory settings.", + "source": "A debugging session with Paul Blackwell at gSchool." +} diff --git a/exercises/practice/robot-name/.meta/example.R b/exercises/practice/robot-name/.meta/example.R new file mode 100644 index 00000000..2166cdcf --- /dev/null +++ b/exercises/practice/robot-name/.meta/example.R @@ -0,0 +1,20 @@ +new_robot <- function() { + structure( + list( + name = random_name() + ), + class = "robot" + ) +} + +reset_robot <- function(robot) { + robot$name <- random_name() + robot +} + +random_name <- function() { + paste0( + c(sample(LETTERS, 2, replace = TRUE), sample(0:9, 3, replace = TRUE)), + collapse = "" + ) +} diff --git a/exercises/practice/robot-name/robot-name.R b/exercises/practice/robot-name/robot-name.R new file mode 100644 index 00000000..90781377 --- /dev/null +++ b/exercises/practice/robot-name/robot-name.R @@ -0,0 +1,7 @@ +new_robot <- function() { + +} + +reset_robot <- function(robot) { + +} diff --git a/exercises/practice/robot-name/test_robot-name.R b/exercises/practice/robot-name/test_robot-name.R new file mode 100644 index 00000000..40d5dc11 --- /dev/null +++ b/exercises/practice/robot-name/test_robot-name.R @@ -0,0 +1,29 @@ +source("./robot-name.R") +library(testthat) + +test_that("Robot has a class", { + robot <- new_robot() + expect_s3_class(robot, "robot") +}) + +test_that("Robot has a name", { + robot <- new_robot() + expect_match(robot$name, "^[A-Z]{2}\\d{3}$") +}) + +test_that("Name is the same each time", { + robot <- new_robot() + expect_equal(robot$name, robot$name) +}) + +test_that("Two different robots have different names", { + robot1 <- new_robot() + robot2 <- new_robot() + expect_true(robot1$name != robot2$name) +}) + +test_that("Can reset the name", { + robot <- new_robot() + reset_robot <- reset_robot(robot) + expect_true(robot$name != reset_robot$name) +}) diff --git a/exercises/practice/simple-cipher/test_simple-cipher.R b/exercises/practice/simple-cipher/test_simple-cipher.R index cebc88bf..ce6fa443 100644 --- a/exercises/practice/simple-cipher/test_simple-cipher.R +++ b/exercises/practice/simple-cipher/test_simple-cipher.R @@ -3,7 +3,7 @@ library(testthat) test_that("Random key cipher - Key is made only of lowercase letters", { key <- generate_key() - expect_equal(all(grepl("^[a-z]+$", key)), TRUE) + expect_match(key, "^[a-z]+$") }) test_that("Random key cipher - Can encode", { diff --git a/exercises/practice/strain/.docs/instructions.md b/exercises/practice/strain/.docs/instructions.md new file mode 100644 index 00000000..3469ae65 --- /dev/null +++ b/exercises/practice/strain/.docs/instructions.md @@ -0,0 +1,29 @@ +# Instructions + +Implement the `keep` and `discard` operation on collections. +Given a collection and a predicate on the collection's elements, `keep` returns a new collection containing those elements where the predicate is true, while `discard` returns a new collection containing those elements where the predicate is false. + +For example, given the collection of numbers: + +- 1, 2, 3, 4, 5 + +And the predicate: + +- is the number even? + +Then your keep operation should produce: + +- 2, 4 + +While your discard operation should produce: + +- 1, 3, 5 + +Note that the union of keep and discard is all the elements. + +The functions may be called `keep` and `discard`, or they may need different names in order to not clash with existing functions or concepts in your language. + +## Restrictions + +Keep your hands off that filter/reject/whatchamacallit functionality provided by your standard library! +Solve this one yourself using other basic tools instead. diff --git a/exercises/practice/strain/.meta/config.json b/exercises/practice/strain/.meta/config.json new file mode 100644 index 00000000..985de8c8 --- /dev/null +++ b/exercises/practice/strain/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "erikschierboom" + ], + "files": { + "solution": [ + "strain.R" + ], + "test": [ + "test_strain.R" + ], + "example": [ + ".meta/example.R" + ] + }, + "blurb": "Implement the `keep` and `discard` operation on collections.", + "source": "Conversation with James Edward Gray II", + "source_url": "http://graysoftinc.com/" +} diff --git a/exercises/practice/strain/.meta/example.R b/exercises/practice/strain/.meta/example.R new file mode 100644 index 00000000..27f668e1 --- /dev/null +++ b/exercises/practice/strain/.meta/example.R @@ -0,0 +1,17 @@ +keep <- function(input, fun) { + if (is.null(input)) return(c()) + + kept <- vector(mode = mode(input)) + + for (element in input) { + if (fun(element)) { + kept[[length(kept) + 1]] <- element + } + } + + kept +} + +discard <- function(input, fun) { + keep(input, Negate(fun)) +} diff --git a/exercises/practice/strain/.meta/tests.toml b/exercises/practice/strain/.meta/tests.toml new file mode 100644 index 00000000..3a617b4a --- /dev/null +++ b/exercises/practice/strain/.meta/tests.toml @@ -0,0 +1,52 @@ +# 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. + +[26af8c32-ba6a-4eb3-aa0a-ebd8f136e003] +description = "keep on empty list returns empty list" + +[f535cb4d-e99b-472a-bd52-9fa0ffccf454] +description = "keeps everything" + +[950b8e8e-f628-42a8-85e2-9b30f09cde38] +description = "keeps nothing" + +[92694259-6e76-470c-af87-156bdf75018a] +description = "keeps first and last" + +[938f7867-bfc7-449e-a21b-7b00cbb56994] +description = "keeps neither first nor last" + +[8908e351-4437-4d2b-a0f7-770811e48816] +description = "keeps strings" + +[2728036b-102a-4f1e-a3ef-eac6160d876a] +description = "keeps lists" + +[ef16beb9-8d84-451a-996a-14e80607fce6] +description = "discard on empty list returns empty list" + +[2f42f9bc-8e06-4afe-a222-051b5d8cd12a] +description = "discards everything" + +[ca990fdd-08c2-4f95-aa50-e0f5e1d6802b] +description = "discards nothing" + +[71595dae-d283-48ca-a52b-45fa96819d2f] +description = "discards first and last" + +[ae141f79-f86d-4567-b407-919eaca0f3dd] +description = "discards neither first nor last" + +[daf25b36-a59f-4f29-bcfe-302eb4e43609] +description = "discards strings" + +[a38d03f9-95ad-4459-80d1-48e937e4acaf] +description = "discards lists" diff --git a/exercises/practice/strain/strain.R b/exercises/practice/strain/strain.R new file mode 100644 index 00000000..ff2c967b --- /dev/null +++ b/exercises/practice/strain/strain.R @@ -0,0 +1,7 @@ +keep <- function(input, fun) { + +} + +discard <- function(input, fun) { + +} diff --git a/exercises/practice/strain/test_strain.R b/exercises/practice/strain/test_strain.R new file mode 100644 index 00000000..b581f595 --- /dev/null +++ b/exercises/practice/strain/test_strain.R @@ -0,0 +1,90 @@ +source("./strain.R") +library(testthat) + +test_that("Empty keep", { + input <- c() + expected <- c() + expect_equal(keep(input, \(x) x < 10), expected) +}) + +test_that("Keep everything", { + input <- c(1, 2, 3) + expected <- c(1, 2, 3) + expect_equal(keep(input, \(x) x < 10), expected) +}) + +test_that("Keep first and last", { + input <- c(1, 2, 3) + expected <- c(1, 3) + expect_equal(keep(input, \(x) x %% 2 != 0), expected) +}) + +test_that("Keep neither first nor last", { + input <- c(1, 2, 3, 4, 5) + expected <- c(2, 4) + expect_equal(keep(input, \(x) x %% 2 == 0), expected) +}) + +test_that("Keep strings", { + input <- c("apple", "zebra", "banana", "zombies", "cherimoya", "zelot") + expected <- c("zebra", "zombies", "zelot") + expect_equal(keep(input, \(x) substr(x, 1, 1) == "z"), expected) +}) + +test_that("Keep list of vectors", { + input <- list( + c(1, 2, 3), + c(5, 5, 5), + c(5, 1, 2), + c(2, 1, 2), + c(1, 5, 2), + c(2, 2, 1), + c(1, 2, 5) + ) + expected <- list(c(5, 5, 5), c(5, 1, 2), c(1, 5, 2), c(1, 2, 5)) + expect_equal(keep(input, \(x) 5 %in% x), expected) +}) + +test_that("Empty discard", { + input <- c() + expected <- c() + expect_equal(discard(input, \(x) x < 10), expected) +}) + +test_that("Discard nothing", { + input <- c(1, 2, 3) + expected <- c(1, 2, 3) + expect_equal(discard(input, \(x) x > 10), expected) +}) + +test_that("Discard first and last", { + input <- c(1, 2, 3) + expected <- c(2) + expect_equal(discard(input, \(x) x %% 2 != 0), expected) +}) + +test_that("Discard neither first nor last", { + input <- c(1, 2, 3, 4, 5) + expected <- c(1, 3, 5) + expect_equal(discard(input, \(x) x %% 2 == 0), expected) +}) + +test_that("Discard strings", { + input <- c("apple", "zebra", "banana", "zombies", "cherimoya", "zelot") + expected <- c("apple", "banana", "cherimoya") + expect_equal(discard(input, \(x) substr(x, 1, 1) == "z"), expected) +}) + +test_that("Discard list of vectors", { + input <- list( + c(1, 2, 3), + c(5, 5, 5), + c(5, 1, 2), + c(2, 1, 2), + c(1, 5, 2), + c(2, 2, 1), + c(1, 2, 5) + ) + expected <- list(c(1, 2, 3), c(2, 1, 2), c(2, 2, 1)) + expect_equal(discard(input, \(x) 5 %in% x), expected) +}) diff --git a/exercises/practice/vehicle-purchase/test_vehicle-purchase.R b/exercises/practice/vehicle-purchase/test_vehicle-purchase.R index 3c37f5f4..a14eda06 100644 --- a/exercises/practice/vehicle-purchase/test_vehicle-purchase.R +++ b/exercises/practice/vehicle-purchase/test_vehicle-purchase.R @@ -4,23 +4,23 @@ library(testthat) # needs_license test_that("requires a license for a car", { - expect_equal(needs_license("car"), TRUE) + expect_true(needs_license("car")) }) test_that("requires a license for a truck", { - expect_equal(needs_license("truck"), TRUE) + expect_true(needs_license("truck")) }) test_that("requires a license for a bike", { - expect_equal(needs_license("bike"), FALSE) + expect_false(needs_license("bike")) }) test_that("requires a license for a stroller", { - expect_equal(needs_license("stroller"), FALSE) + expect_false(needs_license("stroller")) }) test_that("requires a license for an e-scooter", { - expect_equal(needs_license("e-scooter"), FALSE) + expect_false(needs_license("e-scooter")) }) # choose_vehicle