Skip to content

Commit cedba7c

Browse files
authored
Add parallel-letter-frequency exercise (exercism#174)
1 parent 82d1476 commit cedba7c

10 files changed

+436
-0
lines changed

config.json

+22
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,20 @@
1818
"test_runner": {
1919
"average_run_time": 2
2020
},
21+
"files": {
22+
"solution": [
23+
"%{kebab_slug}.wren"
24+
],
25+
"test": [
26+
"%{kebab_slug}.spec.wren"
27+
],
28+
"example": [
29+
".meta/proof.ci.wren"
30+
],
31+
"exemplar": [
32+
".meta/exemplar.wren"
33+
]
34+
},
2135
"exercises": {
2236
"practice": [
2337
{
@@ -685,6 +699,14 @@
685699
"practices": [],
686700
"prerequisites": [],
687701
"difficulty": 7
702+
},
703+
{
704+
"slug": "parallel-letter-frequency",
705+
"name": "Parallel Letter Frequency",
706+
"uuid": "9f322f6a-26e7-4595-9a13-36965657bac6",
707+
"practices": [],
708+
"prerequisites": [],
709+
"difficulty": 7
688710
}
689711
]
690712
},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# ignore
2+
3+
You can read about concurrency in Wren [in the manual][concurrency].
4+
5+
[concurrency]: https://wren.io/concurrency.html
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Instructions
2+
3+
Count the frequency of letters in texts using parallel computation.
4+
5+
Parallelism is about doing things in parallel that can also be done sequentially.
6+
A common example is counting the frequency of letters.
7+
Create a function that returns the total frequency of each letter in a list of texts and that employs parallelism.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"authors": [
3+
"glennj"
4+
],
5+
"files": {
6+
"solution": [
7+
"parallel-letter-frequency.wren"
8+
],
9+
"test": [
10+
"parallel-letter-frequency.spec.wren"
11+
],
12+
"example": [
13+
".meta/proof.ci.wren"
14+
]
15+
},
16+
"blurb": "Count the frequency of letters in texts using parallel computation."
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// ------------------------------------------------------------------
2+
class Frequency {
3+
static ofText(text) {
4+
return text.codePoints.reduce(Frequency.new()) {|freq, cp|
5+
var char
6+
if (65 <= cp && cp <= 90) char = String.fromCodePoint(cp + 32)
7+
if (97 <= cp && cp <= 122) char = String.fromCodePoint(cp)
8+
if (char != null) freq.incr(char)
9+
return freq
10+
}
11+
}
12+
13+
construct new() {
14+
_map = {}
15+
}
16+
17+
keys { _map.keys }
18+
[key] { _map[key] }
19+
[key]=(value) { _map[key] = value }
20+
21+
toMap { _map }
22+
toString { _map.toString }
23+
24+
incr(key) { incr(key, 1) }
25+
incr(key, amount) { _map[key] = (_map.containsKey(key) ? _map[key] : 0) + amount }
26+
27+
addAll(other) {
28+
if (other is Frequency) {
29+
other.keys.each {|key|
30+
incr(key, other[key])
31+
}
32+
}
33+
}
34+
}
35+
36+
// ------------------------------------------------------------------
37+
class ParallelLetterFrequency {
38+
construct new(inputs) {
39+
_texts = inputs
40+
}
41+
42+
nonConcurrent() {
43+
return _texts.reduce(Frequency.new()) {|freq, text|
44+
freq.addAll(Frequency.ofText(text))
45+
return freq
46+
}.toMap
47+
}
48+
49+
concurrent() {
50+
// create a fiber for each input text
51+
var fibers = _texts.map {|text|
52+
return Fiber.new {|str|
53+
Fiber.yield() // so the first `call` doesn't wait for the result
54+
var freq = Frequency.ofText(str)
55+
Fiber.yield(freq)
56+
}
57+
}.toList
58+
59+
// then send a piece of text to each fiber
60+
(0..._texts.count).each {|i|
61+
fibers[i].call(_texts[i])
62+
}
63+
64+
// then collect the results
65+
var result = Frequency.new()
66+
fibers.each {|fiber|
67+
var freq = fiber.call()
68+
result.addAll(freq)
69+
}
70+
71+
return result.toMap
72+
}
73+
74+
calculateFrequencies() {
75+
//return nonConcurrent()
76+
return concurrent()
77+
}
78+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[c054d642-c1fa-4234-8007-9339f2337886]
13+
description = "no texts"
14+
15+
[818031be-49dc-4675-b2f9-c4047f638a2a]
16+
description = "one text with one letter"
17+
18+
[c0b81d1b-940d-4cea-9f49-8445c69c17ae]
19+
description = "one text with multiple letters"
20+
21+
[708ff1e0-f14a-43fd-adb5-e76750dcf108]
22+
description = "two texts with one letter"
23+
24+
[1b5c28bb-4619-4c9d-8db9-a4bb9c3bdca0]
25+
description = "two texts with multiple letters"
26+
27+
[6366e2b8-b84c-4334-a047-03a00a656d63]
28+
description = "ignore letter casing"
29+
30+
[92ebcbb0-9181-4421-a784-f6f5aa79f75b]
31+
description = "ignore whitespace"
32+
33+
[bc5f4203-00ce-4acc-a5fa-f7b865376fd9]
34+
description = "ignore punctuation"
35+
36+
[68032b8b-346b-4389-a380-e397618f6831]
37+
description = "ignore numbers"
38+
39+
[aa9f97ac-3961-4af1-88e7-6efed1bfddfd]
40+
description = "Unicode letters"
41+
include = false
42+
comment = "wren doesn't have a lot of string manipulation functionality"
43+
comment = "it can't lowercase an arbitrary unicode letter"
44+
45+
[7b1da046-701b-41fc-813e-dcfb5ee51813]
46+
description = "combination of lower- and uppercase letters, punctuation and white space"
47+
48+
[4727f020-df62-4dcf-99b2-a6e58319cb4f]
49+
description = "large texts"
50+
51+
[adf8e57b-8e54-4483-b6b8-8b32c115884c]
52+
description = "many small texts"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2023 Exercism
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import "wren-package" for WrenPackage, Dependency
2+
import "os" for Process
3+
4+
class Package is WrenPackage {
5+
construct new() {}
6+
name { "exercism/parallel-letter-frequency" }
7+
dependencies {
8+
return [
9+
Dependency.new("wren-testie", "0.3.0", "https://github.com/joshgoebel/wren-testie.git")
10+
]
11+
}
12+
}
13+
14+
Package.new().default()

exercises/practice/parallel-letter-frequency/parallel-letter-frequency.spec.wren

+211
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class ParallelLetterFrequency {
2+
construct new(inputs) {
3+
// implement me
4+
}
5+
6+
calculateFrequencies() {
7+
// implement me
8+
}
9+
}

0 commit comments

Comments
 (0)