From fc5c3d909fdf88779339910e8e128637edd9f8f9 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Sat, 4 May 2024 16:24:40 +0200 Subject: [PATCH] Add `parallel-letter-frequency` exercise --- config.json | 8 + .../.docs/instructions.md | 7 + .../.meta/config.json | 17 ++ .../.meta/example.8th | 21 +++ .../.meta/tests.toml | 50 +++++ .../libs/exercism/test | 173 ++++++++++++++++++ .../parallel-letter-frequency.8th | 3 + .../parallel-letter-frequency/test.8th | 70 +++++++ 8 files changed, 349 insertions(+) create mode 100644 exercises/practice/parallel-letter-frequency/.docs/instructions.md create mode 100644 exercises/practice/parallel-letter-frequency/.meta/config.json create mode 100644 exercises/practice/parallel-letter-frequency/.meta/example.8th create mode 100644 exercises/practice/parallel-letter-frequency/.meta/tests.toml create mode 100644 exercises/practice/parallel-letter-frequency/libs/exercism/test create mode 100644 exercises/practice/parallel-letter-frequency/parallel-letter-frequency.8th create mode 100644 exercises/practice/parallel-letter-frequency/test.8th diff --git a/config.json b/config.json index 0a1e9267..93ead023 100644 --- a/config.json +++ b/config.json @@ -420,6 +420,14 @@ "practices": [], "prerequisites": [], "difficulty": 3 + }, + { + "slug": "parallel-letter-frequency", + "name": "Parallel Letter Frequency", + "uuid": "8f55c666-41f7-42df-abf2-7133af0cb36a", + "practices": [], + "prerequisites": [], + "difficulty": 6 } ] }, diff --git a/exercises/practice/parallel-letter-frequency/.docs/instructions.md b/exercises/practice/parallel-letter-frequency/.docs/instructions.md new file mode 100644 index 00000000..6147b90a --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/.docs/instructions.md @@ -0,0 +1,7 @@ +# Instructions + +Count the frequency of letters in texts using parallel computation. + +Parallelism is about doing things in parallel that can also be done sequentially. +A common example is counting the frequency of letters. +Employ parallelism to calculate the total frequency of each letter in a list of texts. diff --git a/exercises/practice/parallel-letter-frequency/.meta/config.json b/exercises/practice/parallel-letter-frequency/.meta/config.json new file mode 100644 index 00000000..5a255eae --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/.meta/config.json @@ -0,0 +1,17 @@ +{ + "authors": [ + "erikschierboom" + ], + "files": { + "solution": [ + "parallel-letter-frequency.8th" + ], + "test": [ + "test.8th" + ], + "example": [ + ".meta/example.8th" + ] + }, + "blurb": "Count the frequency of letters in texts using parallel computation." +} diff --git a/exercises/practice/parallel-letter-frequency/.meta/example.8th b/exercises/practice/parallel-letter-frequency/.meta/example.8th new file mode 100644 index 00000000..fe4a469e --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/.meta/example.8th @@ -0,0 +1,21 @@ +needs array/parallel + +: increment-frequency \ m n -- m + 0 m:!? swap ' n:1+ m:op! +; + +: letters \ s -- a + /\p{L}/ r:/ +; + +: letter-frequencies \ s -- m + s:lc letters ( dup -rot increment-frequency ) {} const a:reduce +; + +: merge-frequencies \ a -- m + ( ( >r dup -rot 0 m:@? r> n:+ rot swap m:! ) m:each drop ) {} const a:reduce +; + +: >frequencies \ a -- m + a:len ' letter-frequencies swap a:map-par merge-frequencies +; diff --git a/exercises/practice/parallel-letter-frequency/.meta/tests.toml b/exercises/practice/parallel-letter-frequency/.meta/tests.toml new file mode 100644 index 00000000..0b975745 --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/.meta/tests.toml @@ -0,0 +1,50 @@ +# 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. + +[c054d642-c1fa-4234-8007-9339f2337886] +description = "no texts" + +[818031be-49dc-4675-b2f9-c4047f638a2a] +description = "one text with one letter" + +[c0b81d1b-940d-4cea-9f49-8445c69c17ae] +description = "one text with multiple letters" + +[708ff1e0-f14a-43fd-adb5-e76750dcf108] +description = "two texts with one letter" + +[1b5c28bb-4619-4c9d-8db9-a4bb9c3bdca0] +description = "two texts with multiple letters" + +[6366e2b8-b84c-4334-a047-03a00a656d63] +description = "ignore letter casing" + +[92ebcbb0-9181-4421-a784-f6f5aa79f75b] +description = "ignore whitespace" + +[bc5f4203-00ce-4acc-a5fa-f7b865376fd9] +description = "ignore punctuation" + +[68032b8b-346b-4389-a380-e397618f6831] +description = "ignore numbers" + +[aa9f97ac-3961-4af1-88e7-6efed1bfddfd] +description = "Unicode letters" + +[7b1da046-701b-41fc-813e-dcfb5ee51813] +description = "combination of lower- and uppercase letters, punctuation and white space" + +[4727f020-df62-4dcf-99b2-a6e58319cb4f] +description = "large texts" +include = false + +[adf8e57b-8e54-4483-b6b8-8b32c115884c] +description = "many small texts" diff --git a/exercises/practice/parallel-letter-frequency/libs/exercism/test b/exercises/practice/parallel-letter-frequency/libs/exercism/test new file mode 100644 index 00000000..1d08eb25 --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/libs/exercism/test @@ -0,0 +1,173 @@ +needs console/loaded + +\ ----------------------------------------------------------------- + +ns: test + +-1 var, test-count +var tests-passed +var tests-failed +var tests-skipped +true var, run-test + +\ Some utility words + + +: test-passed \ s x x -- \\ test name, expected value, actual value + 2drop + 1 tests-passed n:+! + con:green con:onBlack . space " ... OK" . con:white con:onBlack cr +; + +: test-skipped \ s -- + 1 tests-skipped n:+! + con:cyan con:onBlack . space " ... SKIPPED" . con:white con:onBlack cr +; + +: test-failed \ s x x -- \\ test name, expected value, actual value + 1 tests-failed n:+! + rot + con:red con:onBlack . space " ... FAIL" . con:white con:onBlack cr + " Actual: «" . . "»" . cr + " Expected: «" . . "»" . cr cr +; + +: isword? \ x -- x f + dup >kind ns:w n:= +; + +: run-test? \ -- T + run-test @ if true else "RUN_ALL_TESTS" getenv n:>bool then +; + +\ Num passed + num skipped + num failed should == num tests +: all-tests-run? \ -- T + tests-passed @ tests-skipped @ tests-failed @ n:+ n:+ + test-count @ n:= +; + +\ returns true if x is a date, false otherwise +: date? \ x -- x T + dup >kind ns:d n:= +; + +\ adapted from 8th forum -- https://8th-dev.com/forum/index.php/topic,2745.0.html +: eq? \ x x -- T + \ are the items the same kind? + 2dup >kind swap >kind n:= + !if 2drop false ;then + + \ same kind: try different comparators + number? if n:= ;then + string? if s:= ;then + array? if ' eq? a:= 2nip ;then + map? if ' eq? m:= 2nip ;then + date? if d:= ;then + + \ otherwise fall back to 'lazy evaluation' + l: = +; + +: eps_eq? \ n x x -- T + \ are the items the same kind? + 2dup >kind swap >kind n:= + !if 2drop false ;then + number? !if 2drop false ;then + rot n:~= +; + +: check-depth \ ... n -- ... + dup>r + n:1+ depth n:= + !if + con:red con:onBlack + "PANIC: expected stack depth to be " . r> . cr + "Stack is:" . cr + .s cr + 255 die + then + rdrop +; + +\ ----------------------------------------------------------------- + +\ status report at end of run +( all-tests-run? + !if con:red con:onBlack "... FAIL - not all tests completed" . con:white con:onBlack cr then +) onexit + +\ Print a summary of the tests run +( con:white con:onBlack + test-count @ . space "tests planned - " . + tests-passed @ . space "passed - " . + tests-skipped @ . space "skipped - " . + tests-failed @ . space "failed" . cr +) onexit + +\ ----------------------------------------------------------------- +\ The public-facing words +\ ----------------------------------------------------------------- + +: equal? \ s x w -- | s w x -- + run-test? !if 2drop test-skipped ;; then + isword? !if swap then + w:exec + 3 check-depth + 2dup \ so test-failed can show actual and expected + eq? if test-passed else test-failed then +; + +: approx_equal? \ s x w n -- | s w x n -- + run-test? !if 3drop test-skipped ;; then + -rot isword? !if swap then + w:exec + 4 check-depth + 3dup \ so test-failed can show actual and expected + eps_eq? + if rot drop test-passed else rot drop test-failed then +; + +: true? \ s w -- + run-test? !if drop test-skipped ;; then + w:exec + 2 check-depth + true swap dup \ so test-failed can show actual and expected + if test-passed else test-failed then +; + +: false? \ s w -- + run-test? !if drop test-skipped ;; then + w:exec + 2 check-depth + false swap dup \ so test-failed can show actual and expected + !if test-passed else test-failed then +; + +: null? \ s w -- + run-test? !if drop test-skipped ;; then + w:exec + 2 check-depth + null swap dup \ so test-failed can show actual and expected + G:null? nip if test-passed else test-failed then +; + +: SKIP-REST-OF-TESTS false run-test ! ; + +: tests \ n -- + test-count ! +; + +\ Set the exit status: +\ 0 = all OK +\ 1 = not all tests were run (some error occurred) +\ 2 = some tests failed +: end-of-tests \ -- + all-tests-run? + if + tests-failed @ 0 n:= if 0 else 2 then + else + 1 + then + die +; + diff --git a/exercises/practice/parallel-letter-frequency/parallel-letter-frequency.8th b/exercises/practice/parallel-letter-frequency/parallel-letter-frequency.8th new file mode 100644 index 00000000..ac317501 --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/parallel-letter-frequency.8th @@ -0,0 +1,3 @@ +: >frequencies \ a -- m + +; diff --git a/exercises/practice/parallel-letter-frequency/test.8th b/exercises/practice/parallel-letter-frequency/test.8th new file mode 100644 index 00000000..ae15ea6c --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/test.8th @@ -0,0 +1,70 @@ +"parallel-letter-frequency.8th" f:include +needs exercism/test +with: test +12 tests + +"no texts" + ( [] >frequencies ) + {} + equal? + +SKIP-REST-OF-TESTS + +"one text with one letter" + ( ["a"] >frequencies ) + {"a": 1} + equal? + +"one text with multiple letters" + ( ["bbcccd"] >frequencies ) + {"b": 2, "c": 3, "d": 1} + equal? + +"two texts with one letter" + ( ["e", "f"] >frequencies ) + {"e": 1, "f": 1} + equal? + +"two texts with multiple letters" + ( ["ggh", "hhi"] >frequencies ) + {"g": 2, "h": 3, "i": 1} + equal? + +"ignore letter casing" + ( ["m", "M"] >frequencies ) + {"m": 2} + equal? + +"ignore whitespace" + ( [" ", " ", " +"] >frequencies ) + {} + equal? + +"ignore punctuation" + ( ["!", "?", ";", ",", "."] >frequencies ) + {} + equal? + +"ignore numbers" + ( ["1", "2", "3", "4", "5", "6", "7", "8", "9"] >frequencies ) + {} + equal? + +"Unicode letters" + ( ["本", "φ", "ほ", "ø"] >frequencies ) + {"本": 1, "φ": 1, "ほ": 1, "ø": 1} + equal? + +"combination of lower- and uppercase letters, punctuation and white space" + ( ["There, peeping among the cloud-wrack above a dark tower high up in the mountains, Sam saw a white star twinkle for a while. The beauty of it smote his heart, as he looked up out of the forsaken land, and hope returned to him. For like a shaft, clear and cold, the thought pierced him that in the end, the shadow was only a small and passing thing: there was light and high beauty forever beyond its reach."] >frequencies ) + {"a": 32, "b": 4, "c": 6, "d": 14, "e": 37, "f": 7, "g": 8, "h": 29, "i": 19, "k": 6, "l": 12, "m": 7, "n": 19, "o": 22, "p": 7, "r": 17, "s": 16, "t": 30, "u": 9, "v": 2, "w": 9, "y": 4} + equal? + +"many small texts" + ( ["abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc", "abbccc"] >frequencies ) + {"a": 50, "b": 100, "c": 150} + equal? + +end-of-tests +;with