Skip to content

Commit

Permalink
Add parallel-letter-frequency exercise (#170)
Browse files Browse the repository at this point in the history
  • Loading branch information
ErikSchierboom authored May 5, 2024
1 parent 51da882 commit 90f4ad5
Show file tree
Hide file tree
Showing 8 changed files with 349 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
]
},
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
17 changes: 17 additions & 0 deletions exercises/practice/parallel-letter-frequency/.meta/config.json
Original file line number Diff line number Diff line change
@@ -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."
}
21 changes: 21 additions & 0 deletions exercises/practice/parallel-letter-frequency/.meta/example.8th
Original file line number Diff line number Diff line change
@@ -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
;
50 changes: 50 additions & 0 deletions exercises/practice/parallel-letter-frequency/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -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"
173 changes: 173 additions & 0 deletions exercises/practice/parallel-letter-frequency/libs/exercism/test
Original file line number Diff line number Diff line change
@@ -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
;

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
: >frequencies \ a -- m

;
70 changes: 70 additions & 0 deletions exercises/practice/parallel-letter-frequency/test.8th
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 90f4ad5

Please sign in to comment.