Skip to content

Instantly share code, notes, and snippets.

@jwthomp
Created April 5, 2011 15:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jwthomp/903799 to your computer and use it in GitHub Desktop.
Save jwthomp/903799 to your computer and use it in GitHub Desktop.
Erlang implemention to solve ishmael problem
% solving Ishmael problem from http://www.renesys.com/challenge_site/challenge/count_me_ishmael
-module(ishmael).
-compile(export_all).
-define(FILENAME, "2701.txt").
time(Func) ->
Start = now(),
ishmael:Func(),
End = now(),
timer:now_diff(End, Start) / 1000.
prof() ->
eprof:start(),
Pid = self(),
eprof:start_profiling([spawn(fun() -> Diff = time(parse_only), io:format("Time: ~p~n", [Diff]), Pid ! done end)]),
receive
done -> ok
end,
eprof:stop_profiling(),
eprof:analyze(),
eprof:stop().
fprof() ->
fprof:trace([start, {file, "first.trace"}]),
ishmael:parse_only(),
fprof:trace([stop]),
fprof:profile({file, "first.trace"}),
ok = fprof:analyse([totals, {dest, "fprof.txt"}]).
start() ->
Dict = parse_only(),
List = dict:to_list(Dict),
Fun = fun
({_, Count1}, {_, Count2}) when Count1 < Count2 -> false;
({_, Count1}, {_, Count2}) when Count1 > Count2 ->true;
({Word1, _}, {Word2, _}) when Word1 >= Word2 -> false;
({Word1, _}, {Word2, _}) when Word1 < Word2 -> true
end,
lists:sort(Fun, List).
parse_only() ->
{ok, Data} = file:read_file(?FILENAME),
parse(dict:new(), Data, [], {nil, nil, nil, nil}).
dump() ->
display(start()).
display(List) ->
io:format("rank count word~n", []),
display(List, 1).
display([], _Rank) -> ok;
display([{Word, Count} | List], Rank) ->
io:format("~p ~p ~s~n", [Rank, Count, Word]),
%io:format("~s ~p~n", [Word, Count]),
display(List, Rank + 1).
% New word cases
parse(Dict, <<"\r\n", SourceString/binary>>, Word, CVVC) ->
case CVVC of
{c, v, v, c} -> NewDict = dict:update_counter(lists:reverse(Word), 1, Dict);
_ -> NewDict = Dict
end,
parse(NewDict, SourceString, [], {nil, nil, nil, nil});
parse(Dict, <<" ", SourceString/binary>>, Word, CVVC) ->
case CVVC of
{c, v, v, c} -> NewDict = dict:update_counter(lists:reverse(Word), 1, Dict);
_ -> NewDict = Dict
end,
parse(NewDict, SourceString, [], {nil, nil, nil, nil});
% Pull a character and move on through rest of word
parse(Dict, <<Char:8, SourceString/binary>>, Word, {c, v, v, c}) ->
LowerChar = string:to_lower(Char),
case LowerChar of
_ when ((LowerChar >= $a) and (LowerChar =< $z)) -> parse(Dict, SourceString, [LowerChar | Word], {c, v, v, c});
_ -> parse(Dict, SourceString, Word, {c, v, v, c})
end;
parse(Dict, <<Char:8, SourceString/binary>>, Word, {A, B, C, D}) ->
LowerChar = string:to_lower(Char),
case ((LowerChar == $a) or (LowerChar == $e) or (LowerChar == $i) or (LowerChar == $o) or (LowerChar == $u)) of
true -> parse(Dict, SourceString, [LowerChar | Word], {B, C, D, v});
false ->
case LowerChar of
_ when ((LowerChar >= $a) and (LowerChar =< $z)) -> parse(Dict, SourceString, [LowerChar | Word], {B, C, D, c});
_ -> parse(Dict, SourceString, Word, {A, B, C, D})
end
end;
% Hit end of data so return
parse(Dict, <<>>, Word, CVVC) ->
case CVVC of
{c, v, v, c} -> dict:update_counter(Word, 1, Dict);
_ -> Dict
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment