The next language in the book was Erlang. Before I give my answers for the first two days of Erlang, I will introduce the language itself.
Erlang was initially developed by Ericsson. It is specifically attributed to Joe Armstrong. The name can stand for Ericsson Language or danish mathematecian’s Agner Erlang name.
Some of the features of the language include a powerful concurrency model, hot swapping of modules and the ability to easily monitor and restart modules. Even without taking these features into consideration, the language offers an interesting proposition for programmers.
Erlang is one of the languages in the book to which I took a particular liking. I like the syntax and how the functional nature of the language is expressed.
The syntax borrows from Prolog, which is a good thing in my book. The programming model on the other hand, is nothing like Prolog.
Here are my answers to the questions for Erlang’s first chapter.
Using recursion, write a function that counts the number of words in a string.
% Erland Day 1 Q 1
-module(day1q1).
-export([number_of_words/1]).
number_of_words(S) -> number_of_words_recursive(string:tokens(S, " ")).
number_of_words_recursive([]) -> 0;
number_of_words_recursive(S) -> [Head | NewList] = S,
1 + number_of_words_recursive(NewList).
Count to ten using recursion.
% Erlang day 1 q 2
-module(day1q2).
-export([count_to_ten/0]).
count_to_ten() -> count_to_ten(1).
count_to_ten(10) -> io:write(10);
count_to_ten(I) -> io:write(I),
count_to_ten(I + 1).
Use matching to either print “success” or “error: ” accompanied with a specified error message. The function must take an input of the form: {error, Message}.
% Erlang day1 q 3
-module(day1q3).
-export([error_or_success/1]).
error_or_success(success) -> io:fwrite(success);
error_or_success({error, Y}) -> io:fwrite(error),
io:fwrite(":"),
io:fwrite(Y).
And now here are my solutions for Seven Seven Languages in Seven Weeks Erlang Day 2 chapter.
Write a function that takes a list of key-value tuples and a key. The function must return the associated value.
-module(day2q1).
-export([test/2]).
print_value(Value) -> io:format("~p~n", [Value]).
test(List, Keyword) -> [print_value(Value) || {Key, Value} <- List, Key =:= Keyword].
Write a function that uses a list comprehension to transform a list of the form [{item, quantity, price}, …] into the form [{item total_price}, …].
-module(day2q2).
-export([price/1]).
price(List) -> [{Item, Quantity * Price} || {Item, Quantity, Price} <- List].
Example usage:
6> day2q2:price([{book, 2, 4}, {tootbrush, 5, 5}]).
[{book,8},{tootbrush,25}]
And now, the bonus question…
Write a program that takes a Tic Tac Toe board in the form of a tuple of size nine. Return the winner or lack of thereof (cat).
In an earlier post, I mentioned a Tic Tac Toe solver I had came up with, and how I had found a better solution. Well here it is.
I found this approach a lot simpler than what I did in Scala. The code is twenty one lines, three of which are white spaces and another three which are comments. So fifteen lines total.
-module(day2q3).
-export([tic_tac_toe/1]).
%WinningPaths = [{1, 2, 3}, {4, 5, 6}, {7, 8, 9},
% {1, 4, 6}, {2, 5, 8}, {3, 6, 9},
% {1, 5, 9}, {7, 5, 3}].
tic_tac_toe({Z, Z, Z, _, _, _, _, _, _}) -> io:format("Winner: ~p~n", [Z]);
tic_tac_toe({_, _, _, Z, Z, Z, _, _, _}) -> io:format("Winner: ~p~n", [Z]);
tic_tac_toe({_, _, _, _, _, _, Z, Z, Z}) -> io:format("Winner: ~p~n", [Z]);
tic_tac_toe({Z, _, _, Z, _, _, Z, _, _}) -> io:format("Winner: ~p~n", [Z]);
tic_tac_toe({_, Z, _, _, Z, _, _, Z, _}) -> io:format("Winner: ~p~n", [Z]);
tic_tac_toe({_, _, Z, _, _, Z, _, _, Z}) -> io:format("Winner: ~p~n", [Z]);
tic_tac_toe({Z, _, _, _, Z, _, _, _, Z}) -> io:format("Winner: ~p~n", [Z]);
tic_tac_toe({_, _, Z, _, Z, _, Z, _, _}) -> io:format("Winner: ~p~n", [Z]);
tic_tac_toe(List) -> Empty_Squares = lists:any(fun(X) -> X == ' ' end, tuple_to_list(List)),
if
Empty_Squares == true -> io:format("No winner. ~n");
Empty_Squares == false -> io:format("cat ~n")
end.
Basically, this is very similar to how I would solve the problem in Prolog. First I define all the winning scenarios, then I handle the two other cases.
Of course, this approach still has a couple of problems. It does not validate the board in any way. I can see multiple ways to break this by sending invalid boards (ie: a full board made up only of X). Also it treats empty spaces as a player.
In a full Tic Tac Toe game, I would ensure that the function that updates the board cannot send it in an invalid state and also validate the consistency of board in regards to the rules of Tic Tac Toe.