forked from pcewing/programming-elixir-exercises
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathword_count.exs
66 lines (57 loc) · 1.79 KB
/
word_count.exs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
defmodule WordCounter do
def count(scheduler) do
send scheduler, {:ready, self}
receive do
{:count, file, word, client} ->
send client, {:answer, file, word, count_word(file, word), self}
count(scheduler)
{:shutdown} ->
exit(:normal)
end
end
def count_word(file, word) do
content = File.read!(file)
tokens = String.split(content, word)
length(tokens) - 1
end
end
defmodule Scheduler do
def run(num_processes, module, func, directory, word) do
{:ok, files} = File.ls(directory)
files = Enum.map(files, fn file -> Path.join(directory, file) end)
(1..num_processes)
|> Enum.map(fn(_) -> spawn(module, func, [self]) end)
|> schedule_processes(files, word, Map.new)
end
defp schedule_processes(processes, queue, word, results) do
receive do
{:ready, pid} when length(queue) > 0 ->
[next | tail] = queue
send pid, {:count, next, word, self}
schedule_processes(processes, tail, word, results)
{:ready, pid} ->
send pid, {:shutdown}
if length(processes) > 1 do
schedule_processes(List.delete(processes, pid), queue, word, results)
else
results
end
{:answer, file, _word, result, _pid} ->
schedule_processes(processes, queue, word, Map.put(results, file, result))
end
end
end
defmodule Runner do
def run do
directory = "test_files/"
word = "cat"
Enum.each 1..10, fn num_processes ->
{time, result} = :timer.tc(Scheduler, :run, [num_processes, WordCounter, :count, directory, word])
if num_processes == 1 do
IO.puts "\nInspecting the results:\n#{inspect result}\n\n"
IO.puts "\n # time (ms)"
end
:io.format "~2B ~.2f~n", [num_processes, time/1000.0]
end
end
end