diff --git a/.github/workflows/no-important-files-changed.yml b/.github/workflows/no-important-files-changed.yml index b940c59..812e912 100644 --- a/.github/workflows/no-important-files-changed.yml +++ b/.github/workflows/no-important-files-changed.yml @@ -16,7 +16,7 @@ permissions: pull-requests: write jobs: - pause: + check: uses: exercism/github-actions/.github/workflows/check-no-important-files-changed.yml@main with: repository: ${{ github.event.pull_request.head.repo.owner.login }}/${{ github.event.pull_request.head.repo.name }} diff --git a/config.json b/config.json index 3a49806..c3f8e73 100644 --- a/config.json +++ b/config.json @@ -217,6 +217,22 @@ "practices": [], "prerequisites": [], "difficulty": 10 + }, + { + "slug": "pangram", + "name": "Pangram", + "uuid": "f9a36482-c18f-4013-bfce-a559ad4c2f79", + "practices": [], + "prerequisites": [], + "difficulty": 1 + }, + { + "slug": "anagram", + "name": "Anagram", + "uuid": "b2d3f839-29fe-4659-94bf-5b14ad39d1bd", + "practices": [], + "prerequisites": [], + "difficulty": 3 } ] }, diff --git a/exercises/practice/anagram/.docs/instructions.md b/exercises/practice/anagram/.docs/instructions.md new file mode 100644 index 0000000..7d1c828 --- /dev/null +++ b/exercises/practice/anagram/.docs/instructions.md @@ -0,0 +1,13 @@ +# Instructions + +An anagram is a rearrangement of letters to form a new word: for example `"owns"` is an anagram of `"snow"`. +A word is not its own anagram: for example, `"stop"` is not an anagram of `"stop"`. + +Given a target word and a set of candidate words, this exercise requests the anagram set: the subset of the candidates that are anagrams of the target. + +The target and candidates are words of one or more ASCII alphabetic characters (`A`-`Z` and `a`-`z`). +Lowercase and uppercase characters are equivalent: for example, `"PoTS"` is an anagram of `"sTOp"`, but `StoP` is not an anagram of `sTOp`. +The anagram set is the subset of the candidate set that are anagrams of the target (in any order). +Words in the anagram set should have the same letter case as in the candidate set. + +Given the target `"stone"` and candidates `"stone"`, `"tones"`, `"banana"`, `"tons"`, `"notes"`, `"Seton"`, the anagram set is `"tones"`, `"notes"`, `"Seton"`. diff --git a/exercises/practice/anagram/.meta/config.json b/exercises/practice/anagram/.meta/config.json new file mode 100644 index 0000000..0c303c4 --- /dev/null +++ b/exercises/practice/anagram/.meta/config.json @@ -0,0 +1,18 @@ +{ + "authors": ["lucaferranti"], + "contributors": ["kytrinyx"], + "files": { + "solution": [ + "src/anagram.chpl" + ], + "test": [ + "test/tests.chpl" + ], + "example": [ + ".meta/reference.chpl" + ] + }, + "blurb": "Given a word and a list of possible anagrams, select the correct sublist.", + "source": "Inspired by the Extreme Startup game", + "source_url": "https://github.com/rchatley/extreme_startup" +} diff --git a/exercises/practice/anagram/.meta/reference.chpl b/exercises/practice/anagram/.meta/reference.chpl new file mode 100644 index 0000000..39753a1 --- /dev/null +++ b/exercises/practice/anagram/.meta/reference.chpl @@ -0,0 +1,16 @@ +module Anagram { + + use Sort; + + proc normaliseString(s: string) { + var v = [c in s] c.toLower(); + sort(v); + return "".join(v); + } + + proc findAnagrams(s: string, candidates: [] string) { + const normalised = normaliseString(s); + return [c in candidates] if c.toLower() != s.toLower() && normaliseString(c) == normalised then c; + } + +} diff --git a/exercises/practice/anagram/.meta/tests.toml b/exercises/practice/anagram/.meta/tests.toml new file mode 100644 index 0000000..4d90562 --- /dev/null +++ b/exercises/practice/anagram/.meta/tests.toml @@ -0,0 +1,86 @@ +# 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" + +[64cd4584-fc15-4781-b633-3d814c4941a4] +description = "detects anagram" + +[99c91beb-838f-4ccd-b123-935139917283] +description = "detects three anagrams" + +[78487770-e258-4e1f-a646-8ece10950d90] +description = "detects multiple anagrams with different case" + +[1d0ab8aa-362f-49b7-9902-3d0c668d557b] +description = "does not detect non-anagrams with identical checksum" + +[9e632c0b-c0b1-4804-8cc1-e295dea6d8a8] +description = "detects anagrams case-insensitively" + +[b248e49f-0905-48d2-9c8d-bd02d8c3e392] +description = "detects anagrams using case-insensitive subject" + +[f367325c-78ec-411c-be76-e79047f4bd54] +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/Mason.toml b/exercises/practice/anagram/Mason.toml new file mode 100644 index 0000000..7da06a2 --- /dev/null +++ b/exercises/practice/anagram/Mason.toml @@ -0,0 +1,5 @@ +[brick] +name="anagram" +version="0.1.0" +chplVersion="1.33.0" +type="application" diff --git a/exercises/practice/anagram/src/anagram.chpl b/exercises/practice/anagram/src/anagram.chpl new file mode 100644 index 0000000..0f7b1c9 --- /dev/null +++ b/exercises/practice/anagram/src/anagram.chpl @@ -0,0 +1,3 @@ +module Anagram { + // Write your solution here. +} diff --git a/exercises/practice/anagram/test/tests.chpl b/exercises/practice/anagram/test/tests.chpl new file mode 100644 index 0000000..3d02618 --- /dev/null +++ b/exercises/practice/anagram/test/tests.chpl @@ -0,0 +1,74 @@ +use UnitTest; + +use Anagram; + +proc testNoMatches(test : borrowed Test) throws { + var anagrams = findAnagrams("diaper", ["hello", "world", "zombies", "pants"]); + test.assertTrue(anagrams.isEmpty()); +} + +proc testDetectsTwoAnagrams(test : borrowed Test) throws { + var anagrams = findAnagrams("solemn", ["lemons", "cherry", "melons"]); + test.assertEqual(anagrams, ["lemons", "melons"]); +} + +proc testDoesNotDetectAnagramSubsets(test : borrowed Test) throws { + var anagrams = findAnagrams("good", ["dog", "goody"]); + test.assertTrue(anagrams.isEmpty()); +} + +proc testDetectsAnagram(test : borrowed Test) throws { + var anagrams = findAnagrams("listen", ["enlists", "google", "inlets", "banana"]); + test.assertEqual(anagrams, ["inlets"]); +} + +proc testDetectsThreeAnagrams(test : borrowed Test) throws { + var anagrams = findAnagrams("allergy", ["gallery", "ballerina", "regally", "clergy", "largely", "leading"]); + test.assertEqual(anagrams, ["gallery", "regally", "largely"]); +} +proc testDetectsMultipleAnagramsWithDifferentCase(test : borrowed Test) throws { + var anagrams = findAnagrams("nose", ["Eons", "ONES"]); + test.assertEqual(anagrams, ["Eons", "ONES"]); +} +proc testDoesNotDetectNonAnagramsWithIdenticalChecksum(test : borrowed Test) throws { + var anagrams = findAnagrams("mass", ["last"]); + test.assertTrue(anagrams.isEmpty()); +} +proc testDetectsAnagramsCaseInsensitively(test : borrowed Test) throws { + var anagrams = findAnagrams("Orchestra", ["cashregister", "Carthorse", "radishes"]); + test.assertEqual(anagrams, ["Carthorse"]); +} +proc testDetectsAnagramsUsingCaseInsensitiveSubject(test : borrowed Test) throws { + var anagrams = findAnagrams("Orchestra", ["cashregister", "carthorse", "radishes"]); + test.assertEqual(anagrams, ["carthorse"]); +} +proc testDetectsAnagramsUsingCaseInsensitivePossibleMatches(test : borrowed Test) throws { + var anagrams = findAnagrams("orchestra", ["cashregister", "Carthorse", "radishes"]); + test.assertEqual(anagrams, ["Carthorse"]); +} +proc testDoesNotDetectAnAnagramIfTheOriginalWordIsRepeated(test : borrowed Test) throws { + var anagrams = findAnagrams("go", ["go Go GO"]); + test.assertTrue(anagrams.isEmpty()); +} +proc testAnagramsMustUseAllLettersExactlyOnce(test : borrowed Test) throws { + var anagrams = findAnagrams("tapper", ["patter"]); + test.assertTrue(anagrams.isEmpty()); +} +proc testWordsAreNotAnagramsOfThemselves(test : borrowed Test) throws { + var anagrams = findAnagrams("BANANA", ["BANANA"]); + test.assertTrue(anagrams.isEmpty()); +} +proc testWordsAreNotAnagramsOfThemselvesEvenIfLetterCaseIsPartiallyDifferent(test : borrowed Test) throws { + var anagrams = findAnagrams("BANANA", ["Banana"]); + test.assertTrue(anagrams.isEmpty()); +} +proc testWordsAreNotAnagramsOfThemselvesEvenIfLetterCaseIsCompletelyDifferent(test : borrowed Test) throws { + var anagrams = findAnagrams("BANANA", ["banana"]); + test.assertTrue(anagrams.isEmpty()); +} +proc testWordsOtherThanThemselvesCanBeAnagrams(test : borrowed Test) throws { + var anagrams = findAnagrams("LISTEN", ["LISTEN", "Silent"]); + test.assertEqual(anagrams, ["Silent"]); +} + +UnitTest.main(); diff --git a/exercises/practice/pangram/.docs/instructions.md b/exercises/practice/pangram/.docs/instructions.md new file mode 100644 index 0000000..817c872 --- /dev/null +++ b/exercises/practice/pangram/.docs/instructions.md @@ -0,0 +1,8 @@ +# Instructions + +Your task is to figure out if a sentence is a pangram. + +A pangram is a sentence using every letter of the alphabet at least once. +It is case insensitive, so it doesn't matter if a letter is lower-case (e.g. `k`) or upper-case (e.g. `K`). + +For this exercise, a sentence is a pangram if it contains each of the 26 letters in the English alphabet. diff --git a/exercises/practice/pangram/.docs/introduction.md b/exercises/practice/pangram/.docs/introduction.md new file mode 100644 index 0000000..32b6f1f --- /dev/null +++ b/exercises/practice/pangram/.docs/introduction.md @@ -0,0 +1,16 @@ +# Introduction + +You work for a company that sells fonts through their website. +They'd like to show a different sentence each time someone views a font on their website. +To give a comprehensive sense of the font, the random sentences should use **all** the letters in the English alphabet. + +They're running a competition to get suggestions for sentences that they can use. +You're in charge of checking the submissions to see if they are valid. + +~~~~exercism/note +Pangram comes from Greek, παν γράμμα, pan gramma, which means "every letter". + +The best known English pangram is: + +> The quick brown fox jumps over the lazy dog. +~~~~ diff --git a/exercises/practice/pangram/.meta/config.json b/exercises/practice/pangram/.meta/config.json new file mode 100644 index 0000000..d2cadcb --- /dev/null +++ b/exercises/practice/pangram/.meta/config.json @@ -0,0 +1,18 @@ +{ + "authors": ["lucaferranti"], + "contributors": ["kytrinyx"], + "files": { + "solution": [ + "src/pangram.chpl" + ], + "test": [ + "test/tests.chpl" + ], + "example": [ + ".meta/reference.chpl" + ] + }, + "blurb": "Determine if a sentence is a pangram.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Pangram" +} diff --git a/exercises/practice/pangram/.meta/reference.chpl b/exercises/practice/pangram/.meta/reference.chpl new file mode 100644 index 0000000..691be36 --- /dev/null +++ b/exercises/practice/pangram/.meta/reference.chpl @@ -0,0 +1,8 @@ +module Pangram { + const ALPHABET = "abcdefghijklmnopqrstuvwxyz"; + + proc isPangram(sentence: string): bool { + var low_sentence = sentence.toLower(); + return && reduce [letter in ALPHABET] low_sentence.find(letter) >= 0; + } +} diff --git a/exercises/practice/pangram/.meta/tests.toml b/exercises/practice/pangram/.meta/tests.toml new file mode 100644 index 0000000..10b5a33 --- /dev/null +++ b/exercises/practice/pangram/.meta/tests.toml @@ -0,0 +1,45 @@ +# 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" + +[74858f80-4a4d-478b-8a5e-c6477e4e4e84] +description = "perfect lower case" + +[61288860-35ca-4abe-ba08-f5df76ecbdcd] +description = "only lower case" + +[6564267d-8ac5-4d29-baf2-e7d2e304a743] +description = "missing the letter 'x'" + +[c79af1be-d715-4cdb-a5f2-b2fa3e7e0de0] +description = "missing the letter 'h'" + +[d835ec38-bc8f-48e4-9e36-eb232427b1df] +description = "with underscores" + +[8cc1e080-a178-4494-b4b3-06982c9be2a8] +description = "with numbers" + +[bed96b1c-ff95-45b8-9731-fdbdcb6ede9a] +description = "missing letters replaced by numbers" + +[938bd5d8-ade5-40e2-a2d9-55a338a01030] +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/Mason.toml b/exercises/practice/pangram/Mason.toml new file mode 100644 index 0000000..ae78f7d --- /dev/null +++ b/exercises/practice/pangram/Mason.toml @@ -0,0 +1,5 @@ +[brick] +name="pangram" +version="0.1.0" +chplVersion="1.33.0" +type="application" diff --git a/exercises/practice/pangram/src/pangram.chpl b/exercises/practice/pangram/src/pangram.chpl new file mode 100644 index 0000000..b656419 --- /dev/null +++ b/exercises/practice/pangram/src/pangram.chpl @@ -0,0 +1,3 @@ +module Pangram { + // Write your solution here +} diff --git a/exercises/practice/pangram/test/tests.chpl b/exercises/practice/pangram/test/tests.chpl new file mode 100644 index 0000000..045c688 --- /dev/null +++ b/exercises/practice/pangram/test/tests.chpl @@ -0,0 +1,45 @@ +use UnitTest; + +use Pangram; + +proc testEmptySentence(test : borrowed Test) throws { + test.assertFalse(isPangram("")); +} + +proc testPerfectLowerCase(test : borrowed Test) throws { + test.assertTrue(isPangram("abcdefghijklmnopqrstuvwxyz")); +} + +proc testOnlyLowerCase(test : borrowed Test) throws { + test.assertTrue(isPangram("the quick brown fox jumps over the lazy dog")); +} + +proc testMissingTheLetterX(test : borrowed Test) throws { + test.assertFalse(isPangram("a quick movement of the enemy will jeopardize five gunboats")); +} + +proc testMissingTheLetterH(test : borrowed Test) throws { + test.assertFalse(isPangram("five boxing wizards jump quickly at it")); +} + +proc testWithUnderscores(test : borrowed Test) throws { + test.assertTrue(isPangram("the_quick_brown_fox_jumps_over_the_lazy_dog")); +} + +proc testWithNumbers(test : borrowed Test) throws { + test.assertTrue(isPangram("the 1 quick brown fox jumps over the 2 lazy dogs")); +} + +proc testMissingLettersReplacedByNumbers(test : borrowed Test) throws { + test.assertFalse(isPangram("7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog")); +} + +proc testMixedCaseAndPunctuation(test : borrowed Test) throws { + test.assertTrue(isPangram("\"Five quacking Zephyrs jolt my wax bed.\"")); +} + +proc testAMAndAMAre26DifferentCharactersButNotAPangram(test : borrowed Test) throws { + test.assertFalse(isPangram("abcdefghijklm ABCDEFGHIJKLM")); +} + +UnitTest.main(); diff --git a/exercises/practice/yacht/.docs/instructions.md b/exercises/practice/yacht/.docs/instructions.md index 163ba37..519b7a6 100644 --- a/exercises/practice/yacht/.docs/instructions.md +++ b/exercises/practice/yacht/.docs/instructions.md @@ -1,35 +1,30 @@ # Instructions -The dice game [Yacht][yacht] is from the same family as Poker Dice, Generala and particularly Yahtzee, of which it is a precursor. -In the game, five dice are rolled and the result can be entered in any of twelve categories. -The score of a throw of the dice depends on category chosen. +Given five dice and a category, calculate the score of the dice for that category. -## Scores in Yacht - -| Category | Score | Description | Example | -| -------- | ----- | ----------- | ------- | -| Ones | 1 × number of ones | Any combination | 1 1 1 4 5 scores 3 | -| Twos | 2 × number of twos | Any combination | 2 2 3 4 5 scores 4 | -| Threes | 3 × number of threes | Any combination | 3 3 3 3 3 scores 15 | -| Fours | 4 × number of fours | Any combination | 1 2 3 3 5 scores 0 | -| Fives | 5 × number of fives| Any combination | 5 1 5 2 5 scores 15 | -| Sixes | 6 × number of sixes | Any combination | 2 3 4 5 6 scores 6 | -| Full House | Total of the dice | Three of one number and two of another | 3 3 3 5 5 scores 19 | -| Four of a Kind | Total of the four dice | At least four dice showing the same face | 4 4 4 4 6 scores 16 | -| Little Straight | 30 points | 1-2-3-4-5 | 1 2 3 4 5 scores 30 | -| Big Straight | 30 points | 2-3-4-5-6 | 2 3 4 5 6 scores 30 | -| Choice | Sum of the dice | Any combination | 2 3 3 4 6 scores 18 | -| Yacht | 50 points | All five dice showing the same face | 4 4 4 4 4 scores 50 | +~~~~exercism/note +You'll always be presented with five dice. +Each dice's value will be between one and six inclusively. +The dice may be unordered. +~~~~ -If the dice do not satisfy the requirements of a category, the score is zero. -If, for example, *Four Of A Kind* is entered in the *Yacht* category, zero points are scored. -A *Yacht* scores zero if entered in the *Full House* category. - -## Task +## Scores in Yacht -Given a list of values for five dice and a category, your solution should return the score of the dice for that category. -If the dice do not satisfy the requirements of the category your solution should return 0. -You can assume that five values will always be presented, and the value of each will be between one and six inclusively. -You should not assume that the dice are ordered. +| Category | Score | Description | Example | +| --------------- | ---------------------- | ---------------------------------------- | ------------------- | +| Ones | 1 × number of ones | Any combination | 1 1 1 4 5 scores 3 | +| Twos | 2 × number of twos | Any combination | 2 2 3 4 5 scores 4 | +| Threes | 3 × number of threes | Any combination | 3 3 3 3 3 scores 15 | +| Fours | 4 × number of fours | Any combination | 1 2 3 3 5 scores 0 | +| Fives | 5 × number of fives | Any combination | 5 1 5 2 5 scores 15 | +| Sixes | 6 × number of sixes | Any combination | 2 3 4 5 6 scores 6 | +| Full House | Total of the dice | Three of one number and two of another | 3 3 3 5 5 scores 19 | +| Four of a Kind | Total of the four dice | At least four dice showing the same face | 4 4 4 4 6 scores 16 | +| Little Straight | 30 points | 1-2-3-4-5 | 1 2 3 4 5 scores 30 | +| Big Straight | 30 points | 2-3-4-5-6 | 2 3 4 5 6 scores 30 | +| Choice | Sum of the dice | Any combination | 2 3 3 4 6 scores 18 | +| Yacht | 50 points | All five dice showing the same face | 4 4 4 4 4 scores 50 | -[yacht]: https://en.wikipedia.org/wiki/Yacht_(dice_game) +If the dice do **not** satisfy the requirements of a category, the score is zero. +If, for example, _Four Of A Kind_ is entered in the _Yacht_ category, zero points are scored. +A _Yacht_ scores zero if entered in the _Full House_ category. diff --git a/exercises/practice/yacht/.docs/introduction.md b/exercises/practice/yacht/.docs/introduction.md new file mode 100644 index 0000000..5b541f5 --- /dev/null +++ b/exercises/practice/yacht/.docs/introduction.md @@ -0,0 +1,11 @@ +# Introduction + +Each year, something new is "all the rage" in your high school. +This year it is a dice game: [Yacht][yacht]. + +The game of Yacht is from the same family as Poker Dice, Generala and particularly Yahtzee, of which it is a precursor. +The game consists of twelve rounds. +In each, five dice are rolled and the player chooses one of twelve categories. +The chosen category is then used to score the throw of the dice. + +[yacht]: https://en.wikipedia.org/wiki/Yacht_(dice_game)