Skip to content

Commit 0caae7f

Browse files
Bring word-count up to date with canonical data (#659)
Co-authored-by: Angelika Tyborska <[email protected]> Co-authored-by: Tim Austin <[email protected]>
1 parent 385fdfa commit 0caae7f

File tree

4 files changed

+90
-16
lines changed

4 files changed

+90
-16
lines changed

config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@
539539
"name": "Word Count",
540540
"uuid": "4a24ba2f-ae92-4095-be53-64bc881422ea",
541541
"prerequisites": [],
542-
"difficulty": 2,
542+
"difficulty": 3,
543543
"topics": [
544544
"lists",
545545
"maps",
Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,34 @@
11
defmodule WordCount do
2-
@ascii_punctuation ~r/!|"|\#|\$|%|&|'|\(|\)|\*|\+|,|\.|\/|:|;|<|=|>|\?|@|\[|\\|]|\^|_|`|\{|\||}|~/
2+
@doc """
3+
Count the number of words in the sentence.
34
5+
Words are compared case-insensitively.
6+
"""
7+
@spec count(String.t()) :: map
48
def count(sentence) do
59
sentence
6-
|> String.downcase()
7-
|> remove_punctuation
8-
|> to_words
9-
|> summarize
10+
|> normalize()
11+
|> split
12+
|> frequencies()
1013
end
1114

12-
defp remove_punctuation(string), do: String.replace(string, @ascii_punctuation, " ")
13-
14-
defp to_words(sentence), do: List.flatten(String.split(sentence))
15+
defp normalize(string) do
16+
string
17+
|> String.downcase()
18+
|> String.replace("_", " ", global: true)
19+
end
1520

16-
defp summarize(words) do
17-
Enum.reduce(words, %{}, &add_count/2)
21+
defp split(string) do
22+
~r/\b[\w'-]+\b/u
23+
|> Regex.scan(string)
24+
|> List.flatten()
1825
end
1926

20-
defp add_count(word, counts) do
21-
Map.update(counts, word, 1, &(&1 + 1))
27+
defp frequencies(strings) do
28+
# Enum.frequencies is only available from Elixir 1.10
29+
strings
30+
|> Enum.reduce(%{}, fn word, count ->
31+
Map.update(count, word, 1, &(&1 + 1))
32+
end)
2233
end
2334
end

exercises/practice/word-count/.meta/version

Lines changed: 0 additions & 1 deletion
This file was deleted.

exercises/practice/word-count/test/word_count_test.exs

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@ defmodule WordCountTest do
1717
assert WordCount.count("one fish two fish red fish blue fish") == expected
1818
end
1919

20+
@tag :pending
21+
test "handles cramped list" do
22+
expected = %{"one" => 1, "two" => 1, "three" => 1}
23+
assert WordCount.count("one,two,three") == expected
24+
end
25+
26+
@tag :pending
27+
test "handles expanded list" do
28+
expected = %{"one" => 1, "two" => 1, "three" => 1}
29+
assert WordCount.count("one,\ntwo,\nthree") == expected
30+
end
31+
2032
@tag :pending
2133
test "ignore punctuation" do
2234
expected = %{"car" => 1, "carpet" => 1, "as" => 1, "java" => 1, "javascript" => 1}
@@ -43,13 +55,65 @@ defmodule WordCountTest do
4355

4456
@tag :pending
4557
test "normalize case" do
46-
expected = %{"go" => 3}
47-
assert WordCount.count("go Go GO") == expected
58+
expected = %{"go" => 3, "stop" => 2}
59+
assert WordCount.count("go Go GO Stop stop") == expected
60+
end
61+
62+
@tag :pending
63+
test "with apostrophes" do
64+
expected = %{"first" => 1, "don't" => 2, "laugh" => 1, "then" => 1, "cry" => 1}
65+
assert WordCount.count("First: don't laugh. Then: don't cry.") == expected
66+
end
67+
68+
@tag :pending
69+
test "with quotations" do
70+
expected = %{"joe" => 1, "can't" => 1, "tell" => 1, "between" => 1, "large" => 2, "and" => 1}
71+
assert WordCount.count("Joe can't tell between 'large' and large.") == expected
72+
end
73+
74+
@tag :pending
75+
test "with quotations at the end at the beginning of the sentence" do
76+
expected = %{"venti" => 1, "in" => 1, "italian" => 1, "means" => 1, "twenty" => 1}
77+
assert WordCount.count("'venti' in Italian means 'twenty'") == expected
78+
end
79+
80+
@tag :pending
81+
test "substrings from the beginning" do
82+
expected = %{
83+
"joe" => 1,
84+
"can't" => 1,
85+
"tell" => 1,
86+
"between" => 1,
87+
"app" => 1,
88+
"apple" => 1,
89+
"and" => 1,
90+
"a" => 1
91+
}
92+
93+
assert WordCount.count("Joe can't tell between app, apple and a.") == expected
94+
end
95+
96+
@tag :pending
97+
test "multiple spaces not detected as a word" do
98+
expected = %{"multiple" => 1, "whitespaces" => 1}
99+
assert WordCount.count(" multiple whitespaces") == expected
100+
end
101+
102+
@tag :pending
103+
test "alternating word separators not detected as a word" do
104+
expected = %{"one" => 1, "two" => 1, "three" => 1}
105+
assert WordCount.count(",\n,one,\n ,two \n 'three'") == expected
48106
end
49107

50108
@tag :pending
51109
test "German" do
52110
expected = %{"götterfunken" => 1, "schöner" => 1, "freude" => 1}
53111
assert WordCount.count("Freude schöner Götterfunken") == expected
54112
end
113+
114+
@tag :pending
115+
test "Polish" do
116+
expected = %{"a" => 1, "w" => 1, "piątym" => 1, "stoi" => 1, "sześć" => 1, "fortepianów" => 1}
117+
assert WordCount.count("A w piątym stoi sześć fortepianów") == expected
118+
end
55119
end

0 commit comments

Comments
 (0)