Conway's Game of Life in Erlang, in 2 hours, with 0 Erlang experience, in 20 lines of code.
1337 h4x0rs:
- @jszmajda
- @ngauthier
- @ericoestrich
- @danivovich
- @kafuchau
Later refactored and enhanced by @seancribbs
-module(gol). | |
-export([transmute_world/1, display/1, run/2]). | |
lives(2,true) -> | |
true; | |
lives(3,_) -> | |
true; | |
lives(_,_) -> | |
false. | |
%% neighbors1(Xin,Yin, World) -> | |
%% length([ | |
%% true || {X, Y, true} <- World, | |
%% X >= Xin - 1, X <= Xin + 1, | |
%% Y >= Yin - 1, Y <= Yin + 1, | |
%% not (X == Xin andalso Y == Yin) | |
%% ]). | |
neighbors2(Xin, Yin, World) -> | |
Neighbors = [ {Xin + X, Yin + Y} || | |
X <- [-1, 0, 1], | |
Y <- [-1, 0, 1], | |
not (X == 0 andalso Y == 0)], | |
length([ true || {X, Y} <- Neighbors, | |
{XW, YW, true} <- World, | |
X == XW andalso Y == YW]). | |
transmute_world(World) -> | |
[ {X, Y, lives(neighbors2(X,Y, World), Alive)} || {X,Y,Alive} <- World ]. | |
sort_by_rows({_, Y0, _}, {_, Y1, _}) when Y0 < Y1 -> | |
true; | |
sort_by_rows({X0, Y, _}, {X1, Y, _}) when X0 < X1 -> | |
true; | |
sort_by_rows(_, _) -> false. | |
cell_to_display_fold({_X, Y, Alive}, {Row, Output}) -> | |
Char = case Alive of | |
true -> $X; | |
false -> $. | |
end, | |
case Row of | |
Y -> {Row, [Char|Output]}; | |
_ -> {Y, [Char, $\n| Output]} | |
end. | |
display(World) -> | |
%% sort by Y so we get rows together | |
World1 = lists:sort(fun sort_by_rows/2, World), | |
%% Turn the true/false into strings for output, adding line returns after rows | |
{_Row, Output} = lists:foldl(fun cell_to_display_fold/2, {0, []}, World1), | |
%% Clear the screen and print the board at the top left. | |
io:format("\e[2J\e[0;0H~ts~n", [lists:reverse(Output)]). | |
run(World, None) when None =< 0 -> | |
World; | |
run(World, Iters) -> | |
display(World), | |
timer:sleep(500), | |
run(transmute_world(World), Iters - 1). |