Skip to content

Commit 730842a

Browse files
Add word-count exercise (#253)
1 parent 40b4dcb commit 730842a

File tree

8 files changed

+319
-0
lines changed

8 files changed

+319
-0
lines changed

config.json

+8
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,14 @@
415415
"prerequisites": [],
416416
"difficulty": 3
417417
},
418+
{
419+
"slug": "word-count",
420+
"name": "Word Count",
421+
"uuid": "438c1838-390a-439f-964a-a6c8d1855b7e",
422+
"practices": [],
423+
"prerequisites": [],
424+
"difficulty": 3
425+
},
418426
{
419427
"slug": "affine-cipher",
420428
"name": "Affine Cipher",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Instructions
2+
3+
Your task is to count how many times each word occurs in a subtitle of a drama.
4+
5+
The subtitles from these dramas use only ASCII characters.
6+
7+
The characters often speak in casual English, using contractions like _they're_ or _it's_.
8+
Though these contractions come from two words (e.g. _we are_), the contraction (_we're_) is considered a single word.
9+
10+
Words can be separated by any form of punctuation (e.g. ":", "!", or "?") or whitespace (e.g. "\t", "\n", or " ").
11+
The only punctuation that does not separate words is the apostrophe in contractions.
12+
13+
Numbers are considered words.
14+
If the subtitles say _It costs 100 dollars._ then _100_ will be its own word.
15+
16+
Words are case insensitive.
17+
For example, the word _you_ occurs three times in the following sentence:
18+
19+
> You come back, you hear me? DO YOU HEAR ME?
20+
21+
The ordering of the word counts in the results doesn't matter.
22+
23+
Here's an example that incorporates several of the elements discussed above:
24+
25+
- simple words
26+
- contractions
27+
- numbers
28+
- case insensitive words
29+
- punctuation (including apostrophes) to separate words
30+
- different forms of whitespace to separate words
31+
32+
`"That's the password: 'PASSWORD 123'!", cried the Special Agent.\nSo I fled.`
33+
34+
The mapping for this subtitle would be:
35+
36+
```text
37+
123: 1
38+
agent: 1
39+
cried: 1
40+
fled: 1
41+
i: 1
42+
password: 2
43+
so: 1
44+
special: 1
45+
that's: 1
46+
the: 2
47+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Introduction
2+
3+
You teach English as a foreign language to high school students.
4+
5+
You've decided to base your entire curriculum on TV shows.
6+
You need to analyze which words are used, and how often they're repeated.
7+
8+
This will let you choose the simplest shows to start with, and to gradually increase the difficulty as time passes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"authors": [
3+
"keiravillekode"
4+
],
5+
"files": {
6+
"solution": [
7+
"word-count.v"
8+
],
9+
"test": [
10+
"run_test.v"
11+
],
12+
"example": [
13+
".meta/example.v"
14+
]
15+
},
16+
"blurb": "Given a phrase, count the occurrences of each word in that phrase.",
17+
"source": "This is a classic toy problem, but we were reminded of it by seeing it in the Go Tour."
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
module main
2+
3+
fn count_words(sentence string) map[string]int {
4+
mut result := map[string]int{}
5+
mut first := 0
6+
7+
outer: for {
8+
for {
9+
if first >= sentence.len {
10+
break outer
11+
}
12+
13+
ch := sentence[first]
14+
if ch.is_letter() || ch.is_digit() {
15+
break
16+
}
17+
18+
first++
19+
}
20+
21+
mut last := first + 1
22+
for {
23+
if last == sentence.len {
24+
break
25+
}
26+
27+
ch := sentence[last]
28+
if !ch.is_letter() && !ch.is_digit() && ch != `'` {
29+
break
30+
}
31+
32+
last++
33+
}
34+
35+
for sentence[last - 1] == `'` {
36+
last--
37+
}
38+
39+
result[sentence[first..last].to_lower()]++
40+
41+
first = last + 1
42+
}
43+
44+
return result
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# This is an auto-generated file. Regular comments will be removed when this
2+
# file is regenerated. Regenerating will not touch any manually added keys,
3+
# so comments can be added in a "comment" key.
4+
5+
[61559d5f-2cad-48fb-af53-d3973a9ee9ef]
6+
description = "count one word"
7+
8+
[5abd53a3-1aed-43a4-a15a-29f88c09cbbd]
9+
description = "count one of each word"
10+
11+
[2a3091e5-952e-4099-9fac-8f85d9655c0e]
12+
description = "multiple occurrences of a word"
13+
14+
[e81877ae-d4da-4af4-931c-d923cd621ca6]
15+
description = "handles cramped lists"
16+
17+
[7349f682-9707-47c0-a9af-be56e1e7ff30]
18+
description = "handles expanded lists"
19+
20+
[a514a0f2-8589-4279-8892-887f76a14c82]
21+
description = "ignore punctuation"
22+
23+
[d2e5cee6-d2ec-497b-bdc9-3ebe092ce55e]
24+
description = "include numbers"
25+
26+
[dac6bc6a-21ae-4954-945d-d7f716392dbf]
27+
description = "normalize case"
28+
29+
[4185a902-bdb0-4074-864c-f416e42a0f19]
30+
description = "with apostrophes"
31+
include = false
32+
33+
[4ff6c7d7-fcfc-43ef-b8e7-34ff1837a2d3]
34+
description = "with apostrophes"
35+
reimplements = "4185a902-bdb0-4074-864c-f416e42a0f19"
36+
37+
[be72af2b-8afe-4337-b151-b297202e4a7b]
38+
description = "with quotations"
39+
40+
[8d6815fe-8a51-4a65-96f9-2fb3f6dc6ed6]
41+
description = "substrings from the beginning"
42+
43+
[c5f4ef26-f3f7-4725-b314-855c04fb4c13]
44+
description = "multiple spaces not detected as a word"
45+
46+
[50176e8a-fe8e-4f4c-b6b6-aa9cf8f20360]
47+
description = "alternating word separators not detected as a word"
48+
49+
[6d00f1db-901c-4bec-9829-d20eb3044557]
50+
description = "quotation for word with apostrophe"
+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
module main
2+
3+
fn test_count_one_word() {
4+
expected := {
5+
'word': 1
6+
}
7+
assert count_words('word') == expected
8+
}
9+
10+
fn test_count_one_of_each_word() {
11+
expected := {
12+
'one': 1
13+
'of': 1
14+
'each': 1
15+
}
16+
assert count_words('one of each') == expected
17+
}
18+
19+
fn test_multiple_occurrences_of_a_word() {
20+
expected := {
21+
'one': 1
22+
'fish': 4
23+
'two': 1
24+
'red': 1
25+
'blue': 1
26+
}
27+
assert count_words('one fish two fish red fish blue fish') == expected
28+
}
29+
30+
fn test_handles_cramped_lists() {
31+
expected := {
32+
'one': 1
33+
'two': 1
34+
'three': 1
35+
}
36+
assert count_words('one,two,three') == expected
37+
}
38+
39+
fn test_handles_expanded_lists() {
40+
expected := {
41+
'one': 1
42+
'two': 1
43+
'three': 1
44+
}
45+
assert count_words('one,\ntwo,\nthree') == expected
46+
}
47+
48+
fn test_ignore_punctuation() {
49+
expected := {
50+
'car': 1
51+
'carpet': 1
52+
'as': 1
53+
'java': 1
54+
'javascript': 1
55+
}
56+
assert count_words('car: carpet as java: javascript!!&@$%^&') == expected
57+
}
58+
59+
fn test_include_numbers() {
60+
expected := {
61+
'testing': 2
62+
'1': 1
63+
'2': 1
64+
}
65+
assert count_words('testing, 1, 2 testing') == expected
66+
}
67+
68+
fn test_normalize_case() {
69+
expected := {
70+
'go': 3
71+
'stop': 2
72+
}
73+
assert count_words('go Go GO Stop stop') == expected
74+
}
75+
76+
fn test_with_apostrophes() {
77+
expected := {
78+
'first': 1
79+
"don't": 2
80+
'laugh': 1
81+
'then': 1
82+
'cry': 1
83+
"you're": 1
84+
'getting': 1
85+
'it': 1
86+
}
87+
assert count_words("'First: don't laugh. Then: don't cry. You're getting it.'") == expected
88+
}
89+
90+
fn test_with_quotations() {
91+
expected := {
92+
'joe': 1
93+
"can't": 1
94+
'tell': 1
95+
'between': 1
96+
'large': 2
97+
'and': 1
98+
}
99+
assert count_words("Joe can't tell between 'large' and large.") == expected
100+
}
101+
102+
fn test_substrings_from_the_beginning() {
103+
expected := {
104+
'joe': 1
105+
"can't": 1
106+
'tell': 1
107+
'between': 1
108+
'app': 1
109+
'apple': 1
110+
'and': 1
111+
'a': 1
112+
}
113+
assert count_words("Joe can't tell between app, apple and a.") == expected
114+
}
115+
116+
fn test_multiple_spaces_not_detected_as_a_word() {
117+
expected := {
118+
'multiple': 1
119+
'whitespaces': 1
120+
}
121+
assert count_words(' multiple whitespaces') == expected
122+
}
123+
124+
fn test_alternating_word_separators_not_detected_as_a_word() {
125+
expected := {
126+
'one': 1
127+
'two': 1
128+
'three': 1
129+
}
130+
assert count_words(",\n,one,\n ,two \n 'three'") == expected
131+
}
132+
133+
fn test_quotation_for_word_with_apostrophe() {
134+
expected := {
135+
'can': 1
136+
"can't": 2
137+
}
138+
assert count_words("can, can't, 'can't'") == expected
139+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module main
2+
3+
fn count_words(sentence string) map[string]int {
4+
}

0 commit comments

Comments
 (0)