I’ve recently been using the word chains kata for interviewing, and I thought it might be interesting to try using Erlang, and property testing.
The first step is to get a word list. I thought most linux distros came with a dictionary file, but my laptop only had a crack lib, which wasn’t really what I was looking for.
I had used this npm package before, so I just downloaded the text file it provides. With that hand, getting a list of words is easy:
word_list() ->
{ok, Data} = file:read_file("words.txt"),
binary:split(Data, [<<"\n">>], [global]).
The next step is to find all words that are one letter away from the first word. So we create a property:
prop_next_word_should_be_new() ->
?FORALL({FirstWord, LastWord}, valid_words(),
begin
NextWord = word_chains:next_word(FirstWord, LastWord),
NextWord =/= FirstWord
end).
For each first word/last word pair, we check that the next word is different from the first word. We also need a generator, of valid words:
valid_words() ->
?SUCHTHAT({FirstWord, LastWord},
?LET(N, choose(2, 10),
begin
WordList = word_chains:word_list(),
SameLengthWords = lists:filter(fun(W) -> length(W) =:= N end, WordList),
{random_word(SameLengthWords), random_word(SameLengthWords)}
end),
FirstWord =/= LastWord).
random_word(Words) ->
lists:nth(rand:uniform(length(Words)), Words).
First we pick a random number, in the range (2, 10), and then pick 2 words of that length, from the full word list, at random. This could result in the same word being used as both first & last word, so we filter that out, using the ?SUCHTHAT macro.
For now, we can make this pass by simply returning the last word:
next_word(_FirstWord, LastWord) ->
LastWord.
$ ./rebar3 proper
===> Verifying dependencies...
===> Compiling word_chains
===> Testing prop_word_chains:prop_next_word_should_be_new()
....................................................................................................
OK: Passed 100 test(s).
===>
1/1 properties passed
Boom! Next time, a more useful implementation of next word.