Skip to content

Instantly share code, notes, and snippets.

@OJ
Created December 31, 2009 12:00
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 OJ/266708 to your computer and use it in GitHub Desktop.
Save OJ/266708 to your computer and use it in GitHub Desktop.
%% @author OJ Reeves <oj@buffered.io>
%%
%% My first crappy attempt at Dave Thomas' 6th Code Kata
%% (located at http://codekata.pragprog.com/2007/01/kata_six_anagra.html)
%%
%% Extra bits are now done.
%%
%% Refactored some small bits, and made changes based on suggestions from
%% the guys on Google Wave.
-module(anagrams).
-author('OJ Reeves <oj@buffered.io>').
-export([list/1]).
list(FileName) ->
Words = file_to_list(FileName),
Grouped = group(Words),
Anagrams = lists:filter(fun({_, W}) -> length(W) > 1 end, Grouped),
{_, Longest} = find_by(fun longest/2, Anagrams),
{_, Biggest} = find_by(fun biggest/2, Anagrams),
io:format("Anagrams List:~n", []),
lists:map(fun({_, W}) -> io:format("~s~n", [to_string(W)]) end, Anagrams),
io:format("Biggest Anagram Set: ~s (~p items)~n", [to_string(Biggest), length(Biggest)]),
io:format("Longest Anagram: ~s (~p chars)~n", [to_string(Longest), length(hd(Longest))]).
to_string(List) ->
string:join(List, " ").
longest_list({L1,R1}, {L2,R2}) ->
Diff = length(L1) - length(L2),
if
Diff < 0 -> R2;
true -> R1
end.
longest(Elem={E, _}, Acc={A, _}) ->
longest_list({E, Elem}, {A, Acc}).
biggest(Elem={_, E}, Acc={_, A}) ->
longest_list({E, Elem}, {A, Acc}).
find_by(Fun, [H|Anagrams]) ->
lists:foldl(Fun, H, Anagrams).
group(Words) ->
KeyVals = lists:map(fun(Word) -> {lists:sort(Word), Word} end, Words),
Sorted = lists:keysort(1, KeyVals),
Grouped = group_by(fun key_equals/2, Sorted),
flatten(Grouped).
flatten(List) ->
Fun = fun(SubList=[{H,_}|_]) -> {H, lists:map(fun({_, W}) -> W end, SubList)} end,
lists:map(Fun, List).
key_equals({X, _}, {Y, _}) ->
X =:= Y.
group_by(_Fun, []) ->
[];
group_by(Fun, [H|T]) ->
{Ys, Zs} = span(fun(X) -> Fun(X, H) end, T),
Front = [H|Ys],
Back = group_by(Fun, Zs),
[Front|Back].
span(_Fun, []) ->
{[], []};
span(Fun, List=[H|T]) ->
case Fun(H) of
true ->
{Ys, Zs} = span(Fun, T),
{[H|Ys], Zs};
_ ->
{[], List}
end.
file_to_list(FileName) ->
{ok, Bin} = file:read_file(FileName),
string:tokens(binary_to_list(Bin), "\n").
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment