From 321825828ac918bad28d0597a8616c6dc9802c3c Mon Sep 17 00:00:00 2001 From: Andinus Date: Wed, 11 Aug 2021 15:26:15 +0530 Subject: Add solved exercises --- raku/anagram/Anagram.rakumod | 8 + raku/anagram/README.md | 31 ++ raku/anagram/anagram.rakutest | 223 ++++++++ raku/bob/Bob.rakumod | 15 + raku/bob/README.md | 39 ++ raku/bob/bob.rakutest | 226 +++++++++ raku/clock/Clock.rakumod | 27 + raku/clock/README.md | 30 ++ raku/clock/clock.rakutest | 642 ++++++++++++++++++++++++ raku/hamming/Hamming.rakumod | 12 + raku/hamming/README.md | 47 ++ raku/hamming/hamming.rakutest | 122 +++++ raku/hello-world/HelloWorld.rakumod | 5 + raku/hello-world/README.md | 38 ++ raku/hello-world/hello-world.rakutest | 12 + raku/leap/Leap.rakumod | 5 + raku/leap/README.md | 47 ++ raku/leap/leap.rakutest | 99 ++++ raku/luhn/Luhn.rakumod | 4 + raku/luhn/README.md | 88 ++++ raku/luhn/luhn.rakutest | 165 ++++++ raku/nucleotide-count/NucleotideCount.rakumod | 6 + raku/nucleotide-count/README.md | 36 ++ raku/nucleotide-count/nucleotide-count.rakutest | 95 ++++ raku/pangram/Pangram.rakumod | 5 + raku/pangram/README.md | 32 ++ raku/pangram/pangram.rakutest | 101 ++++ raku/phone-number/Phone.rakumod | 16 + raku/phone-number/README.md | 52 ++ raku/phone-number/phone-number.rakutest | 200 ++++++++ raku/raindrops/README.md | 39 ++ raku/raindrops/Raindrops.rakumod | 9 + raku/raindrops/raindrops.rakutest | 165 ++++++ raku/two-fer/README.md | 49 ++ raku/two-fer/TwoFer.rakumod | 5 + raku/two-fer/two-fer.rakutest | 49 ++ raku/word-count/README.md | 54 ++ raku/word-count/WordCount.rakumod | 5 + raku/word-count/word-count.rakutest | 184 +++++++ 39 files changed, 2987 insertions(+) create mode 100644 raku/anagram/Anagram.rakumod create mode 100644 raku/anagram/README.md create mode 100644 raku/anagram/anagram.rakutest create mode 100644 raku/bob/Bob.rakumod create mode 100644 raku/bob/README.md create mode 100644 raku/bob/bob.rakutest create mode 100644 raku/clock/Clock.rakumod create mode 100644 raku/clock/README.md create mode 100644 raku/clock/clock.rakutest create mode 100644 raku/hamming/Hamming.rakumod create mode 100644 raku/hamming/README.md create mode 100644 raku/hamming/hamming.rakutest create mode 100644 raku/hello-world/HelloWorld.rakumod create mode 100644 raku/hello-world/README.md create mode 100644 raku/hello-world/hello-world.rakutest create mode 100644 raku/leap/Leap.rakumod create mode 100644 raku/leap/README.md create mode 100644 raku/leap/leap.rakutest create mode 100644 raku/luhn/Luhn.rakumod create mode 100644 raku/luhn/README.md create mode 100644 raku/luhn/luhn.rakutest create mode 100644 raku/nucleotide-count/NucleotideCount.rakumod create mode 100644 raku/nucleotide-count/README.md create mode 100644 raku/nucleotide-count/nucleotide-count.rakutest create mode 100644 raku/pangram/Pangram.rakumod create mode 100644 raku/pangram/README.md create mode 100644 raku/pangram/pangram.rakutest create mode 100644 raku/phone-number/Phone.rakumod create mode 100644 raku/phone-number/README.md create mode 100644 raku/phone-number/phone-number.rakutest create mode 100644 raku/raindrops/README.md create mode 100644 raku/raindrops/Raindrops.rakumod create mode 100644 raku/raindrops/raindrops.rakutest create mode 100644 raku/two-fer/README.md create mode 100644 raku/two-fer/TwoFer.rakumod create mode 100644 raku/two-fer/two-fer.rakutest create mode 100644 raku/word-count/README.md create mode 100644 raku/word-count/WordCount.rakumod create mode 100644 raku/word-count/word-count.rakutest (limited to 'raku') diff --git a/raku/anagram/Anagram.rakumod b/raku/anagram/Anagram.rakumod new file mode 100644 index 0000000..5f67e65 --- /dev/null +++ b/raku/anagram/Anagram.rakumod @@ -0,0 +1,8 @@ +unit module Anagram; + +sub match-anagrams (Str :$subject!, :@candidates!) is export { + gather for @candidates { + next if .fc eq $subject.fc; + take $_ if .fc.comb.Bag eqv $subject.fc.comb.Bag; + } +} diff --git a/raku/anagram/README.md b/raku/anagram/README.md new file mode 100644 index 0000000..ca11115 --- /dev/null +++ b/raku/anagram/README.md @@ -0,0 +1,31 @@ +# Anagram + +An anagram is a rearrangement of letters to form a new word. +Given a word and a list of candidates, select the sublist of anagrams of the given word. + +Given `"listen"` and a list of candidates like `"enlists" "google" +"inlets" "banana"` the program should return a list containing +`"inlets"`. + +## Resources + +Remember to check out the Raku [documentation](https://docs.raku.org/) and +[resources](https://raku.org/resources/) pages for information, tips, and +examples if you get stuck. + +## Running the tests + +There is a test suite and module included with the exercise. +The test suite (a file with the extension `.rakutest`) will attempt to run routines +from the module (a file with the extension `.rakumod`). +Add/modify routines in the module so that the tests will pass! You can view the +test data by executing the command `raku --doc *.rakutest` (\* being the name of the +test suite), and run the test suite for the exercise by executing the command +`prove6 .` in the exercise directory. + +## Source + +Inspired by the Extreme Startup game [https://github.com/rchatley/extreme_startup](https://github.com/rchatley/extreme_startup) + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/raku/anagram/anagram.rakutest b/raku/anagram/anagram.rakutest new file mode 100644 index 0000000..6aa62c6 --- /dev/null +++ b/raku/anagram/anagram.rakutest @@ -0,0 +1,223 @@ +#!/usr/bin/env raku +use Test; +use JSON::Fast; +use lib $?FILE.IO.dirname; +use Anagram; +plan 14; + +my @test-cases = from-json($=pod.pop.contents).List; +for @test-cases -> %case { + cmp-ok match-anagrams( |%case:p ), + '~~', %case.Set, %case; +} + +=head2 Test Cases +=begin code +[ + { + "description": "no matches", + "expected": [ + ], + "input": { + "candidates": [ + "hello", + "world", + "zombies", + "pants" + ], + "subject": "diaper" + }, + "property": "findAnagrams" + }, + { + "description": "detects two anagrams", + "expected": [ + "stream", + "maters" + ], + "input": { + "candidates": [ + "stream", + "pigeon", + "maters" + ], + "subject": "master" + }, + "property": "findAnagrams" + }, + { + "description": "does not detect anagram subsets", + "expected": [ + ], + "input": { + "candidates": [ + "dog", + "goody" + ], + "subject": "good" + }, + "property": "findAnagrams" + }, + { + "description": "detects anagram", + "expected": [ + "inlets" + ], + "input": { + "candidates": [ + "enlists", + "google", + "inlets", + "banana" + ], + "subject": "listen" + }, + "property": "findAnagrams" + }, + { + "description": "detects three anagrams", + "expected": [ + "gallery", + "regally", + "largely" + ], + "input": { + "candidates": [ + "gallery", + "ballerina", + "regally", + "clergy", + "largely", + "leading" + ], + "subject": "allergy" + }, + "property": "findAnagrams" + }, + { + "description": "detects multiple anagrams with different case", + "expected": [ + "Eons", + "ONES" + ], + "input": { + "candidates": [ + "Eons", + "ONES" + ], + "subject": "nose" + }, + "property": "findAnagrams" + }, + { + "description": "does not detect non-anagrams with identical checksum", + "expected": [ + ], + "input": { + "candidates": [ + "last" + ], + "subject": "mass" + }, + "property": "findAnagrams" + }, + { + "description": "detects anagrams case-insensitively", + "expected": [ + "Carthorse" + ], + "input": { + "candidates": [ + "cashregister", + "Carthorse", + "radishes" + ], + "subject": "Orchestra" + }, + "property": "findAnagrams" + }, + { + "description": "detects anagrams using case-insensitive subject", + "expected": [ + "carthorse" + ], + "input": { + "candidates": [ + "cashregister", + "carthorse", + "radishes" + ], + "subject": "Orchestra" + }, + "property": "findAnagrams" + }, + { + "description": "detects anagrams using case-insensitive possible matches", + "expected": [ + "Carthorse" + ], + "input": { + "candidates": [ + "cashregister", + "Carthorse", + "radishes" + ], + "subject": "orchestra" + }, + "property": "findAnagrams" + }, + { + "description": "does not detect an anagram if the original word is repeated", + "expected": [ + ], + "input": { + "candidates": [ + "go Go GO" + ], + "subject": "go" + }, + "property": "findAnagrams" + }, + { + "description": "anagrams must use all letters exactly once", + "expected": [ + ], + "input": { + "candidates": [ + "patter" + ], + "subject": "tapper" + }, + "property": "findAnagrams" + }, + { + "description": "words are not anagrams of themselves (case-insensitive)", + "expected": [ + ], + "input": { + "candidates": [ + "BANANA", + "Banana", + "banana" + ], + "subject": "BANANA" + }, + "property": "findAnagrams" + }, + { + "description": "words other than themselves can be anagrams", + "expected": [ + "Silent" + ], + "input": { + "candidates": [ + "Listen", + "Silent", + "LISTEN" + ], + "subject": "LISTEN" + }, + "property": "findAnagrams" + } +] +=end code diff --git a/raku/bob/Bob.rakumod b/raku/bob/Bob.rakumod new file mode 100644 index 0000000..ab6fa66 --- /dev/null +++ b/raku/bob/Bob.rakumod @@ -0,0 +1,15 @@ +unit class Bob; + +method hey (Str $msg is copy) { + $msg .= trim; + + given $msg.trim { + when .chars == 0 { "Fine. Be that way!" } + when $_ eq .uc && $_ ~~ /<[a..zA..Z]>/ { + return "Calm down, I know what I'm doing!" if $_.ends-with("?"); + "Whoa, chill out!"; + } + when .ends-with("?") { "Sure." } + default { "Whatever." } + } +} diff --git a/raku/bob/README.md b/raku/bob/README.md new file mode 100644 index 0000000..01800c5 --- /dev/null +++ b/raku/bob/README.md @@ -0,0 +1,39 @@ +# Bob + +Bob is a lackadaisical teenager. In conversation, his responses are very limited. + +Bob answers 'Sure.' if you ask him a question, such as "How are you?". + +He answers 'Whoa, chill out!' if you YELL AT HIM (in all capitals). + +He answers 'Calm down, I know what I'm doing!' if you yell a question at him. + +He says 'Fine. Be that way!' if you address him without actually saying +anything. + +He answers 'Whatever.' to anything else. + +Bob's conversational partner is a purist when it comes to written communication and always follows normal rules regarding sentence punctuation in English. + +## Resources + +Remember to check out the Raku [documentation](https://docs.raku.org/) and +[resources](https://raku.org/resources/) pages for information, tips, and +examples if you get stuck. + +## Running the tests + +There is a test suite and module included with the exercise. +The test suite (a file with the extension `.rakutest`) will attempt to run routines +from the module (a file with the extension `.rakumod`). +Add/modify routines in the module so that the tests will pass! You can view the +test data by executing the command `raku --doc *.rakutest` (\* being the name of the +test suite), and run the test suite for the exercise by executing the command +`prove6 .` in the exercise directory. + +## Source + +Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. [http://pine.fm/LearnToProgram/?Chapter=06](http://pine.fm/LearnToProgram/?Chapter=06) + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/raku/bob/bob.rakutest b/raku/bob/bob.rakutest new file mode 100644 index 0000000..a540719 --- /dev/null +++ b/raku/bob/bob.rakutest @@ -0,0 +1,226 @@ +#!/usr/bin/env raku +use Test; +use JSON::Fast; +use lib $?FILE.IO.dirname; #`[Look for the module inside the same directory as this test file.] +use Bob; +plan 26; #`[This is how many tests we expect to run.] + +#`[Check that the class 'Bob' can use all of the methods +needed in the tests (only 'hey' for this one).] +subtest 'Class methods', { + for -> $method { + can-ok Bob, $method; + } +} or bail-out 'Cannot run expected method(s).'; + +my @test-cases = from-json($=pod.pop.contents).List; +# Go through the cases and check that Bob gives us the correct responses. +for @test-cases -> %case { + is Bob.hey(%case), |%case; +} + +=head2 Test Cases +=begin code +[ + { + "description": "stating something", + "expected": "Whatever.", + "input": { + "heyBob": "Tom-ay-to, tom-aaaah-to." + }, + "property": "response" + }, + { + "description": "shouting", + "expected": "Whoa, chill out!", + "input": { + "heyBob": "WATCH OUT!" + }, + "property": "response" + }, + { + "description": "shouting gibberish", + "expected": "Whoa, chill out!", + "input": { + "heyBob": "FCECDFCAAB" + }, + "property": "response" + }, + { + "description": "asking a question", + "expected": "Sure.", + "input": { + "heyBob": "Does this cryogenic chamber make me look fat?" + }, + "property": "response" + }, + { + "description": "asking a numeric question", + "expected": "Sure.", + "input": { + "heyBob": "You are, what, like 15?" + }, + "property": "response" + }, + { + "description": "asking gibberish", + "expected": "Sure.", + "input": { + "heyBob": "fffbbcbeab?" + }, + "property": "response" + }, + { + "description": "talking forcefully", + "expected": "Whatever.", + "input": { + "heyBob": "Hi there!" + }, + "property": "response" + }, + { + "description": "using acronyms in regular speech", + "expected": "Whatever.", + "input": { + "heyBob": "It's OK if you don't want to go work for NASA." + }, + "property": "response" + }, + { + "description": "forceful question", + "expected": "Calm down, I know what I'm doing!", + "input": { + "heyBob": "WHAT'S GOING ON?" + }, + "property": "response" + }, + { + "description": "shouting numbers", + "expected": "Whoa, chill out!", + "input": { + "heyBob": "1, 2, 3 GO!" + }, + "property": "response" + }, + { + "description": "no letters", + "expected": "Whatever.", + "input": { + "heyBob": "1, 2, 3" + }, + "property": "response" + }, + { + "description": "question with no letters", + "expected": "Sure.", + "input": { + "heyBob": "4?" + }, + "property": "response" + }, + { + "description": "shouting with special characters", + "expected": "Whoa, chill out!", + "input": { + "heyBob": "ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!" + }, + "property": "response" + }, + { + "description": "shouting with no exclamation mark", + "expected": "Whoa, chill out!", + "input": { + "heyBob": "I HATE THE DENTIST" + }, + "property": "response" + }, + { + "description": "statement containing question mark", + "expected": "Whatever.", + "input": { + "heyBob": "Ending with ? means a question." + }, + "property": "response" + }, + { + "description": "non-letters with question", + "expected": "Sure.", + "input": { + "heyBob": ":) ?" + }, + "property": "response" + }, + { + "description": "prattling on", + "expected": "Sure.", + "input": { + "heyBob": "Wait! Hang on. Are you going to be OK?" + }, + "property": "response" + }, + { + "description": "silence", + "expected": "Fine. Be that way!", + "input": { + "heyBob": "" + }, + "property": "response" + }, + { + "description": "prolonged silence", + "expected": "Fine. Be that way!", + "input": { + "heyBob": " " + }, + "property": "response" + }, + { + "description": "alternate silence", + "expected": "Fine. Be that way!", + "input": { + "heyBob": "\t\t\t\t\t\t\t\t\t\t" + }, + "property": "response" + }, + { + "description": "multiple line question", + "expected": "Whatever.", + "input": { + "heyBob": "\nDoes this cryogenic chamber make me look fat?\nNo." + }, + "property": "response" + }, + { + "description": "starting with whitespace", + "expected": "Whatever.", + "input": { + "heyBob": " hmmmmmmm..." + }, + "property": "response" + }, + { + "description": "ending with whitespace", + "expected": "Sure.", + "input": { + "heyBob": "Okay if like my spacebar quite a bit? " + }, + "property": "response" + }, + { + "description": "other whitespace", + "expected": "Fine. Be that way!", + "input": { + "heyBob": "\n\r \t" + }, + "property": "response" + }, + { + "description": "non-question ending with whitespace", + "expected": "Whatever.", + "input": { + "heyBob": "This is a statement ending with whitespace " + }, + "property": "response" + } +] +=end code diff --git a/raku/clock/Clock.rakumod b/raku/clock/Clock.rakumod new file mode 100644 index 0000000..cf2b5d4 --- /dev/null +++ b/raku/clock/Clock.rakumod @@ -0,0 +1,27 @@ +unit class Clock; + +has Int $.hour; +has Int $.minute; + +submethod TWEAK() { self.wrap-time; } + +method time { sprintf "%02d:%02d", $!hour, $!minute; } + +method add-minutes(UInt $amount --> Clock) { + $!hour += $amount div 60; + $!minute += $amount % 60; + self.wrap-time; +} + +method subtract-minutes(UInt $amount --> Clock) { + $!hour -= $amount div 60; + $!minute -= $amount % 60; + self.wrap-time; +} + +method wrap-time(--> Clock) { + $!hour += $!minute div 60; + $!minute %= 60; + $!hour %= 24; + return self; +} diff --git a/raku/clock/README.md b/raku/clock/README.md new file mode 100644 index 0000000..57a61aa --- /dev/null +++ b/raku/clock/README.md @@ -0,0 +1,30 @@ +# Clock + +Implement a clock that handles times without dates. + +You should be able to add and subtract minutes to it. + +Two clocks that represent the same time should be equal to each other. + +## Resources + +Remember to check out the Raku [documentation](https://docs.raku.org/) and +[resources](https://raku.org/resources/) pages for information, tips, and +examples if you get stuck. + +## Running the tests + +There is a test suite and module included with the exercise. +The test suite (a file with the extension `.rakutest`) will attempt to run routines +from the module (a file with the extension `.rakumod`). +Add/modify routines in the module so that the tests will pass! You can view the +test data by executing the command `raku --doc *.rakutest` (\* being the name of the +test suite), and run the test suite for the exercise by executing the command +`prove6 .` in the exercise directory. + +## Source + +Pairing session with Erin Drummond [https://twitter.com/ebdrummond](https://twitter.com/ebdrummond) + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/raku/clock/clock.rakutest b/raku/clock/clock.rakutest new file mode 100644 index 0000000..ee57c0e --- /dev/null +++ b/raku/clock/clock.rakutest @@ -0,0 +1,642 @@ +#!/usr/bin/env raku +use Test; +use JSON::Fast; +use lib $?FILE.IO.dirname; +use Clock; +plan 55; + +subtest 'Class methods', { + for