diff --git a/config.json b/config.json index 79b8f029..701b9283 100644 --- a/config.json +++ b/config.json @@ -243,7 +243,7 @@ "uuid": "169de5ae-6d7d-4ba3-bfb7-2ad75b17db93", "practices": [], "prerequisites": [], - "difficulty": 2, + "difficulty": 4, "topics": [ "arrays", "strings" diff --git a/exercises/practice/allergies/.meta/tests.toml b/exercises/practice/allergies/.meta/tests.toml index 8a754c20..799ab856 100644 --- a/exercises/practice/allergies/.meta/tests.toml +++ b/exercises/practice/allergies/.meta/tests.toml @@ -1,150 +1,160 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [17fc7296-2440-4ac4-ad7b-d07c321bc5a0] -description = "not allergic to anything" +description = "testing for eggs allergy -> not allergic to anything" [07ced27b-1da5-4c2e-8ae2-cb2791437546] -description = "allergic only to eggs" +description = "testing for eggs allergy -> allergic only to eggs" [5035b954-b6fa-4b9b-a487-dae69d8c5f96] -description = "allergic to eggs and something else" +description = "testing for eggs allergy -> allergic to eggs and something else" [64a6a83a-5723-4b5b-a896-663307403310] -description = "allergic to something, but not eggs" +description = "testing for eggs allergy -> allergic to something, but not eggs" [90c8f484-456b-41c4-82ba-2d08d93231c6] -description = "allergic to everything" +description = "testing for eggs allergy -> allergic to everything" [d266a59a-fccc-413b-ac53-d57cb1f0db9d] -description = "not allergic to anything" +description = "testing for peanuts allergy -> not allergic to anything" [ea210a98-860d-46b2-a5bf-50d8995b3f2a] -description = "allergic only to peanuts" +description = "testing for peanuts allergy -> allergic only to peanuts" [eac69ae9-8d14-4291-ac4b-7fd2c73d3a5b] -description = "allergic to peanuts and something else" +description = "testing for peanuts allergy -> allergic to peanuts and something else" [9152058c-ce39-4b16-9b1d-283ec6d25085] -description = "allergic to something, but not peanuts" +description = "testing for peanuts allergy -> allergic to something, but not peanuts" [d2d71fd8-63d5-40f9-a627-fbdaf88caeab] -description = "allergic to everything" +description = "testing for peanuts allergy -> allergic to everything" [b948b0a1-cbf7-4b28-a244-73ff56687c80] -description = "not allergic to anything" +description = "testing for shellfish allergy -> not allergic to anything" [9ce9a6f3-53e9-4923-85e0-73019047c567] -description = "allergic only to shellfish" +description = "testing for shellfish allergy -> allergic only to shellfish" [b272fca5-57ba-4b00-bd0c-43a737ab2131] -description = "allergic to shellfish and something else" +description = "testing for shellfish allergy -> allergic to shellfish and something else" [21ef8e17-c227-494e-8e78-470a1c59c3d8] -description = "allergic to something, but not shellfish" +description = "testing for shellfish allergy -> allergic to something, but not shellfish" [cc789c19-2b5e-4c67-b146-625dc8cfa34e] -description = "allergic to everything" +description = "testing for shellfish allergy -> allergic to everything" [651bde0a-2a74-46c4-ab55-02a0906ca2f5] -description = "not allergic to anything" +description = "testing for strawberries allergy -> not allergic to anything" [b649a750-9703-4f5f-b7f7-91da2c160ece] -description = "allergic only to strawberries" +description = "testing for strawberries allergy -> allergic only to strawberries" [50f5f8f3-3bac-47e6-8dba-2d94470a4bc6] -description = "allergic to strawberries and something else" +description = "testing for strawberries allergy -> allergic to strawberries and something else" [23dd6952-88c9-48d7-a7d5-5d0343deb18d] -description = "allergic to something, but not strawberries" +description = "testing for strawberries allergy -> allergic to something, but not strawberries" [74afaae2-13b6-43a2-837a-286cd42e7d7e] -description = "allergic to everything" +description = "testing for strawberries allergy -> allergic to everything" [c49a91ef-6252-415e-907e-a9d26ef61723] -description = "not allergic to anything" +description = "testing for tomatoes allergy -> not allergic to anything" [b69c5131-b7d0-41ad-a32c-e1b2cc632df8] -description = "allergic only to tomatoes" +description = "testing for tomatoes allergy -> allergic only to tomatoes" [1ca50eb1-f042-4ccf-9050-341521b929ec] -description = "allergic to tomatoes and something else" +description = "testing for tomatoes allergy -> allergic to tomatoes and something else" [e9846baa-456b-4eff-8025-034b9f77bd8e] -description = "allergic to something, but not tomatoes" +description = "testing for tomatoes allergy -> allergic to something, but not tomatoes" [b2414f01-f3ad-4965-8391-e65f54dad35f] -description = "allergic to everything" +description = "testing for tomatoes allergy -> allergic to everything" [978467ab-bda4-49f7-b004-1d011ead947c] -description = "not allergic to anything" +description = "testing for chocolate allergy -> not allergic to anything" [59cf4e49-06ea-4139-a2c1-d7aad28f8cbc] -description = "allergic only to chocolate" +description = "testing for chocolate allergy -> allergic only to chocolate" [b0a7c07b-2db7-4f73-a180-565e07040ef1] -description = "allergic to chocolate and something else" +description = "testing for chocolate allergy -> allergic to chocolate and something else" [f5506893-f1ae-482a-b516-7532ba5ca9d2] -description = "allergic to something, but not chocolate" +description = "testing for chocolate allergy -> allergic to something, but not chocolate" [02debb3d-d7e2-4376-a26b-3c974b6595c6] -description = "allergic to everything" +description = "testing for chocolate allergy -> allergic to everything" [17f4a42b-c91e-41b8-8a76-4797886c2d96] -description = "not allergic to anything" +description = "testing for pollen allergy -> not allergic to anything" [7696eba7-1837-4488-882a-14b7b4e3e399] -description = "allergic only to pollen" +description = "testing for pollen allergy -> allergic only to pollen" [9a49aec5-fa1f-405d-889e-4dfc420db2b6] -description = "allergic to pollen and something else" +description = "testing for pollen allergy -> allergic to pollen and something else" [3cb8e79f-d108-4712-b620-aa146b1954a9] -description = "allergic to something, but not pollen" +description = "testing for pollen allergy -> allergic to something, but not pollen" [1dc3fe57-7c68-4043-9d51-5457128744b2] -description = "allergic to everything" +description = "testing for pollen allergy -> allergic to everything" [d3f523d6-3d50-419b-a222-d4dfd62ce314] -description = "not allergic to anything" +description = "testing for cats allergy -> not allergic to anything" [eba541c3-c886-42d3-baef-c048cb7fcd8f] -description = "allergic only to cats" +description = "testing for cats allergy -> allergic only to cats" [ba718376-26e0-40b7-bbbe-060287637ea5] -description = "allergic to cats and something else" +description = "testing for cats allergy -> allergic to cats and something else" [3c6dbf4a-5277-436f-8b88-15a206f2d6c4] -description = "allergic to something, but not cats" +description = "testing for cats allergy -> allergic to something, but not cats" [1faabb05-2b98-4995-9046-d83e4a48a7c1] -description = "allergic to everything" +description = "testing for cats allergy -> allergic to everything" [f9c1b8e7-7dc5-4887-aa93-cebdcc29dd8f] -description = "no allergies" +description = "list when: -> no allergies" [9e1a4364-09a6-4d94-990f-541a94a4c1e8] -description = "just eggs" +description = "list when: -> just eggs" [8851c973-805e-4283-9e01-d0c0da0e4695] -description = "just peanuts" +description = "list when: -> just peanuts" [2c8943cb-005e-435f-ae11-3e8fb558ea98] -description = "just strawberries" +description = "list when: -> just strawberries" [6fa95d26-044c-48a9-8a7b-9ee46ec32c5c] -description = "eggs and peanuts" +description = "list when: -> eggs and peanuts" [19890e22-f63f-4c5c-a9fb-fb6eacddfe8e] -description = "more than eggs but not peanuts" +description = "list when: -> more than eggs but not peanuts" [4b68f470-067c-44e4-889f-c9fe28917d2f] -description = "lots of stuff" +description = "list when: -> lots of stuff" [0881b7c5-9efa-4530-91bd-68370d054bc7] -description = "everything" +description = "list when: -> everything" [12ce86de-b347-42a0-ab7c-2e0570f0c65b] -description = "no allergen score parts" +description = "list when: -> no allergen score parts" + +[93c2df3e-4f55-4fed-8116-7513092819cd] +description = "list when: -> no allergen score parts without highest valid score" diff --git a/exercises/practice/allergies/src/test/groovy/AllergiesSpec.groovy b/exercises/practice/allergies/src/test/groovy/AllergiesSpec.groovy index 96e69b71..58305ea6 100644 --- a/exercises/practice/allergies/src/test/groovy/AllergiesSpec.groovy +++ b/exercises/practice/allergies/src/test/groovy/AllergiesSpec.groovy @@ -251,4 +251,14 @@ class AllergiesSpec extends Specification { 'cats'] } -} \ No newline at end of file + @Ignore + def "No allergen score parts without highest valid score"() { + given: + int score = 257 + def allergies = new Allergies(score) + + expect: + allergies.list() == ['eggs'] + } + +} diff --git a/exercises/practice/anagram/.meta/tests.toml b/exercises/practice/anagram/.meta/tests.toml index 7fb93f71..4d905627 100644 --- a/exercises/practice/anagram/.meta/tests.toml +++ b/exercises/practice/anagram/.meta/tests.toml @@ -1,12 +1,24 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [dd40c4d2-3c8b-44e5-992a-f42b393ec373] description = "no matches" [b3cca662-f50a-489e-ae10-ab8290a09bdc] description = "detects two anagrams" +include = false + +[03eb9bbe-8906-4ea0-84fa-ffe711b52c8b] +description = "detects two anagrams" +reimplements = "b3cca662-f50a-489e-ae10-ab8290a09bdc" [a27558ee-9ba0-4552-96b1-ecf665b06556] description = "does not detect anagram subsets" @@ -34,12 +46,41 @@ description = "detects anagrams using case-insensitive possible matches" [7cc195ad-e3c7-44ee-9fd2-d3c344806a2c] description = "does not detect an anagram if the original word is repeated" +include = false + +[630abb71-a94e-4715-8395-179ec1df9f91] +description = "does not detect an anagram if the original word is repeated" +reimplements = "7cc195ad-e3c7-44ee-9fd2-d3c344806a2c" [9878a1c9-d6ea-4235-ae51-3ea2befd6842] description = "anagrams must use all letters exactly once" [85757361-4535-45fd-ac0e-3810d40debc1] description = "words are not anagrams of themselves (case-insensitive)" +include = false + +[68934ed0-010b-4ef9-857a-20c9012d1ebf] +description = "words are not anagrams of themselves" +reimplements = "85757361-4535-45fd-ac0e-3810d40debc1" + +[589384f3-4c8a-4e7d-9edc-51c3e5f0c90e] +description = "words are not anagrams of themselves even if letter case is partially different" +reimplements = "85757361-4535-45fd-ac0e-3810d40debc1" + +[ba53e423-7e02-41ee-9ae2-71f91e6d18e6] +description = "words are not anagrams of themselves even if letter case is completely different" +reimplements = "85757361-4535-45fd-ac0e-3810d40debc1" [a0705568-628c-4b55-9798-82e4acde51ca] description = "words other than themselves can be anagrams" +include = false + +[33d3f67e-fbb9-49d3-a90e-0beb00861da7] +description = "words other than themselves can be anagrams" +reimplements = "a0705568-628c-4b55-9798-82e4acde51ca" + +[a6854f66-eec1-4afd-a137-62ef2870c051] +description = "handles case of greek letters" + +[fd3509e5-e3ba-409d-ac3d-a9ac84d13296] +description = "different characters may have the same bytes" diff --git a/exercises/practice/anagram/src/test/groovy/AnagramSpec.groovy b/exercises/practice/anagram/src/test/groovy/AnagramSpec.groovy index e979cf4a..302a1e7d 100644 --- a/exercises/practice/anagram/src/test/groovy/AnagramSpec.groovy +++ b/exercises/practice/anagram/src/test/groovy/AnagramSpec.groovy @@ -18,7 +18,7 @@ class AnagramSpec extends Specification { where: subject | candidates || expected - 'master' | ['stream', 'pigeon', 'maters'] || ['stream', 'maters'] + 'solemn' | ['lemons', 'cherry', 'melons'] || ['lemons', 'melons'] } @Ignore @@ -114,8 +114,8 @@ class AnagramSpec extends Specification { new Anagram(subject).find(candidates) == expected where: - subject | candidates || expected - 'go' | ['go Go GO'] || [] + subject | candidates || expected + 'go' | ['goGoGO'] || [] } @Ignore @@ -129,13 +129,33 @@ class AnagramSpec extends Specification { } @Ignore - def "Words are not anagrams of themselves (case-insensitive)"() { + def "Words are not anagrams of themselves"() { expect: new Anagram(subject).find(candidates) == expected where: - subject | candidates || expected - 'BANANA' | ['BANANA', 'Banana', 'banana'] || [] + subject | candidates || expected + 'BANANA' | ['BANANA'] || [] + } + + @Ignore + def "Words are not anagrams of themselves even if the letter case is partially different"() { + expect: + new Anagram(subject).find(candidates) == expected + + where: + subject | candidates || expected + 'BANANA' | ['Banana'] || [] + } + + @Ignore + def "Words are not anagrams of themselves even if the letter case is completely different"() { + expect: + new Anagram(subject).find(candidates) == expected + + where: + subject | candidates || expected + 'BANANA' | ['banana'] || [] } @Ignore @@ -144,8 +164,28 @@ class AnagramSpec extends Specification { new Anagram(subject).find(candidates) == expected where: - subject | candidates || expected - 'LISTEN' | ['Listen', 'Silent', 'LISTEN'] || ['Silent'] + subject | candidates || expected + 'LISTEN' | ['Listen', 'Silent'] || ['Silent'] + } + + @Ignore + def "Handles case of greek letters"() { + expect: + new Anagram(subject).find(candidates) == expected + + where: + subject | candidates || expected + 'ΑΒΓ' | ['ΒΓΑ', 'ΒΓΔ', 'γβα', 'αβγ'] || ['ΒΓΑ', 'γβα'] + } + + @Ignore + def "Different characters may have the same bytes"() { + expect: + new Anagram(subject).find(candidates) == expected + + where: + subject | candidates || expected + 'a⬂' | ['€a'] || [] } -} \ No newline at end of file +} diff --git a/exercises/practice/armstrong-numbers/.meta/tests.toml b/exercises/practice/armstrong-numbers/.meta/tests.toml index fdada6d1..b956bdfd 100644 --- a/exercises/practice/armstrong-numbers/.meta/tests.toml +++ b/exercises/practice/armstrong-numbers/.meta/tests.toml @@ -1,30 +1,45 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [c1ed103c-258d-45b2-be73-d8c6d9580c7b] description = "Zero is an Armstrong number" [579e8f03-9659-4b85-a1a2-d64350f6b17a] -description = "Single digit numbers are Armstrong numbers" +description = "Single-digit numbers are Armstrong numbers" [2d6db9dc-5bf8-4976-a90b-b2c2b9feba60] -description = "There are no 2 digit Armstrong numbers" +description = "There are no two-digit Armstrong numbers" [509c087f-e327-4113-a7d2-26a4e9d18283] -description = "Three digit number that is an Armstrong number" +description = "Three-digit number that is an Armstrong number" [7154547d-c2ce-468d-b214-4cb953b870cf] -description = "Three digit number that is not an Armstrong number" +description = "Three-digit number that is not an Armstrong number" [6bac5b7b-42e9-4ecb-a8b0-4832229aa103] -description = "Four digit number that is an Armstrong number" +description = "Four-digit number that is an Armstrong number" [eed4b331-af80-45b5-a80b-19c9ea444b2e] -description = "Four digit number that is not an Armstrong number" +description = "Four-digit number that is not an Armstrong number" [f971ced7-8d68-4758-aea1-d4194900b864] -description = "Seven digit number that is an Armstrong number" +description = "Seven-digit number that is an Armstrong number" [7ee45d52-5d35-4fbd-b6f1-5c8cd8a67f18] -description = "Seven digit number that is not an Armstrong number" +description = "Seven-digit number that is not an Armstrong number" + +[5ee2fdf8-334e-4a46-bb8d-e5c19c02c148] +description = "Armstrong number containing seven zeroes" +include = false + +[12ffbf10-307a-434e-b4ad-c925680e1dd4] +description = "The largest and last Armstrong number" +include = false diff --git a/exercises/practice/bank-account/.meta/src/reference/groovy/BankAccount.groovy b/exercises/practice/bank-account/.meta/src/reference/groovy/BankAccount.groovy index 3f35f2c5..eb785a8c 100644 --- a/exercises/practice/bank-account/.meta/src/reference/groovy/BankAccount.groovy +++ b/exercises/practice/bank-account/.meta/src/reference/groovy/BankAccount.groovy @@ -6,6 +6,8 @@ class BankAccount { // An account opens with a balance of 0 // You can reopen an account synchronized void open() { + if (isOpen) + throw new Exception("Already open") isOpen = true balance = 0 } @@ -13,7 +15,6 @@ class BankAccount { // you cannot do any operations after you close the account synchronized void close() { checkOpen() - balance = 0 isOpen = false } @@ -45,4 +46,4 @@ class BankAccount { if (!isOpen) throw new Exception("Account must be open") } -} \ No newline at end of file +} diff --git a/exercises/practice/bank-account/.meta/tests.toml b/exercises/practice/bank-account/.meta/tests.toml new file mode 100644 index 00000000..4e42d4dc --- /dev/null +++ b/exercises/practice/bank-account/.meta/tests.toml @@ -0,0 +1,61 @@ +# 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. + +[983a1528-4ceb-45e5-8257-8ce01aceb5ed] +description = "Newly opened account has zero balance" + +[e88d4ec3-c6bf-4752-8e59-5046c44e3ba7] +description = "Single deposit" + +[3d9147d4-63f4-4844-8d2b-1fee2e9a2a0d] +description = "Multiple deposits" + +[08f1af07-27ae-4b38-aa19-770bde558064] +description = "Withdraw once" + +[6f6d242f-8c31-4ac6-8995-a90d42cad59f] +description = "Withdraw twice" + +[45161c94-a094-4c77-9cec-998b70429bda] +description = "Can do multiple operations sequentially" + +[f9facfaa-d824-486e-8381-48832c4bbffd] +description = "Cannot check balance of closed account" + +[7a65ba52-e35c-4fd2-8159-bda2bde6e59c] +description = "Cannot deposit into closed account" + +[a0a1835d-faae-4ad4-a6f3-1fcc2121380b] +description = "Cannot deposit into unopened account" + +[570dfaa5-0532-4c1f-a7d3-0f65c3265608] +description = "Cannot withdraw from closed account" + +[c396d233-1c49-4272-98dc-7f502dbb9470] +description = "Cannot close an account that was not opened" + +[c06f534f-bdc2-4a02-a388-1063400684de] +description = "Cannot open an already opened account" + +[0722d404-6116-4f92-ba3b-da7f88f1669c] +description = "Reopened account does not retain balance" + +[ec42245f-9361-4341-8231-a22e8d19c52f] +description = "Cannot withdraw more than deposited" + +[4f381ef8-10ef-4507-8e1d-0631ecc8ee72] +description = "Cannot withdraw negative" + +[d45df9ea-1db0-47f3-b18c-d365db49d938] +description = "Cannot deposit negative" + +[ba0c1e0b-0f00-416f-8097-a7dfc97871ff] +description = "Can handle concurrent transactions" diff --git a/exercises/practice/bank-account/src/test/groovy/BankAccountSpec.groovy b/exercises/practice/bank-account/src/test/groovy/BankAccountSpec.groovy index 9731f45e..a2139a52 100644 --- a/exercises/practice/bank-account/src/test/groovy/BankAccountSpec.groovy +++ b/exercises/practice/bank-account/src/test/groovy/BankAccountSpec.groovy @@ -2,7 +2,7 @@ import spock.lang.* class BankAccountSpec extends Specification { - def "Newly opened account has empty balance"() { + def "Newly opened account has zero balance"() { setup: BankAccount account = new BankAccount() @@ -14,172 +14,215 @@ class BankAccountSpec extends Specification { } @Ignore - def "Can deposit money"() { + def "Single deposit"() { setup: BankAccount account = new BankAccount() when: account.open() - account.deposit(10) + account.deposit(100) then: - account.getBalance() == 10 + account.getBalance() == 100 } @Ignore - def "Can deposit money sequentially"() { + def "Multiple deposit"() { setup: BankAccount bankAccount = new BankAccount() when: bankAccount.open() - bankAccount.deposit(5) - bankAccount.deposit(23) + bankAccount.deposit(100) + bankAccount.deposit(50) then: - bankAccount.getBalance() == 28 + bankAccount.getBalance() == 150 } @Ignore - def "Can withdraw money"() { + def "Withdraw once"() { setup: BankAccount bankAccount = new BankAccount() when: bankAccount.open() - bankAccount.deposit(10) - bankAccount.withdraw(5) + bankAccount.deposit(100) + bankAccount.withdraw(75) then: - bankAccount.getBalance() == 5 + bankAccount.getBalance() == 25 } @Ignore - def "Can withdraw money sequentially"() { + def "Withdraw twice"() { setup: BankAccount bankAccount = new BankAccount() when: bankAccount.open() - bankAccount.deposit(23) - bankAccount.withdraw(10) - bankAccount.withdraw(13) + bankAccount.deposit(100) + bankAccount.withdraw(80) + bankAccount.withdraw(20) then: bankAccount.getBalance() == 0 } @Ignore - def "Cannot withdraw money from empty account"() { + def "Can do multiple operations sequentially"() { setup: BankAccount bankAccount = new BankAccount() when: - bankAccount.withdraw(5) + bankAccount.open() + bankAccount.deposit(100) + bankAccount.deposit(110) + bankAccount.withdraw(200) + bankAccount.deposit(60) + bankAccount.withdraw(50) then: - thrown(Exception) + bankAccount.getBalance() == 20 } @Ignore - def "Cannot withdraw more money than you have"() { + def "Cannot check balance of closed account"() { setup: BankAccount bankAccount = new BankAccount() when: bankAccount.open() - bankAccount.deposit(6) - bankAccount.withdraw(7) + bankAccount.close() + bankAccount.getBalance() then: thrown(Exception) } @Ignore - def "Cannot deposit negative amount"() { + def "Cannot deposit into closed account"() { setup: BankAccount bankAccount = new BankAccount() when: bankAccount.open() - bankAccount.deposit(-1) + bankAccount.close() + bankAccount.deposit(50) then: thrown(Exception) } @Ignore - def "Cannot withdraw negative amount"() { + def "Cannot deposit into unopened account"() { setup: BankAccount bankAccount = new BankAccount() when: - bankAccount.open() - bankAccount.deposit(105) - bankAccount.withdraw(-5) + bankAccount.deposit(50) then: thrown(Exception) } @Ignore - def "Cannot get balance of closed account"() { + def "Cannot withdraw from closed account"() { setup: BankAccount bankAccount = new BankAccount() when: bankAccount.open() - bankAccount.deposit(10) bankAccount.close() - bankAccount.getBalance() + bankAccount.withdraw(50) then: thrown(Exception) } @Ignore - def "Cannot deposit money into closed account"() { + def "Cannot close an account that was not opened"() { setup: BankAccount bankAccount = new BankAccount() when: - bankAccount.open() bankAccount.close() - bankAccount.deposit(5) then: thrown(Exception) } @Ignore - def "Cannot withdraw money from closed account"() { + def "Cannot open an already opened account"() { setup: BankAccount bankAccount = new BankAccount() when: bankAccount.open() - bankAccount.deposit(20) + bankAccount.open() + + then: + thrown(Exception) + } + + @Ignore + def "Reopened account does not retain balance"() { + setup: + BankAccount bankAccount = new BankAccount() + + when: + bankAccount.open() + bankAccount.deposit(50) bankAccount.close() - bankAccount.withdraw(5) + bankAccount.open() + + then: + bankAccount.getBalance() == 0 + } + + @Ignore + def "Cannot withdraw more than deposited"() { + setup: + BankAccount bankAccount = new BankAccount() + + when: + bankAccount.open() + bankAccount.deposit(25) + bankAccount.withdraw(50) then: thrown(Exception) } @Ignore - def "Bank account is closed before it is opened"() { + def "Cannot withdraw negative"() { setup: BankAccount bankAccount = new BankAccount() when: - bankAccount.getBalance() + bankAccount.open() + bankAccount.deposit(100) + bankAccount.withdraw(-50) + + then: + thrown(Exception) + } + + @Ignore + def "Cannot deposit negative"() { + setup: + BankAccount bankAccount = new BankAccount() + + when: + bankAccount.open() + bankAccount.deposit(-50) then: thrown(Exception) } @Ignore - def "Can adjust balance concurrently"() { + def "Can handle concurrent transactions"() { setup: BankAccount bankAccount = new BankAccount() @@ -216,4 +259,4 @@ class BankAccountSpec extends Specification { threads.each { it.join() } } -} \ No newline at end of file +} diff --git a/exercises/practice/bob/.meta/tests.toml b/exercises/practice/bob/.meta/tests.toml index 63048557..5299e289 100644 --- a/exercises/practice/bob/.meta/tests.toml +++ b/exercises/practice/bob/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [e162fead-606f-437a-a166-d051915cea8e] description = "stating something" @@ -64,6 +71,7 @@ description = "alternate silence" [66953780-165b-4e7e-8ce3-4bcb80b6385a] description = "multiple line question" +include = false [5371ef75-d9ea-4103-bcfa-2da973ddec1b] description = "starting with whitespace" @@ -76,3 +84,7 @@ description = "other whitespace" [12983553-8601-46a8-92fa-fcaa3bc4a2a0] description = "non-question ending with whitespace" + +[2c7278ac-f955-4eb4-bf8f-e33eb4116a15] +description = "multiple line question" +reimplements = "66953780-165b-4e7e-8ce3-4bcb80b6385a" diff --git a/exercises/practice/bob/src/test/groovy/BobSpec.groovy b/exercises/practice/bob/src/test/groovy/BobSpec.groovy index 2d138370..a2c07480 100644 --- a/exercises/practice/bob/src/test/groovy/BobSpec.groovy +++ b/exercises/practice/bob/src/test/groovy/BobSpec.groovy @@ -207,8 +207,8 @@ class BobSpec extends Specification { Bob.response(heyBob) == expected where: - heyBob || expected - '\nDoes this cryogenic chamber make me look fat?\nNo.' || 'Whatever.' + heyBob || expected + '\nDoes this cryogenic chamber make\n me look fat?' || 'Sure.' } @Ignore @@ -251,4 +251,4 @@ class BobSpec extends Specification { 'This is a statement ending with whitespace ' || 'Whatever.' } -} \ No newline at end of file +} diff --git a/exercises/practice/collatz-conjecture/.meta/src/reference/groovy/CollatzConjecture.groovy b/exercises/practice/collatz-conjecture/.meta/src/reference/groovy/CollatzConjecture.groovy index 0391a06c..547ba4c8 100644 --- a/exercises/practice/collatz-conjecture/.meta/src/reference/groovy/CollatzConjecture.groovy +++ b/exercises/practice/collatz-conjecture/.meta/src/reference/groovy/CollatzConjecture.groovy @@ -1,7 +1,7 @@ class CollatzConjecture { static int steps(int number) { - if (number < 1) throw new ArithmeticException("Only positive numbers are allowed") + if (number < 1) throw new ArithmeticException("Only positive integers are allowed") int result = 0 int n = number @@ -12,4 +12,4 @@ class CollatzConjecture { result } -} \ No newline at end of file +} diff --git a/exercises/practice/collatz-conjecture/.meta/tests.toml b/exercises/practice/collatz-conjecture/.meta/tests.toml index 04187f60..cc34e168 100644 --- a/exercises/practice/collatz-conjecture/.meta/tests.toml +++ b/exercises/practice/collatz-conjecture/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [540a3d51-e7a6-47a5-92a3-4ad1838f0bfd] description = "zero steps for one" @@ -16,6 +23,16 @@ description = "large number of even and odd steps" [7d4750e6-def9-4b86-aec7-9f7eb44f95a3] description = "zero is an error" +include = false + +[2187673d-77d6-4543-975e-66df6c50e2da] +description = "zero is an error" +reimplements = "7d4750e6-def9-4b86-aec7-9f7eb44f95a3" [c6c795bf-a288-45e9-86a1-841359ad426d] description = "negative value is an error" +include = false + +[ec11f479-56bc-47fd-a434-bcd7a31a7a2e] +description = "negative value is an error" +reimplements = "c6c795bf-a288-45e9-86a1-841359ad426d" diff --git a/exercises/practice/dnd-character/.meta/tests.toml b/exercises/practice/dnd-character/.meta/tests.toml index 2b04dd33..719043b2 100644 --- a/exercises/practice/dnd-character/.meta/tests.toml +++ b/exercises/practice/dnd-character/.meta/tests.toml @@ -65,3 +65,8 @@ description = "random character is valid" [2ca77b9b-c099-46c3-a02c-0d0f68ffa0fe] description = "each ability is only calculated once" +include = false + +[dca2b2ec-f729-4551-84b9-078876bb4808] +description = "each ability is only calculated once" +reimplements = "2ca77b9b-c099-46c3-a02c-0d0f68ffa0fe" diff --git a/exercises/practice/dnd-character/src/test/groovy/DndCharacterSpec.groovy b/exercises/practice/dnd-character/src/test/groovy/DndCharacterSpec.groovy index 4f47d5e7..241d9ee4 100644 --- a/exercises/practice/dnd-character/src/test/groovy/DndCharacterSpec.groovy +++ b/exercises/practice/dnd-character/src/test/groovy/DndCharacterSpec.groovy @@ -180,10 +180,27 @@ class DndCharacterSpec extends Specification { def "each ability is only calculated once"() { given: def character = new DndCharacter() + def strength = character.strength + def dexterity = character.dexterity + def constitution = character.constitution + def intelligence = character.intelligence + def wisdom = character.wisdom + def charisma = character.charisma + def strengthAgain = character.strength + def dexterityAgain = character.dexterity + def constitutionAgain = character.constitution + def intelligenceAgain = character.intelligence + def wisdomAgain = character.wisdom + def charismaAgain = character.charisma expect: strength == strengthAgain + dexterity == dexterityAgain + constitution == constitutionAgain + intelligence == intelligenceAgain + wisdom == wisdomAgain + charisma == charismaAgain } } diff --git a/exercises/practice/flatten-array/.meta/tests.toml b/exercises/practice/flatten-array/.meta/tests.toml index 99eea495..44acf175 100644 --- a/exercises/practice/flatten-array/.meta/tests.toml +++ b/exercises/practice/flatten-array/.meta/tests.toml @@ -1,10 +1,23 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. + +[8c71dabd-da60-422d-a290-4a571471fb14] +description = "empty" [d268b919-963c-442d-9f07-82b93f1b518c] description = "no nesting" +[3f15bede-c856-479e-bb71-1684b20c6a30] +description = "flattens a nested array" + [c84440cc-bb3a-48a6-862c-94cf23f2815d] description = "flattens array with just integers present" @@ -14,8 +27,37 @@ description = "5 level nesting" [d572bdba-c127-43ed-bdcd-6222ac83d9f7] description = "6 level nesting" +[0705a8e5-dc86-4cec-8909-150c5e54fa9c] +description = "null values are omitted from the final result" + +[c6cf26de-8ccd-4410-84bd-b9efd88fd2bc] +description = "consecutive null values at the front of the list are omitted from the final result" +include = false + +[bc72da10-5f55-4ada-baf3-50e4da02ec8e] +description = "consecutive null values at the front of the array are omitted from the final result" +reimplements = "c6cf26de-8ccd-4410-84bd-b9efd88fd2bc" + +[382c5242-587e-4577-b8ce-a5fb51e385a1] +description = "consecutive null values in the middle of the list are omitted from the final result" +include = false + +[6991836d-0d9b-4703-80a0-3f1f23eb5981] +description = "consecutive null values in the middle of the array are omitted from the final result" +reimplements = "382c5242-587e-4577-b8ce-a5fb51e385a1" + [ef1d4790-1b1e-4939-a179-51ace0829dbd] description = "6 level nest list with null values" +include = false + +[dc90a09c-5376-449c-a7b3-c2d20d540069] +description = "6 level nested array with null values" +reimplements = "ef1d4790-1b1e-4939-a179-51ace0829dbd" [85721643-705a-4150-93ab-7ae398e2942d] description = "all values in nested list are null" +include = false + +[51f5d9af-8f7f-4fb5-a156-69e8282cb275] +description = "all values in nested array are null" +reimplements = "85721643-705a-4150-93ab-7ae398e2942d" diff --git a/exercises/practice/flatten-array/src/test/groovy/FlattenArraySpec.groovy b/exercises/practice/flatten-array/src/test/groovy/FlattenArraySpec.groovy index a5b575a5..a763832e 100644 --- a/exercises/practice/flatten-array/src/test/groovy/FlattenArraySpec.groovy +++ b/exercises/practice/flatten-array/src/test/groovy/FlattenArraySpec.groovy @@ -5,6 +5,16 @@ class FlattenArraySpec extends Specification { @Shared def flattener = new FlattenArray() + def "Empty"() { + expect: + flattener.flatten(array) == expected + + where: + array || expected + [] || [] + } + + @Ignore def "No nesting"() { expect: flattener.flatten(array) == expected @@ -14,6 +24,16 @@ class FlattenArraySpec extends Specification { [0, 1, 2] || [0, 1, 2] } + @Ignore + def "Flattens a nested array"() { + expect: + flattener.flatten(array) == expected + + where: + array || expected + [ [ [] ] ] || [] + } + @Ignore def "Flattens array with just integers present"() { expect: @@ -45,7 +65,47 @@ class FlattenArraySpec extends Specification { } @Ignore - def "6 level nest list with null values"() { + def "Null values are omitted from the final result"() { + expect: + flattener.flatten(array) == expected + + where: + array || expected + [1, 2, null] || [1, 2] + } + + @Ignore + def "Consecutive null values at the front of the array are omitted from the final result"() { + expect: + flattener.flatten(array) == expected + + where: + array || expected + [null, null, 3] || [3] + } + + @Ignore + def "Consecutive null values in the middle of the array are omitted from the final result"() { + expect: + flattener.flatten(array) == expected + + where: + array || expected + [1, null, null, 4] || [1, 4] + } + + @Ignore + def "Consecutive null values at the front of the array are omitted from the final result"() { + expect: + flattener.flatten(array) == expected + + where: + array || expected + [null, null, 3] || [3] + } + + @Ignore + def "6 level nest array with null values"() { expect: flattener.flatten(array) == expected @@ -55,7 +115,7 @@ class FlattenArraySpec extends Specification { } @Ignore - def "All values in nested list are null"() { + def "All values in nested array are null"() { expect: flattener.flatten(array) == expected diff --git a/exercises/practice/gigasecond/.meta/tests.toml b/exercises/practice/gigasecond/.meta/tests.toml index 18672327..a7caf00d 100644 --- a/exercises/practice/gigasecond/.meta/tests.toml +++ b/exercises/practice/gigasecond/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [92fbe71c-ea52-4fac-bd77-be38023cacf7] description = "date only specification of time" @@ -16,3 +23,6 @@ description = "full time specified" [09d4e30e-728a-4b52-9005-be44a58d9eba] description = "full time with day roll-over" + +[fcec307c-7529-49ab-b0fe-20309197618a] +description = "does not mutate the input" diff --git a/exercises/practice/gigasecond/src/test/groovy/GigasecondSpec.groovy b/exercises/practice/gigasecond/src/test/groovy/GigasecondSpec.groovy index b338a1f4..f9c24e2a 100644 --- a/exercises/practice/gigasecond/src/test/groovy/GigasecondSpec.groovy +++ b/exercises/practice/gigasecond/src/test/groovy/GigasecondSpec.groovy @@ -55,4 +55,14 @@ class GigasecondSpec extends Specification { expected = LocalDateTime.of(2046, Month.OCTOBER, 3, 1, 46, 39) } + @Ignore + def "Does not mutate the input"() { + given: + def moment = LocalDateTime.of(2015, Month.JANUARY, 24, 23, 59, 59) + def future = Gigasecond.add(moment) + + expect: + moment == LocalDateTime.of(2015, Month.JANUARY, 24, 23, 59, 59) + } + } diff --git a/exercises/practice/hamming/.meta/tests.toml b/exercises/practice/hamming/.meta/tests.toml index b2f80f48..5dc17ed4 100644 --- a/exercises/practice/hamming/.meta/tests.toml +++ b/exercises/practice/hamming/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [f6dcb64f-03b0-4b60-81b1-3c9dbf47e887] description = "empty strands" @@ -19,12 +26,42 @@ description = "long different strands" [919f8ef0-b767-4d1b-8516-6379d07fcb28] description = "disallow first strand longer" +include = false + +[b9228bb1-465f-4141-b40f-1f99812de5a8] +description = "disallow first strand longer" +reimplements = "919f8ef0-b767-4d1b-8516-6379d07fcb28" [8a2d4ed0-ead5-4fdd-924d-27c4cf56e60e] description = "disallow second strand longer" +include = false + +[dab38838-26bb-4fff-acbe-3b0a9bfeba2d] +description = "disallow second strand longer" +reimplements = "8a2d4ed0-ead5-4fdd-924d-27c4cf56e60e" [5dce058b-28d4-4ca7-aa64-adfe4e17784c] description = "disallow left empty strand" +include = false + +[db92e77e-7c72-499d-8fe6-9354d2bfd504] +description = "disallow left empty strand" +include = false +reimplements = "5dce058b-28d4-4ca7-aa64-adfe4e17784c" + +[b764d47c-83ff-4de2-ab10-6cfe4b15c0f3] +description = "disallow empty first strand" +reimplements = "db92e77e-7c72-499d-8fe6-9354d2bfd504" [38826d4b-16fb-4639-ac3e-ba027dec8b5f] description = "disallow right empty strand" +include = false + +[920cd6e3-18f4-4143-b6b8-74270bb8f8a3] +description = "disallow right empty strand" +include = false +reimplements = "38826d4b-16fb-4639-ac3e-ba027dec8b5f" + +[9ab9262f-3521-4191-81f5-0ed184a5aa89] +description = "disallow empty second strand" +reimplements = "920cd6e3-18f4-4143-b6b8-74270bb8f8a3" diff --git a/exercises/practice/high-scores/.meta/tests.toml b/exercises/practice/high-scores/.meta/tests.toml index 4008e012..7c946338 100644 --- a/exercises/practice/high-scores/.meta/tests.toml +++ b/exercises/practice/high-scores/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [1035eb93-2208-4c22-bab8-fef06769a73c] description = "List of scores" @@ -12,16 +19,28 @@ description = "Latest score" description = "Personal best" [3d996a97-c81c-4642-9afc-80b80dc14015] -description = "Personal top three from a list of scores" +description = "Top 3 scores -> Personal top three from a list of scores" [1084ecb5-3eb4-46fe-a816-e40331a4e83a] -description = "Personal top highest to lowest" +description = "Top 3 scores -> Personal top highest to lowest" [e6465b6b-5a11-4936-bfe3-35241c4f4f16] -description = "Personal top when there is a tie" +description = "Top 3 scores -> Personal top when there is a tie" [f73b02af-c8fd-41c9-91b9-c86eaa86bce2] -description = "Personal top when there are less than 3" +description = "Top 3 scores -> Personal top when there are less than 3" [16608eae-f60f-4a88-800e-aabce5df2865] -description = "Personal top when there is only one" +description = "Top 3 scores -> Personal top when there is only one" + +[2df075f9-fec9-4756-8f40-98c52a11504f] +description = "Top 3 scores -> Latest score after personal top scores" + +[809c4058-7eb1-4206-b01e-79238b9b71bc] +description = "Top 3 scores -> Scores after personal top scores" + +[ddb0efc0-9a86-4f82-bc30-21ae0bdc6418] +description = "Top 3 scores -> Latest score after personal best" + +[6a0fd2d1-4cc4-46b9-a5bb-2fb667ca2364] +description = "Top 3 scores -> Scores after personal best" diff --git a/exercises/practice/high-scores/src/test/groovy/HighScoresSpec.groovy b/exercises/practice/high-scores/src/test/groovy/HighScoresSpec.groovy index f513a197..c35f4e10 100644 --- a/exercises/practice/high-scores/src/test/groovy/HighScoresSpec.groovy +++ b/exercises/practice/high-scores/src/test/groovy/HighScoresSpec.groovy @@ -80,9 +80,9 @@ class HighScoresSpec extends Specification { scores || expected [40] || [40] } - + @Ignore - def "Personal top three does not mutate"() { + def "Latest score after personal top scores"() { given: def hs = new HighScores(scores) def top3 = hs.personalTopThree() @@ -92,7 +92,49 @@ class HighScoresSpec extends Specification { where: scores || expected - [40, 20, 10, 30] || 30 + [70, 50, 20, 30] || 30 + } + + @Ignore + def "Scores after personal top scores"() { + given: + def hs = new HighScores(scores) + def top3 = hs.personalTopThree() + + expect: + hs.scores == expected + + where: + scores || expected + [30, 50, 20, 70] || [30, 50, 20, 70] + } + + @Ignore + def "Latest score after personal best"() { + given: + def hs = new HighScores(scores) + def top3 = hs.personalBest() + + expect: + hs.latest() == expected + + where: + scores || expected + [20, 70, 15, 25, 30] || 30 + } + + @Ignore + def "Scores after personal best"() { + given: + def hs = new HighScores(scores) + def top3 = hs.personalBest() + + expect: + hs.scores == expected + + where: + scores || expected + [20, 70, 15, 25, 30] || [20, 70, 15, 25, 30] } } diff --git a/exercises/practice/isbn-verifier/.meta/tests.toml b/exercises/practice/isbn-verifier/.meta/tests.toml index 5d2c0c3f..722fffae 100644 --- a/exercises/practice/isbn-verifier/.meta/tests.toml +++ b/exercises/practice/isbn-verifier/.meta/tests.toml @@ -1,25 +1,38 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [0caa3eac-d2e3-4c29-8df8-b188bc8c9292] -description = "valid isbn number" +description = "valid isbn" [19f76b53-7c24-45f8-87b8-4604d0ccd248] description = "invalid isbn check digit" [4164bfee-fb0a-4a1c-9f70-64c6a1903dcd] -description = "valid isbn number with a check digit of 10" +description = "valid isbn with a check digit of 10" [3ed50db1-8982-4423-a993-93174a20825c] description = "check digit is a character other than X" +[9416f4a5-fe01-4b61-a07b-eb75892ef562] +description = "invalid check digit in isbn is not treated as zero" + [c19ba0c4-014f-4dc3-a63f-ff9aefc9b5ec] -description = "invalid character in isbn" +description = "invalid character in isbn is not treated as zero" [28025280-2c39-4092-9719-f3234b89c627] description = "X is only valid as a check digit" +[fdb14c99-4cf8-43c5-b06d-eb1638eff343] +description = "X is not substituted by the value 10" + [f6294e61-7e79-46b3-977b-f48789a4945b] description = "valid isbn without separating dashes" @@ -48,7 +61,10 @@ description = "empty isbn" description = "input is 9 characters" [ed6e8d1b-382c-4081-8326-8b772c581fec] -description = "invalid characters are not ignored" +description = "invalid characters are not ignored after checking length" + +[daad3e58-ce00-4395-8a8e-e3eded1cdc86] +description = "invalid characters are not ignored before checking length" [fb5e48d8-7c03-4bfb-a088-b101df16fdc3] description = "input is too long but contains a valid isbn" diff --git a/exercises/practice/isbn-verifier/src/test/groovy/IsbnVerifierSpec.groovy b/exercises/practice/isbn-verifier/src/test/groovy/IsbnVerifierSpec.groovy index 88967767..f96ade6e 100644 --- a/exercises/practice/isbn-verifier/src/test/groovy/IsbnVerifierSpec.groovy +++ b/exercises/practice/isbn-verifier/src/test/groovy/IsbnVerifierSpec.groovy @@ -41,6 +41,16 @@ class IsbnVerifierSpec extends Specification { '3-598-21507-A' || false } + @Ignore + def "Invalid check digit in isbn is not treated as zero"() { + expect: + IsbnVerifier.isValid(isbn) == expected + + where: + isbn || expected + '4-598-21507-B' || false + } + @Ignore def "Invalid character in isbn"() { expect: @@ -61,6 +71,16 @@ class IsbnVerifierSpec extends Specification { '3-598-2X507-9' || false } + @Ignore + def "X is not substituted by the value 10"() { + expect: + IsbnVerifier.isValid(isbn) == expected + + where: + isbn || expected + '3-598-2X507-5' || false + } + @Ignore def "Valid isbn without separating dashes"() { expect: @@ -152,7 +172,7 @@ class IsbnVerifierSpec extends Specification { } @Ignore - def "Invalid characters are not ignored"() { + def "Invalid characters are not ignored after checking length"() { expect: IsbnVerifier.isValid(isbn) == expected @@ -161,6 +181,16 @@ class IsbnVerifierSpec extends Specification { '3132P34035' || false } + @Ignore + def "Invalid characters are not ignored before checking length"() { + expect: + IsbnVerifier.isValid(isbn) == expected + + where: + isbn || expected + '3598P215088' || false + } + @Ignore def "Input is too long but contains a valid isbn"() { expect: @@ -170,4 +200,4 @@ class IsbnVerifierSpec extends Specification { isbn || expected '98245726788' || false } -} \ No newline at end of file +} diff --git a/exercises/practice/isogram/.meta/tests.toml b/exercises/practice/isogram/.meta/tests.toml index 7187c340..ba04c664 100644 --- a/exercises/practice/isogram/.meta/tests.toml +++ b/exercises/practice/isogram/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [a0e97d2d-669e-47c7-8134-518a1e2c4555] description = "empty string" @@ -40,3 +47,6 @@ description = "duplicated character in the middle" [310ac53d-8932-47bc-bbb4-b2b94f25a83e] description = "same first and last characters" + +[0d0b8644-0a1e-4a31-a432-2b3ee270d847] +description = "word with duplicated character and with two hyphens" diff --git a/exercises/practice/isogram/src/test/groovy/IsogramSpec.groovy b/exercises/practice/isogram/src/test/groovy/IsogramSpec.groovy index 52c0d942..d019fa95 100644 --- a/exercises/practice/isogram/src/test/groovy/IsogramSpec.groovy +++ b/exercises/practice/isogram/src/test/groovy/IsogramSpec.groovy @@ -131,4 +131,14 @@ class IsogramSpec extends Specification { 'angola' || false } -} \ No newline at end of file + @Ignore + def "Word with duplicated character and with two hyphens"() { + expect: + Isogram.isIsogram(phrase) == expected + + where: + phrase || expected + 'up-to-date' || false + } + +} diff --git a/exercises/practice/largest-series-product/.meta/src/reference/groovy/LargestSeriesProduct.groovy b/exercises/practice/largest-series-product/.meta/src/reference/groovy/LargestSeriesProduct.groovy index 8262ce13..be1943ef 100644 --- a/exercises/practice/largest-series-product/.meta/src/reference/groovy/LargestSeriesProduct.groovy +++ b/exercises/practice/largest-series-product/.meta/src/reference/groovy/LargestSeriesProduct.groovy @@ -1,7 +1,7 @@ class LargestSeriesProduct { static int largestProduct(String digits, final int span) { if (span < 0) throw new IllegalArgumentException("span must not be negative") - if (span > digits.length()) throw new IllegalArgumentException("span must be smaller than string length") + if (span > digits.length()) throw new IllegalArgumentException("span must not exceed string length") if (!digits.chars().allMatch(Character::isDigit)) throw new IllegalArgumentException("digits input must only contain digits") int maximum = 0 for (i in 0..digits.length() - span) { @@ -13,4 +13,4 @@ class LargestSeriesProduct { } maximum } -} \ No newline at end of file +} diff --git a/exercises/practice/largest-series-product/.meta/tests.toml b/exercises/practice/largest-series-product/.meta/tests.toml index 6c111adf..5a62d619 100644 --- a/exercises/practice/largest-series-product/.meta/tests.toml +++ b/exercises/practice/largest-series-product/.meta/tests.toml @@ -38,6 +38,11 @@ description = "reports zero if all spans include zero" [5d81aaf7-4f67-4125-bf33-11493cc7eab7] description = "rejects span longer than string length" +include = false + +[0ae1ce53-d9ba-41bb-827f-2fceb64f058b] +description = "rejects span longer than string length" +reimplements = "5d81aaf7-4f67-4125-bf33-11493cc7eab7" [06bc8b90-0c51-4c54-ac22-3ec3893a079e] description = "reports 1 for empty string and empty product (0 span)" @@ -47,6 +52,11 @@ description = "reports 1 for nonempty string and empty product (0 span)" [6d96c691-4374-4404-80ee-2ea8f3613dd4] description = "rejects empty string and nonzero span" +include = false + +[6cf66098-a6af-4223-aab1-26aeeefc7402] +description = "rejects empty string and nonzero span" +reimplements = "6d96c691-4374-4404-80ee-2ea8f3613dd4" [7a38f2d6-3c35-45f6-8d6f-12e6e32d4d74] description = "rejects invalid character in digits" diff --git a/exercises/practice/largest-series-product/src/test/groovy/LargestSeriesProductSpec.groovy b/exercises/practice/largest-series-product/src/test/groovy/LargestSeriesProductSpec.groovy index 190c7b23..dc10b136 100644 --- a/exercises/practice/largest-series-product/src/test/groovy/LargestSeriesProductSpec.groovy +++ b/exercises/practice/largest-series-product/src/test/groovy/LargestSeriesProductSpec.groovy @@ -101,7 +101,7 @@ class LargestSeriesProductSpec extends Specification { where: digits | span || expectedErrorMessage - "123" | 4 || "span must be smaller than string length" + "123" | 4 || "span must not exceed string length" } @Ignore @@ -135,7 +135,7 @@ class LargestSeriesProductSpec extends Specification { where: digits | span || expectedErrorMessage - "" | 1 || "span must be smaller than string length" + "" | 1 || "span must not exceed string length" } @Ignore @@ -165,4 +165,4 @@ class LargestSeriesProductSpec extends Specification { digits | span || expectedErrorMessage "12345" | -1 || "span must not be negative" } -} \ No newline at end of file +} diff --git a/exercises/practice/linked-list/.meta/config.json b/exercises/practice/linked-list/.meta/config.json index 811d4961..990ff5d6 100644 --- a/exercises/practice/linked-list/.meta/config.json +++ b/exercises/practice/linked-list/.meta/config.json @@ -3,7 +3,8 @@ "contributors": [ "amscotti", "ikhadykin", - "Raibaz" + "Raibaz", + "glennj" ], "files": { "solution": [ diff --git a/exercises/practice/linked-list/.meta/src/reference/groovy/DoubleLinkedList.groovy b/exercises/practice/linked-list/.meta/src/reference/groovy/DoubleLinkedList.groovy index 1d2ee8ae..811ba2ad 100644 --- a/exercises/practice/linked-list/.meta/src/reference/groovy/DoubleLinkedList.groovy +++ b/exercises/practice/linked-list/.meta/src/reference/groovy/DoubleLinkedList.groovy @@ -1,8 +1,14 @@ class DoubleLinkedList { Element head + int n = 0 + + int count() { + n + } void push(T value) { + n++ if (!head) { head = new Element<>(value, null, null) head.next = head @@ -22,6 +28,7 @@ class DoubleLinkedList { } T shift() { + n-- T value = head.value def newHead = head.next @@ -43,6 +50,30 @@ class DoubleLinkedList { head = head.prev } + void delete(T value) { + if (n == 1) { + if (head.value == value) { + head = null + n-- + } + } else if (n > 1) { + Element node = head + while (true) { + if (node.value == value) { + n-- + node.prev.next = node.next + node.next.prev = node.prev + if (head.is(node)) { + head = node.next + } + return + } + node = node.next + if (node.is(head)) break + } + } + } + private static final class Element { final T value Element prev diff --git a/exercises/practice/linked-list/.meta/tests.toml b/exercises/practice/linked-list/.meta/tests.toml new file mode 100644 index 00000000..96906d2c --- /dev/null +++ b/exercises/practice/linked-list/.meta/tests.toml @@ -0,0 +1,67 @@ +# 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. + +[7f7e3987-b954-41b8-8084-99beca08752c] +description = "pop gets element from the list" + +[c3f67e5d-cfa2-4c3e-a18f-7ce999c3c885] +description = "push/pop respectively add/remove at the end of the list" + +[00ea24ce-4f5c-4432-abb4-cc6e85462657] +description = "shift gets an element from the list" + +[37962ee0-3324-4a29-b588-5a4c861e6564] +description = "shift gets first element from the list" + +[30a3586b-e9dc-43fb-9a73-2770cec2c718] +description = "unshift adds element at start of the list" + +[042f71e4-a8a7-4cf0-8953-7e4f3a21c42d] +description = "pop, push, shift, and unshift can be used in any order" + +[88f65c0c-4532-4093-8295-2384fb2f37df] +description = "count an empty list" + +[fc055689-5cbe-4cd9-b994-02e2abbb40a5] +description = "count a list with items" + +[8272cef5-130d-40ea-b7f6-5ffd0790d650] +description = "count is correct after mutation" + +[229b8f7a-bd8a-4798-b64f-0dc0bb356d95] +description = "popping to empty doesn't break the list" + +[4e1948b4-514e-424b-a3cf-a1ebbfa2d1ad] +description = "shifting to empty doesn't break the list" + +[e8f7c600-d597-4f79-949d-8ad8bae895a6] +description = "deletes the only element" + +[fd65e422-51f3-45c0-9fd0-c33da638f89b] +description = "deletes the element with the specified value from the list" + +[59db191a-b17f-4ab7-9c5c-60711ec1d013] +description = "deletes the element with the specified value from the list, re-assigns tail" + +[58242222-5d39-415b-951d-8128247f8993] +description = "deletes the element with the specified value from the list, re-assigns head" + +[ee3729ee-3405-4bd2-9bad-de0d4aa5d647] +description = "deletes the first of two elements" + +[47e3b3b4-b82c-4c23-8c1a-ceb9b17cb9fb] +description = "deletes the second of two elements" + +[7b420958-f285-4922-b8f9-10d9dcab5179] +description = "delete does not modify the list if the element is not found" + +[7e04828f-6082-44e3-a059-201c63252a76] +description = "deletes only the first occurrence" diff --git a/exercises/practice/linked-list/src/main/groovy/DoubleLinkedList.groovy b/exercises/practice/linked-list/src/main/groovy/DoubleLinkedList.groovy index 483dbb3f..a86178e6 100644 --- a/exercises/practice/linked-list/src/main/groovy/DoubleLinkedList.groovy +++ b/exercises/practice/linked-list/src/main/groovy/DoubleLinkedList.groovy @@ -16,4 +16,12 @@ class DoubleLinkedList { throw new UnsupportedOperationException('Method implementation is missing') } + int count() { + throw new UnsupportedOperationException('Method implementation is missing') + } + + void delete(T value) { + throw new UnsupportedOperationException('Method implementation is missing') + } + } diff --git a/exercises/practice/linked-list/src/test/groovy/DoubleLinkedListSpec.groovy b/exercises/practice/linked-list/src/test/groovy/DoubleLinkedListSpec.groovy index 8c95104d..2b1b27dc 100644 --- a/exercises/practice/linked-list/src/test/groovy/DoubleLinkedListSpec.groovy +++ b/exercises/practice/linked-list/src/test/groovy/DoubleLinkedListSpec.groovy @@ -2,89 +2,288 @@ import spock.lang.* class DoubleLinkedListSpec extends Specification { - def "Can push and pop"() { + def "pop gets element from the list"() { DoubleLinkedList list = new DoubleLinkedList<>() when: - list.push(10) - list.push(20) + list.push(7) then: - list.pop() == 20 + list.pop() == 7 + } + + @Ignore + def "push/pop respectively add/remove at the end of the list"() { + DoubleLinkedList list = new DoubleLinkedList<>() + + when: + list.push(11) + list.push(13) + + then: + list.pop() == 13 and: - list.pop() == 10 + list.pop() == 11 } @Ignore - def "Can push and shift"() { - DoubleLinkedList list = new DoubleLinkedList<>() + def "shift gets an element from the list"() { + DoubleLinkedList list = new DoubleLinkedList<>() + + when: + list.push(17) + + then: + list.shift() == 17 + } + + @Ignore + def "shift gets first element from the list"() { + DoubleLinkedList list = new DoubleLinkedList<>() when: - list.push('10') - list.push('20') + list.push(23) + list.push(5) then: - list.shift() == '10' + list.shift() == 23 and: - list.shift() == '20' + list.shift() == 5 } @Ignore - def "Can unshift an shift"() { - DoubleLinkedList list = new DoubleLinkedList<>() + def "unshift adds element at start of the list"() { + DoubleLinkedList list = new DoubleLinkedList<>() when: - list.unshift('1') - list.unshift('2') + list.unshift(23) + list.unshift(5) then: - list.shift() == '2' + list.shift() == 5 and: - list.shift() == '1' + list.shift() == 23 } @Ignore - def "Can unshift and pop"() { + def "pop, push, shift, and unshift can be used in any order"() { DoubleLinkedList list = new DoubleLinkedList<>() + given: + list.push(1) + list.push(2) + def a = list.pop() + list.push(3) + def b = list.shift() + list.unshift(4) + list.push(5) + def c = list.shift() + def d = list.pop() + def e = list.shift() + + expect: + a == 2 + b == 1 + c == 4 + d == 5 + e == 3 + } + + @Ignore + def "count an empty list"() { + DoubleLinkedList list = new DoubleLinkedList<>() + + expect: + list.count() == 0 + } + + @Ignore + def "count a list with items"() { + DoubleLinkedList list = new DoubleLinkedList<>() + when: - list.unshift(10) - list.unshift(20) + list.push('one') + list.push('two') then: - list.pop() == 10 + list.count() == 2 + } + + @Ignore + def "count is correct after mutation"() { + DoubleLinkedList list = new DoubleLinkedList<>() + + given: + list.push(31) + def a = list.count() + list.unshift(43) + def b = list.count() + list.shift() + def c = list.count() + list.pop() + def d = list.count() + + expect: + a == 1 + b == 2 + c == 1 + d == 0 + } + + @Ignore + def "popping to empty doesn't break the list"() { + DoubleLinkedList list = new DoubleLinkedList<>() + + when: + list.push(41) + list.push(59) + list.pop() + list.pop() + list.push(47) + + then: + list.count() == 1 and: - list.pop() == 20 + list.pop() == 47 } @Ignore - def "Complete example"() { - DoubleLinkedList list = new DoubleLinkedList<>() + def "shifting to empty doesn't break the list"() { + DoubleLinkedList list = new DoubleLinkedList<>() + + when: + list.push(41) + list.push(59) + list.shift() + list.shift() + list.push(47) + + then: + list.count() == 1 + + and: + list.pop() == 47 + } + + @Ignore + def "deletes the only element"() { + DoubleLinkedList list = new DoubleLinkedList<>() + + when: + list.push(61) + list.delete(61) + + then: + list.count() == 0 + } + + @Ignore + def "deletes the element with the specified value from the list"() { + DoubleLinkedList list = new DoubleLinkedList<>() when: - list.push('ten') - list.push('twenty') + list.push(71) + list.push(83) + list.push(79) + list.delete(83) then: - list.pop() == 'twenty' + list.count() == 2 + list.pop() == 79 + list.shift() == 71 + } + + @Ignore + def "deletes the element with the specified value from the list, re-assigns tail"() { + DoubleLinkedList list = new DoubleLinkedList<>() when: - list.push('thirty') + list.push(71) + list.push(83) + list.push(79) + list.delete(83) then: - list.shift() == 'ten' + list.count() == 2 + list.pop() == 79 + list.pop() == 71 + } + + @Ignore + def "deletes the element with the specified value from the list, re-assigns head"() { + DoubleLinkedList list = new DoubleLinkedList<>() + + when: + list.push(71) + list.push(83) + list.push(79) + list.delete(83) + + then: + list.count() == 2 + list.shift() == 71 + list.shift() == 79 + } + + @Ignore + def "deletes the first of two elements"() { + DoubleLinkedList list = new DoubleLinkedList<>() + + when: + list.push(97) + list.push(101) + list.delete(97) + + then: + list.count() == 1 + list.pop() == 101 + } + + @Ignore + def "deletes the second of two elements"() { + DoubleLinkedList list = new DoubleLinkedList<>() + + given: + list.push(97) + list.push(101) + list.delete(101) + + expect: + list.count() == 1 + list.pop() == 97 + } + + @Ignore + def "delete does not modify the list if the element is not found"() { + DoubleLinkedList list = new DoubleLinkedList<>() + + when: + list.push(89) + list.delete(103) + + then: + list.count() == 1 + } + + @Ignore + def "deletes only the first occurrence"() { + DoubleLinkedList list = new DoubleLinkedList<>() when: - list.unshift('forty') - list.push('fifty') + list.push(73) + list.push(9) + list.push(9) + list.push(107) + list.delete(9) then: - list.shift() == 'forty' - list.pop() == 'fifty' - list.shift() == 'thirty' + list.count() == 3 + list.pop() == 107 + list.pop() == 9 + list.pop() == 73 } } diff --git a/exercises/practice/luhn/.meta/tests.toml b/exercises/practice/luhn/.meta/tests.toml index 9bb82241..c0be0c4d 100644 --- a/exercises/practice/luhn/.meta/tests.toml +++ b/exercises/practice/luhn/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [792a7082-feb7-48c7-b88b-bbfec160865e] description = "single digit strings can not be valid" @@ -26,6 +33,9 @@ description = "invalid credit card" [20e67fad-2121-43ed-99a8-14b5b856adb9] description = "invalid long number with an even remainder" +[7e7c9fc1-d994-457c-811e-d390d52fba5e] +description = "invalid long number with a remainder divisible by 5" + [ad2a0c5f-84ed-4e5b-95da-6011d6f4f0aa] description = "valid number with an even number of digits" @@ -50,8 +60,17 @@ description = "more than a single zero is valid" [ab56fa80-5de8-4735-8a4a-14dae588663e] description = "input digit 9 is correctly converted to output digit 9" +[b9887ee8-8337-46c5-bc45-3bcab51bc36f] +description = "very long input is valid" + +[8a7c0e24-85ea-4154-9cf1-c2db90eabc08] +description = "valid luhn with an odd number of digits and non zero first digit" + [39a06a5a-5bad-4e0f-b215-b042d46209b1] description = "using ascii value for non-doubled non-digit isn't allowed" [f94cf191-a62f-4868-bc72-7253114aa157] description = "using ascii value for doubled non-digit isn't allowed" + +[8b72ad26-c8be-49a2-b99c-bcc3bf631b33] +description = "non-numeric, non-space char in the middle with a sum that's divisible by 10 isn't allowed" diff --git a/exercises/practice/luhn/src/test/groovy/LuhnSpec.groovy b/exercises/practice/luhn/src/test/groovy/LuhnSpec.groovy index 2eb9cbc2..26e61d1b 100644 --- a/exercises/practice/luhn/src/test/groovy/LuhnSpec.groovy +++ b/exercises/practice/luhn/src/test/groovy/LuhnSpec.groovy @@ -81,6 +81,16 @@ class LuhnSpec extends Specification { '1 2345 6789 1234 5678 9012' || false } + @Ignore + def "Invalid long number with a remainder divisible by 5"() { + expect: + Luhn.valid(value) == expected + + where: + value || expected + '1 2345 6789 1234 5678 9013' || false + } + @Ignore def "Valid number with an even number of digits"() { expect: @@ -161,6 +171,26 @@ class LuhnSpec extends Specification { '091' || true } + @Ignore + def "Very long input is valid"() { + expect: + Luhn.valid(value) == expected + + where: + value || expected + '9999999999 9999999999 9999999999 9999999999' || true + } + + @Ignore + def "Valid luhn with an odd number of digits and non zero first digit"() { + expect: + Luhn.valid(value) == expected + + where: + value || expected + '109' || true + } + @Ignore def "Using ascii value for non-doubled non-digit isn't allowed"() { expect: @@ -181,4 +211,14 @@ class LuhnSpec extends Specification { ':9' || false } -} \ No newline at end of file + @Ignore + def "Non-numeric, non-space char in the middle with a sum that's divisible by 10 isn't allowed"() { + expect: + Luhn.valid(value) == expected + + where: + value || expected + '59%59' || false + } + +} diff --git a/exercises/practice/matching-brackets/.meta/tests.toml b/exercises/practice/matching-brackets/.meta/tests.toml index cc9e471a..35a98a04 100644 --- a/exercises/practice/matching-brackets/.meta/tests.toml +++ b/exercises/practice/matching-brackets/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [81ec11da-38dd-442a-bcf9-3de7754609a5] description = "paired square brackets" @@ -41,12 +48,21 @@ description = "unpaired and nested brackets" [a0205e34-c2ac-49e6-a88a-899508d7d68e] description = "paired and wrong nested brackets" +[1d5c093f-fc84-41fb-8c2a-e052f9581602] +description = "paired and wrong nested brackets but innermost are correct" + [ef47c21b-bcfd-4998-844c-7ad5daad90a8] description = "paired and incomplete brackets" [a4675a40-a8be-4fc2-bc47-2a282ce6edbe] description = "too many closing brackets" +[a345a753-d889-4b7e-99ae-34ac85910d1a] +description = "early unexpected brackets" + +[21f81d61-1608-465a-b850-baa44c5def83] +description = "early mismatched brackets" + [99255f93-261b-4435-a352-02bdecc9bdf2] description = "math expression" diff --git a/exercises/practice/matching-brackets/src/test/groovy/MatchingBracketsSpec.groovy b/exercises/practice/matching-brackets/src/test/groovy/MatchingBracketsSpec.groovy index e1160566..399b2e38 100644 --- a/exercises/practice/matching-brackets/src/test/groovy/MatchingBracketsSpec.groovy +++ b/exercises/practice/matching-brackets/src/test/groovy/MatchingBracketsSpec.groovy @@ -131,6 +131,16 @@ class MatchingBracketsSpec extends Specification { '[({]})' || false } + @Ignore + def "Paired and wrong nested brackets but innermost are correct"() { + expect: + MatchingBrackets.isPaired(value) == expected + + where: + value || expected + '[({}])' || false + } + @Ignore def "Paired and incomplete brackets"() { expect: @@ -151,6 +161,26 @@ class MatchingBracketsSpec extends Specification { '[]]' || false } + @Ignore + def "Early unexpected brackets"() { + expect: + MatchingBrackets.isPaired(value) == expected + + where: + value || expected + ')()' || false + } + + @Ignore + def "Early mismatched brackets"() { + expect: + MatchingBrackets.isPaired(value) == expected + + where: + value || expected + '{)()' || false + } + @Ignore def "Math expression"() { expect: @@ -171,4 +201,4 @@ class MatchingBracketsSpec extends Specification { expected = true } -} \ No newline at end of file +} diff --git a/exercises/practice/pangram/.meta/tests.toml b/exercises/practice/pangram/.meta/tests.toml index 8075c5ba..10b5a335 100644 --- a/exercises/practice/pangram/.meta/tests.toml +++ b/exercises/practice/pangram/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [64f61791-508e-4f5c-83ab-05de042b0149] description = "empty sentence" @@ -31,3 +38,8 @@ description = "mixed case and punctuation" [2577bf54-83c8-402d-a64b-a2c0f7bb213a] description = "case insensitive" +include = false + +[7138e389-83e4-4c6e-8413-1e40a0076951] +description = "a-m and A-M are 26 different characters but not a pangram" +reimplements = "2577bf54-83c8-402d-a64b-a2c0f7bb213a" diff --git a/exercises/practice/pangram/src/test/groovy/PangramSpec.groovy b/exercises/practice/pangram/src/test/groovy/PangramSpec.groovy index 079d3dd2..ba6ab46b 100644 --- a/exercises/practice/pangram/src/test/groovy/PangramSpec.groovy +++ b/exercises/practice/pangram/src/test/groovy/PangramSpec.groovy @@ -92,13 +92,13 @@ class PangramSpec extends Specification { } @Ignore - def "Case insensitive"() { + def "a-m and A-M are 26 different characters but not a pangram"() { expect: Pangram.isPangram(sentence) == expected where: - sentence || expected - 'the quick brown fox jumps over with lazy FX' || false + sentence || expected + 'abcdefghijklm ABCDEFGHIJKLM' || false } -} \ No newline at end of file +} diff --git a/exercises/practice/phone-number/.meta/tests.toml b/exercises/practice/phone-number/.meta/tests.toml index 6365e12c..24dbf07a 100644 --- a/exercises/practice/phone-number/.meta/tests.toml +++ b/exercises/practice/phone-number/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [79666dce-e0f1-46de-95a1-563802913c35] description = "cleans the number" @@ -13,6 +20,11 @@ description = "cleans numbers with multiple spaces" [598d8432-0659-4019-a78b-1c6a73691d21] description = "invalid when 9 digits" +include = false + +[2de74156-f646-42b5-8638-0ef1d8b58bc2] +description = "invalid when 9 digits" +reimplements = "598d8432-0659-4019-a78b-1c6a73691d21" [57061c72-07b5-431f-9766-d97da7c4399d] description = "invalid when 11 digits does not start with a 1" @@ -25,12 +37,27 @@ description = "valid when 11 digits and starting with 1 even with punctuation" [c6a5f007-895a-4fc5-90bc-a7e70f9b5cad] description = "invalid when more than 11 digits" +include = false + +[4a1509b7-8953-4eec-981b-c483358ff531] +description = "invalid when more than 11 digits" +reimplements = "c6a5f007-895a-4fc5-90bc-a7e70f9b5cad" [63f38f37-53f6-4a5f-bd86-e9b404f10a60] description = "invalid with letters" +include = false + +[eb8a1fc0-64e5-46d3-b0c6-33184208e28a] +description = "invalid with letters" +reimplements = "63f38f37-53f6-4a5f-bd86-e9b404f10a60" [4bd97d90-52fd-45d3-b0db-06ab95b1244e] description = "invalid with punctuations" +include = false + +[065f6363-8394-4759-b080-e6c8c351dd1f] +description = "invalid with punctuations" +reimplements = "4bd97d90-52fd-45d3-b0db-06ab95b1244e" [d77d07f8-873c-4b17-8978-5f66139bf7d7] description = "invalid if area code starts with 0" diff --git a/exercises/practice/phone-number/src/test/groovy/PhoneNumberSpec.groovy b/exercises/practice/phone-number/src/test/groovy/PhoneNumberSpec.groovy index 8a717974..9477a1af 100644 --- a/exercises/practice/phone-number/src/test/groovy/PhoneNumberSpec.groovy +++ b/exercises/practice/phone-number/src/test/groovy/PhoneNumberSpec.groovy @@ -95,7 +95,7 @@ class PhoneNumberSpec extends Specification { thrown(Exception) where: - phrase = '123-abc-7890' + phrase = '523-abc-7890' } @Ignore @@ -107,7 +107,7 @@ class PhoneNumberSpec extends Specification { thrown(Exception) where: - phrase = '123-@:!-7890' + phrase = '523-@:!-7890' } @Ignore diff --git a/exercises/practice/pig-latin/.meta/tests.toml b/exercises/practice/pig-latin/.meta/tests.toml index c29168c5..d524305b 100644 --- a/exercises/practice/pig-latin/.meta/tests.toml +++ b/exercises/practice/pig-latin/.meta/tests.toml @@ -39,6 +39,9 @@ description = "first letter and ay are moved to the end of words that start with [bce94a7a-a94e-4e2b-80f4-b2bb02e40f71] description = "first letter and ay are moved to the end of words that start with consonants -> word beginning with q without a following u" +[e59dbbe8-ccee-4619-a8e9-ce017489bfc0] +description = "first letter and ay are moved to the end of words that start with consonants -> word beginning with consonant and vowel containing qu" + [c01e049a-e3e2-451c-bf8e-e2abb7e438b8] description = "some letter clusters are treated like a single consonant -> word beginning with ch" diff --git a/exercises/practice/pig-latin/src/test/groovy/PigLatinSpec.groovy b/exercises/practice/pig-latin/src/test/groovy/PigLatinSpec.groovy index ffd2af54..9e374f41 100644 --- a/exercises/practice/pig-latin/src/test/groovy/PigLatinSpec.groovy +++ b/exercises/practice/pig-latin/src/test/groovy/PigLatinSpec.groovy @@ -24,11 +24,12 @@ class PigLatinSpec extends Specification { PigLatin.translate(phrase) == expected where: - label | phrase || expected - 'word beginning with p' | 'pig' || 'igpay' - 'word beginning with k' | 'koala' || 'oalakay' - 'word beginning with x' | 'xenon' || 'enonxay' - 'word beginning with q without a following u' | 'qat' || 'atqay' + label | phrase || expected + 'word beginning with p' | 'pig' || 'igpay' + 'word beginning with k' | 'koala' || 'oalakay' + 'word beginning with x' | 'xenon' || 'enonxay' + 'word beginning with q without a following u' | 'qat' || 'atqay' + 'word beginning with consonant and vowel containing qu' | 'liquid' || 'iquidlay' } @Unroll diff --git a/exercises/practice/prime-factors/.meta/tests.toml b/exercises/practice/prime-factors/.meta/tests.toml index f3f05a3e..6f9cc8ce 100644 --- a/exercises/practice/prime-factors/.meta/tests.toml +++ b/exercises/practice/prime-factors/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [924fc966-a8f5-4288-82f2-6b9224819ccd] description = "no factors" @@ -8,12 +15,27 @@ description = "no factors" [17e30670-b105-4305-af53-ddde182cb6ad] description = "prime number" +[238d57c8-4c12-42ef-af34-ae4929f94789] +description = "another prime number" + [f59b8350-a180-495a-8fb1-1712fbee1158] description = "square of a prime" +[756949d3-3158-4e3d-91f2-c4f9f043ee70] +description = "product of first prime" + [bc8c113f-9580-4516-8669-c5fc29512ceb] description = "cube of a prime" +[7d6a3300-a4cb-4065-bd33-0ced1de6cb44] +description = "product of second prime" + +[073ac0b2-c915-4362-929d-fc45f7b9a9e4] +description = "product of third prime" + +[6e0e4912-7fb6-47f3-a9ad-dbcd79340c75] +description = "product of first and second prime" + [00485cd3-a3fe-4fbe-a64a-a4308fc1f870] description = "product of primes and non-primes" diff --git a/exercises/practice/prime-factors/src/test/groovy/PrimeFactorsSpec.groovy b/exercises/practice/prime-factors/src/test/groovy/PrimeFactorsSpec.groovy index 265c0432..5e828fdf 100644 --- a/exercises/practice/prime-factors/src/test/groovy/PrimeFactorsSpec.groovy +++ b/exercises/practice/prime-factors/src/test/groovy/PrimeFactorsSpec.groovy @@ -21,6 +21,16 @@ class PrimeFactorsSpec extends Specification { 2 || [2] } + @Ignore + def "Another prime number"() { + expect: + PrimeFactors.factors(value) == expected + + where: + value || expected + 3 || [3] + } + @Ignore def "Square of a prime"() { expect: @@ -31,6 +41,16 @@ class PrimeFactorsSpec extends Specification { 9 || [3, 3] } + @Ignore + def "Product of first prime"() { + expect: + PrimeFactors.factors(value) == expected + + where: + value || expected + 4 || [2, 2] + } + @Ignore def "Cube of a prime"() { expect: @@ -41,6 +61,36 @@ class PrimeFactorsSpec extends Specification { 8 || [2, 2, 2] } + @Ignore + def "Product of second prime"() { + expect: + PrimeFactors.factors(value) == expected + + where: + value || expected + 27 || [3, 3, 3] + } + + @Ignore + def "Product of third prime"() { + expect: + PrimeFactors.factors(value) == expected + + where: + value || expected + 625 || [5, 5, 5, 5] + } + + @Ignore + def "Product of first and second prime"() { + expect: + PrimeFactors.factors(value) == expected + + where: + value || expected + 6 || [2, 3] + } + @Ignore def "Product of primes and non-primes"() { expect: @@ -71,4 +121,4 @@ class PrimeFactorsSpec extends Specification { 93819012551 || [11, 9539, 894119] } -} \ No newline at end of file +} diff --git a/exercises/practice/protein-translation/.meta/config.json b/exercises/practice/protein-translation/.meta/config.json index 2b9e4a6a..09729994 100644 --- a/exercises/practice/protein-translation/.meta/config.json +++ b/exercises/practice/protein-translation/.meta/config.json @@ -2,6 +2,9 @@ "authors": [ "amscotti" ], + "contributors": [ + "glennj" + ], "files": { "solution": [ "src/main/groovy/ProteinTranslation.groovy" diff --git a/exercises/practice/protein-translation/.meta/src/reference/groovy/ProteinTranslation.groovy b/exercises/practice/protein-translation/.meta/src/reference/groovy/ProteinTranslation.groovy index 4d23b7e0..075eef4c 100644 --- a/exercises/practice/protein-translation/.meta/src/reference/groovy/ProteinTranslation.groovy +++ b/exercises/practice/protein-translation/.meta/src/reference/groovy/ProteinTranslation.groovy @@ -1,6 +1,7 @@ class ProteinTranslation { private static final STOP = 'STOP' + private static final INVALID = 'INVALID' private static final PROTEINS = [ 'AUG': 'Methionine', @@ -16,10 +17,21 @@ class ProteinTranslation { 'UAC': 'Tyrosine', 'UGU': 'Cysteine', 'UGC': 'Cysteine', - 'UGG': 'Tryptophan' - ].withDefault { STOP } + 'UGG': 'Tryptophan', + 'UAA': STOP, + 'UAG': STOP, + 'UGA': STOP + ].withDefault { INVALID } static List proteins(String strand) { - strand.split('').collate(3).collect { PROTEINS[it.join()] }.takeWhile { it != STOP } + List result = [] + while (strand != "") { + def protein = PROTEINS[strand.take(3)] + if (protein == INVALID) throw new Exception('Invalid codon') + if (protein == STOP) break + result.add(protein) + strand = strand.drop(3) + } + result } -} \ No newline at end of file +} diff --git a/exercises/practice/protein-translation/.meta/tests.toml b/exercises/practice/protein-translation/.meta/tests.toml index 02a54c34..de680e39 100644 --- a/exercises/practice/protein-translation/.meta/tests.toml +++ b/exercises/practice/protein-translation/.meta/tests.toml @@ -1,6 +1,16 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. + +[2c44f7bf-ba20-43f7-a3bf-f2219c0c3f98] +description = "Empty RNA sequence results in no proteins" [96d3d44f-34a2-4db4-84cd-fff523e069be] description = "Methionine RNA sequence" @@ -53,6 +63,12 @@ description = "STOP codon RNA sequence 2" [9c2ad527-ebc9-4ace-808b-2b6447cb54cb] description = "STOP codon RNA sequence 3" +[f4d9d8ee-00a8-47bf-a1e3-1641d4428e54] +description = "Sequence of two protein codons translates into proteins" + +[dd22eef3-b4f1-4ad6-bb0b-27093c090a9d] +description = "Sequence of two different protein codons translates into proteins" + [d0f295df-fb70-425c-946c-ec2ec185388e] description = "Translate RNA strand into correct protein list" @@ -70,3 +86,20 @@ description = "Translation stops if STOP codon in middle of three-codon sequence [2c2a2a60-401f-4a80-b977-e0715b23b93d] description = "Translation stops if STOP codon in middle of six-codon sequence" + +[f6f92714-769f-4187-9524-e353e8a41a80] +description = "Sequence of two non-STOP codons does not translate to a STOP codon" + +[1e75ea2a-f907-4994-ae5c-118632a1cb0f] +description = "Non-existing codon can't translate" +include = false + +[9eac93f3-627a-4c90-8653-6d0a0595bc6f] +description = "Unknown amino acids, not part of a codon, can't translate" +reimplements = "1e75ea2a-f907-4994-ae5c-118632a1cb0f" + +[9d73899f-e68e-4291-b1e2-7bf87c00f024] +description = "Incomplete RNA sequence can't translate" + +[43945cf7-9968-402d-ab9f-b8a28750b050] +description = "Incomplete RNA sequence can translate if valid until a STOP codon" diff --git a/exercises/practice/protein-translation/src/test/groovy/ProteinTranslationSpec.groovy b/exercises/practice/protein-translation/src/test/groovy/ProteinTranslationSpec.groovy index dfac3245..9e803285 100644 --- a/exercises/practice/protein-translation/src/test/groovy/ProteinTranslationSpec.groovy +++ b/exercises/practice/protein-translation/src/test/groovy/ProteinTranslationSpec.groovy @@ -2,6 +2,16 @@ import spock.lang.* class ProteinTranslationSpec extends Specification { + def "Empty RNA sequence results in no proteins"() { + expect: + ProteinTranslation.proteins(strand) == expected + + where: + strand || expected + '' || [] + } + + @Ignore def "Methionine RNA sequence"() { expect: ProteinTranslation.proteins(strand) == expected @@ -90,6 +100,27 @@ class ProteinTranslationSpec extends Specification { 'UGA' || [] } + @Ignore + def "Sequence of two protein codons translates into proteins"() { + expect: + ProteinTranslation.proteins(strand) == expected + + where: + strand || expected + 'UUUUUU' || ['Phenylalanine', 'Phenylalanine'] + } + + @Ignore + def "Sequence of two different protein codons translates into proteins"() { + expect: + ProteinTranslation.proteins(strand) == expected + + where: + strand || expected + 'UUAUUG' || ['Leucine', 'Leucine'] + } + + @Ignore def "Translate RNA strand into correct protein list"() { expect: @@ -150,4 +181,51 @@ class ProteinTranslationSpec extends Specification { 'UGGUGUUAUUAAUGGUUU' || ['Tryptophan', 'Cysteine', 'Tyrosine'] } -} \ No newline at end of file + @Ignore + def "Sequence of two non-STOP codons does not translate to a STOP codon"() { + expect: + ProteinTranslation.proteins(strand) == expected + + where: + strand || expected + 'AUGAUG' || ['Methionine', 'Methionine'] + } + + @Ignore + def "Non-existing codon can't translate"() { + when: + ProteinTranslation.proteins('AAA') + + then: + thrown(Exception) + } + + @Ignore + def "Unknown amino acids, not part of a codon, can't translate"() { + when: + ProteinTranslation.proteins('XYZ') + + then: + thrown(Exception) + } + + @Ignore + def "Incomplete RNA sequence can't translate"() { + when: + ProteinTranslation.proteins('AUGU') + + then: + thrown(Exception) + } + + @Ignore + def "Incomplete RNA sequence can translate if valid until a STOP codon"() { + expect: + ProteinTranslation.proteins(strand) == expected + + where: + strand || expected + 'UUCUUCUAAUGGU' || ['Phenylalanine', 'Phenylalanine'] + } + +} diff --git a/exercises/practice/resistor-color-duo/.meta/tests.toml b/exercises/practice/resistor-color-duo/.meta/tests.toml index 862b5770..9036fc78 100644 --- a/exercises/practice/resistor-color-duo/.meta/tests.toml +++ b/exercises/practice/resistor-color-duo/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [ce11995a-5b93-4950-a5e9-93423693b2fc] description = "Brown and black" @@ -11,8 +18,14 @@ description = "Blue and grey" [f1886361-fdfd-4693-acf8-46726fe24e0c] description = "Yellow and violet" +[b7a6cbd2-ae3c-470a-93eb-56670b305640] +description = "White and red" + [77a8293d-2a83-4016-b1af-991acc12b9fe] description = "Orange and orange" [0c4fb44f-db7c-4d03-afa8-054350f156a8] description = "Ignore additional colors" + +[4a8ceec5-0ab4-4904-88a4-daf953a5e818] +description = "Black and brown, one-digit" diff --git a/exercises/practice/resistor-color-duo/src/test/groovy/ResistorColorDuoSpec.groovy b/exercises/practice/resistor-color-duo/src/test/groovy/ResistorColorDuoSpec.groovy index 00ef0451..5529fcd8 100644 --- a/exercises/practice/resistor-color-duo/src/test/groovy/ResistorColorDuoSpec.groovy +++ b/exercises/practice/resistor-color-duo/src/test/groovy/ResistorColorDuoSpec.groovy @@ -11,43 +11,19 @@ class ResistorColorDuoSpec extends Specification { ['brown', 'black'] || 10 } + @Unroll @Ignore - def "Blue and grey"() { + def "Resistor Color Duo - #label"() { expect: ResistorColorDuo.value(colors) == expected where: - colors || expected - ['blue', 'grey'] || 68 + label | colors || expected + 'Blue and grey' | ['blue', 'grey'] || 68 + 'Yellow and violet' | ['yellow', 'violet'] || 47 + 'White and red' | ['white', 'red'] || 92 + 'Orange and orange' | ['orange', 'orange'] || 33 + 'Ignore additional colors' | ['green', 'brown', 'orange'] || 51 + 'Black and brown, one digit' | ['black', 'brown'] || 1 } - - @Ignore - def "Yellow and violet"() { - expect: - ResistorColorDuo.value(colors) == expected - - where: - colors || expected - ['yellow', 'violet'] || 47 - } - - @Ignore - def "Orange and orange"() { - expect: - ResistorColorDuo.value(colors) == expected - - where: - colors || expected - ['orange', 'orange'] || 33 - } - - @Ignore - def "Ignore additional colors"() { - expect: - ResistorColorDuo.value(colors) == expected - - where: - colors || expected - ['green', 'brown', 'orange'] || 51 - } -} \ No newline at end of file +} diff --git a/exercises/practice/resistor-color-trio/.meta/config.json b/exercises/practice/resistor-color-trio/.meta/config.json index d8a832ee..46bebd27 100644 --- a/exercises/practice/resistor-color-trio/.meta/config.json +++ b/exercises/practice/resistor-color-trio/.meta/config.json @@ -2,6 +2,9 @@ "authors": [ "amscotti" ], + "contributors": [ + "glennj" + ], "files": { "solution": [ "src/main/groovy/ResistorColorTrio.groovy" diff --git a/exercises/practice/resistor-color-trio/.meta/src/reference/groovy/ResistorColorTrio.groovy b/exercises/practice/resistor-color-trio/.meta/src/reference/groovy/ResistorColorTrio.groovy index 41c8b8e2..384ea8ce 100644 --- a/exercises/practice/resistor-color-trio/.meta/src/reference/groovy/ResistorColorTrio.groovy +++ b/exercises/practice/resistor-color-trio/.meta/src/reference/groovy/ResistorColorTrio.groovy @@ -12,10 +12,21 @@ class ResistorColorTrio { 'white'] static String label(List colorsInput) { - def (tens, ones, zeros) = colorsInput - int value = (colors.indexOf(tens) * 10 + colors.indexOf(ones)) * (10**colors.indexOf(zeros)) + def (tens, ones, zeros) = colorsInput.take(3) + .collect { colors.indexOf(it) } + .collect { BigInteger.valueOf(it) } - value < 1000 ? "${value} ohms" : "${value / 1000} kiloohms" + def value = (10 * tens + ones) * BigInteger.TEN.pow(zeros) + + def idx = 0 + while (value > 0 && value % 1000 == 0) { + idx++ + value /= 1000 + } + + def prefix = ['', 'kilo', 'mega', 'giga'][idx] + + "${value} ${prefix}ohms" } -} \ No newline at end of file +} diff --git a/exercises/practice/resistor-color-trio/.meta/tests.toml b/exercises/practice/resistor-color-trio/.meta/tests.toml index beabab3d..b7d45fa5 100644 --- a/exercises/practice/resistor-color-trio/.meta/tests.toml +++ b/exercises/practice/resistor-color-trio/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [d6863355-15b7-40bb-abe0-bfb1a25512ed] description = "Orange and orange and black" @@ -16,3 +23,18 @@ description = "Green and brown and orange" [f5d37ef9-1919-4719-a90d-a33c5a6934c9] description = "Yellow and violet and yellow" + +[5f6404a7-5bb3-4283-877d-3d39bcc33854] +description = "Blue and violet and blue" + +[7d3a6ab8-e40e-46c3-98b1-91639fff2344] +description = "Minimum possible value" + +[ca0aa0ac-3825-42de-9f07-dac68cc580fd] +description = "Maximum possible value" + +[0061a76c-903a-4714-8ce2-f26ce23b0e09] +description = "First two colors make an invalid octal number" + +[30872c92-f567-4b69-a105-8455611c10c4] +description = "Ignore extra colors" diff --git a/exercises/practice/resistor-color-trio/src/test/groovy/ResistorColorTrioSpec.groovy b/exercises/practice/resistor-color-trio/src/test/groovy/ResistorColorTrioSpec.groovy index 17668c4a..77ade2fc 100644 --- a/exercises/practice/resistor-color-trio/src/test/groovy/ResistorColorTrioSpec.groovy +++ b/exercises/practice/resistor-color-trio/src/test/groovy/ResistorColorTrioSpec.groovy @@ -11,44 +11,41 @@ class ResistorColorTrioSpec extends Specification { ['orange', 'orange', 'black'] || '33 ohms' } + @Unroll @Ignore - def "Blue and grey and brown"() { + def "Resistor Color Trio - #label"() { expect: ResistorColorTrio.label(colors) == expected where: - colors || expected - ['blue', 'grey', 'brown'] || '680 ohms' + label | colors || expected + 'Blue and grey and brown' | ['blue', 'grey', 'brown'] || '680 ohms' + 'Red and black and red' | ['red', 'black', 'red'] || '2 kiloohms' + 'Green and brown and orange' | ['green', 'brown', 'orange'] || '51 kiloohms' + 'Yellow and violet and yellow' | ['yellow', 'violet', 'yellow'] || '470 kiloohms' + 'Blue and violet and blue' | ['blue', 'violet', 'blue'] || '67 megaohms' + 'Minimum possible value' | ['black', 'black', 'black'] || '0 ohms' + 'Maximum possible value' | ['white', 'white', 'white'] || '99 gigaohms' } @Ignore - def "Red and black and red"() { + def "First two colors make an invalid octal number"() { expect: ResistorColorTrio.label(colors) == expected where: - colors || expected - ['red', 'black', 'red'] || '2 kiloohms' + colors || expected + ['black', 'grey', 'black'] || '8 ohms' } @Ignore - def "Green and brown and orange"() { + def "Ignore extra colors"() { expect: ResistorColorTrio.label(colors) == expected where: - colors || expected - ['green', 'brown', 'orange'] || '51 kiloohms' + colors || expected + ['blue', 'green', 'yellow', 'orange'] || '650 kiloohms' } - @Ignore - def "Yellow and violet and yellow"() { - expect: - ResistorColorTrio.label(colors) == expected - - where: - colors || expected - ['yellow', 'violet', 'yellow'] || '470 kiloohms' - } - -} \ No newline at end of file +} diff --git a/exercises/practice/reverse-string/.meta/tests.toml b/exercises/practice/reverse-string/.meta/tests.toml index 2113a533..52fda995 100644 --- a/exercises/practice/reverse-string/.meta/tests.toml +++ b/exercises/practice/reverse-string/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [c3b7d806-dced-49ee-8543-933fd1719b1c] description = "an empty string" @@ -19,3 +26,15 @@ description = "a palindrome" [b9e7dec1-c6df-40bd-9fa3-cd7ded010c4c] description = "an even-sized word" + +[1bed0f8a-13b0-4bd3-9d59-3d0593326fa2] +description = "wide characters" +include = false + +[93d7e1b8-f60f-4f3c-9559-4056e10d2ead] +description = "grapheme cluster with pre-combined form" +include = false + +[1028b2c1-6763-4459-8540-2da47ca512d9] +description = "grapheme clusters" +include = false diff --git a/exercises/practice/reverse-string/src/test/groovy/ReverseStringSpec.groovy b/exercises/practice/reverse-string/src/test/groovy/ReverseStringSpec.groovy index f2e320c2..8b296ed7 100644 --- a/exercises/practice/reverse-string/src/test/groovy/ReverseStringSpec.groovy +++ b/exercises/practice/reverse-string/src/test/groovy/ReverseStringSpec.groovy @@ -60,4 +60,4 @@ class ReverseStringSpec extends Specification { value || expected 'drawer' || 'reward' } -} \ No newline at end of file +} diff --git a/exercises/practice/roman-numerals/.meta/tests.toml b/exercises/practice/roman-numerals/.meta/tests.toml index 57c6c4be..709011b5 100644 --- a/exercises/practice/roman-numerals/.meta/tests.toml +++ b/exercises/practice/roman-numerals/.meta/tests.toml @@ -84,5 +84,8 @@ description = "3000 is MMM" [3bc4b41c-c2e6-49d9-9142-420691504336] description = "3001 is MMMI" +[2f89cad7-73f6-4d1b-857b-0ef531f68b7e] +description = "3888 is MMMDCCCLXXXVIII" + [4e18e96b-5fbb-43df-a91b-9cb511fe0856] description = "3999 is MMMCMXCIX" diff --git a/exercises/practice/roman-numerals/src/test/groovy/RomanNumeralsSpec.groovy b/exercises/practice/roman-numerals/src/test/groovy/RomanNumeralsSpec.groovy index 8075245c..164f3961 100644 --- a/exercises/practice/roman-numerals/src/test/groovy/RomanNumeralsSpec.groovy +++ b/exercises/practice/roman-numerals/src/test/groovy/RomanNumeralsSpec.groovy @@ -37,6 +37,7 @@ class RomanNumeralsSpec extends Specification { 1666 || 'MDCLXVI' 3000 || 'MMM' 3001 || 'MMMI' + 3888 || 'MMMDCCCLXXXVIII' 3999 || 'MMMCMXCIX' } diff --git a/exercises/practice/series/.meta/tests.toml b/exercises/practice/series/.meta/tests.toml index 52ff7ed5..9696f51f 100644 --- a/exercises/practice/series/.meta/tests.toml +++ b/exercises/practice/series/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [7ae7a46a-d992-4c2a-9c15-a112d125ebad] description = "slices of one from one" @@ -23,6 +30,9 @@ description = "slices of a long series" [6d235d85-46cf-4fae-9955-14b6efef27cd] description = "slice length is too large" +[d7957455-346d-4e47-8e4b-87ed1564c6d7] +description = "slice length is way too large" + [d34004ad-8765-4c09-8ba1-ada8ce776806] description = "slice length cannot be zero" diff --git a/exercises/practice/series/src/test/groovy/SeriesSpec.groovy b/exercises/practice/series/src/test/groovy/SeriesSpec.groovy index ef79879b..4e31e496 100644 --- a/exercises/practice/series/src/test/groovy/SeriesSpec.groovy +++ b/exercises/practice/series/src/test/groovy/SeriesSpec.groovy @@ -72,6 +72,15 @@ class SeriesSpec extends Specification { thrown(ArithmeticException) } + @Ignore + def "Slice length is way too large"() { + when: + Series.slices('12345', 42) + + then: + thrown(ArithmeticException) + } + @Ignore def "Slice length cannot be zero"() { when: @@ -98,4 +107,4 @@ class SeriesSpec extends Specification { then: thrown(ArithmeticException) } -} \ No newline at end of file +} diff --git a/exercises/practice/space-age/.meta/tests.toml b/exercises/practice/space-age/.meta/tests.toml index b4a221dc..7957bb77 100644 --- a/exercises/practice/space-age/.meta/tests.toml +++ b/exercises/practice/space-age/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [84f609af-5a91-4d68-90a3-9e32d8a5cd34] description = "age on Earth" @@ -25,3 +32,6 @@ description = "age on Uranus" [80096d30-a0d4-4449-903e-a381178355d8] description = "age on Neptune" + +[57b96e2a-1178-40b7-b34d-f3c9c34e4bf4] +description = "invalid planet causes error" diff --git a/exercises/practice/space-age/src/test/groovy/SpaceAgeSpec.groovy b/exercises/practice/space-age/src/test/groovy/SpaceAgeSpec.groovy index 8f83474d..c6424560 100644 --- a/exercises/practice/space-age/src/test/groovy/SpaceAgeSpec.groovy +++ b/exercises/practice/space-age/src/test/groovy/SpaceAgeSpec.groovy @@ -81,4 +81,13 @@ class SpaceAgeSpec extends Specification { 'Neptune' | 1821023456 || 0.35 } -} \ No newline at end of file + @Ignore + def "Invalid planet causes error"() { + when: + SpaceAge.age('Sun', 680804807) + + then: + thrown(Exception) + } + +} diff --git a/exercises/practice/triangle/.meta/tests.toml b/exercises/practice/triangle/.meta/tests.toml index 59107059..7db09164 100644 --- a/exercises/practice/triangle/.meta/tests.toml +++ b/exercises/practice/triangle/.meta/tests.toml @@ -1,60 +1,73 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [8b2c43ac-7257-43f9-b552-7631a91988af] -description = "all sides are equal" +description = "equilateral triangle -> all sides are equal" [33eb6f87-0498-4ccf-9573-7f8c3ce92b7b] -description = "any side is unequal" +description = "equilateral triangle -> any side is unequal" [c6585b7d-a8c0-4ad8-8a34-e21d36f7ad87] -description = "no sides are equal" +description = "equilateral triangle -> no sides are equal" [16e8ceb0-eadb-46d1-b892-c50327479251] -description = "all zero sides is not a triangle" +description = "equilateral triangle -> all zero sides is not a triangle" [3022f537-b8e5-4cc1-8f12-fd775827a00c] -description = "sides may be floats" +description = "equilateral triangle -> sides may be floats" [cbc612dc-d75a-4c1c-87fc-e2d5edd70b71] -description = "last two sides are equal" +description = "isosceles triangle -> last two sides are equal" [e388ce93-f25e-4daf-b977-4b7ede992217] -description = "first two sides are equal" +description = "isosceles triangle -> first two sides are equal" [d2080b79-4523-4c3f-9d42-2da6e81ab30f] -description = "first and last sides are equal" +description = "isosceles triangle -> first and last sides are equal" [8d71e185-2bd7-4841-b7e1-71689a5491d8] -description = "equilateral triangles are also isosceles" +description = "isosceles triangle -> equilateral triangles are also isosceles" [840ed5f8-366f-43c5-ac69-8f05e6f10bbb] -description = "no sides are equal" +description = "isosceles triangle -> no sides are equal" [2eba0cfb-6c65-4c40-8146-30b608905eae] -description = "first triangle inequality violation" +description = "isosceles triangle -> first triangle inequality violation" [278469cb-ac6b-41f0-81d4-66d9b828f8ac] -description = "second triangle inequality violation" +description = "isosceles triangle -> second triangle inequality violation" [90efb0c7-72bb-4514-b320-3a3892e278ff] -description = "third triangle inequality violation" +description = "isosceles triangle -> third triangle inequality violation" [adb4ee20-532f-43dc-8d31-e9271b7ef2bc] -description = "sides may be floats" +description = "isosceles triangle -> sides may be floats" [e8b5f09c-ec2e-47c1-abec-f35095733afb] -description = "no sides are equal" +description = "scalene triangle -> no sides are equal" [2510001f-b44d-4d18-9872-2303e7977dc1] -description = "all sides are equal" +description = "scalene triangle -> all sides are equal" [c6e15a92-90d9-4fb3-90a2-eef64f8d3e1e] -description = "two sides are equal" +description = "scalene triangle -> first and second sides are equal" + +[3da23a91-a166-419a-9abf-baf4868fd985] +description = "scalene triangle -> first and third sides are equal" + +[b6a75d98-1fef-4c42-8e9a-9db854ba0a4d] +description = "scalene triangle -> second and third sides are equal" [70ad5154-0033-48b7-af2c-b8d739cd9fdc] -description = "may not violate triangle inequality" +description = "scalene triangle -> may not violate triangle inequality" [26d9d59d-f8f1-40d3-ad58-ae4d54123d7d] -description = "sides may be floats" +description = "scalene triangle -> sides may be floats" diff --git a/exercises/practice/triangle/src/test/groovy/TriangleSpec.groovy b/exercises/practice/triangle/src/test/groovy/TriangleSpec.groovy index c8e81672..4e7225a0 100644 --- a/exercises/practice/triangle/src/test/groovy/TriangleSpec.groovy +++ b/exercises/practice/triangle/src/test/groovy/TriangleSpec.groovy @@ -162,7 +162,7 @@ class TriangleSpec extends Specification { } @Ignore - def "Two sides are equal"() { + def "First and second sides are equal"() { expect: new Triangle(a, b, c).isScalene() == expected @@ -171,6 +171,26 @@ class TriangleSpec extends Specification { 4 | 4 | 3 || false } + @Ignore + def "First and third sides are equal"() { + expect: + new Triangle(a, b, c).isScalene() == expected + + where: + a | b | c || expected + 3 | 4 | 3 || false + } + + @Ignore + def "Second and thirdsides are equal"() { + expect: + new Triangle(a, b, c).isScalene() == expected + + where: + a | b | c || expected + 4 | 3 | 3 || false + } + @Ignore def "May not violate triangle inequality"() { expect: diff --git a/exercises/practice/word-count/.meta/tests.toml b/exercises/practice/word-count/.meta/tests.toml index b00c20ae..1be425b3 100644 --- a/exercises/practice/word-count/.meta/tests.toml +++ b/exercises/practice/word-count/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [61559d5f-2cad-48fb-af53-d3973a9ee9ef] description = "count one word" @@ -28,6 +35,11 @@ description = "normalize case" [4185a902-bdb0-4074-864c-f416e42a0f19] description = "with apostrophes" +include = false + +[4ff6c7d7-fcfc-43ef-b8e7-34ff1837a2d3] +description = "with apostrophes" +reimplements = "4185a902-bdb0-4074-864c-f416e42a0f19" [be72af2b-8afe-4337-b151-b297202e4a7b] description = "with quotations" @@ -40,3 +52,6 @@ description = "multiple spaces not detected as a word" [50176e8a-fe8e-4f4c-b6b6-aa9cf8f20360] description = "alternating word separators not detected as a word" + +[6d00f1db-901c-4bec-9829-d20eb3044557] +description = "quotation for word with apostrophe" diff --git a/exercises/practice/word-count/src/test/groovy/WordCountSpec.groovy b/exercises/practice/word-count/src/test/groovy/WordCountSpec.groovy index d47787ee..d8e232e0 100644 --- a/exercises/practice/word-count/src/test/groovy/WordCountSpec.groovy +++ b/exercises/practice/word-count/src/test/groovy/WordCountSpec.groovy @@ -88,7 +88,9 @@ class WordCountSpec extends Specification { where: sentence || expected - "First: don't laugh. Then: don't cry." || ['first': 1, "don't": 2, 'laugh': 1, 'then': 1, 'cry': 1] + "'First: don't laugh. Then: don't cry. You're getting it.'" || ["first": 1, "don't": 2, "laugh": 1, + "then": 1, "cry": 1, "you're": 1, + "getting": 1, "it": 1] } @Ignore @@ -132,4 +134,14 @@ class WordCountSpec extends Specification { sentence || expected ",\n,one,\n ,two \n 'three'" || ['one': 1, 'two': 1, 'three': 1] } -} \ No newline at end of file + + @Ignore + def "Quotation for word with apostrophe"() { + expect: + new WordCount(sentence).countWords() == expected + + where: + sentence || expected + "can, can't, 'can't'" || ['can': 1, "can't": 2] + } +}