Code Language: erlang

Re: Naïve quick sort

Refactoring of: Naïve quick sort

Language: Erlang

qsort([]) -> [];
qsort([H|T]) ->
  {Bigger,Smaller} = lists:partition(fun(N) -> N > H end, T),
  qsort(Smaller) ++ [H] ++ qsort(Bigger).
Reveal More
Added over 1 year ago by Segal-avatar_normal zdzolton

Naïve quick sort

Language: Erlang

qsort([]) -> [];
qsort([H|T]) ->
  Smaller = [N || N <- T, N =< H],
  Bigger = [N || N <- T, N > H],
  qsort(Smaller) ++ [H] ++ qsort(Bigger).
Reveal More
Added over 1 year ago by Segal-avatar_normal zdzolton

map/reduce with erlang

Language: Erlang

-module(mapreduce).
-export([reduce_task/2, map_task/2,
        test_reduce_task/0, test_map_reduce/0,
        repeat_exec/2]).

%%% Execute the function N times,
%%%   and put the result into a list
repeat_exec(N,Func) ->
 lists:map(Func, lists:seq(0, N-1)).
 

%%% Identify the reducer process by
%%%   using the hashcode of the key
find_reducer(Processes, Key) ->
 Index = erlang:phash(Key, length(Processes)),
 lists:nth(Index, Processes).

%%% Identify the mapper process by random
find_mapper(Processes) ->
 case random:uniform(length(Processes)) of
   0 ->
     find_mapper(Processes);
   N ->
     lists:nth(N, Processes)
 end.

%%% Collect result synchronously from
%%%   a reducer process
collect(Reduce_proc) ->
 Reduce_proc ! {collect, self()},
 receive
   {result, Result} ->
     Result
 end.

%%% The entry point of the map/reduce framework
map_reduce(M, R, Map_func,
          Reduce_func, Acc0, List) ->

 %% Start all the reducer processes
 Reduce_processes =
   repeat_exec(R,
     fun(_) ->
       spawn(mapreduce, reduce_task,
             [Acc0, Reduce_func])
     end),

 io:format("Reduce processes ~w are started~n",
           [Reduce_processes]),

 %% Start all mapper processes
 Map_processes =
   repeat_exec(M,
     fun(_) ->
       spawn(mapreduce, map_task,
             [Reduce_processes, Map_func])
     end),

 io:format("Map processes ~w are started~n",
           [Map_processes]),

 %% Send the data to the mapper processes
 Extract_func =
   fun(N) ->
     Extracted_line = lists:nth(N+1, List),
     Map_proc = find_mapper(Map_processes),
     io:format("Send ~w to map process ~w~n",
               [Extracted_line, Map_proc]),
     Map_proc ! {map, Extracted_line}
   end,

 repeat_exec(length(List), Extract_func),

 timer:sleep(2000),

 %% Collect the result from all reducer processes
 io:format("Collect all data from reduce processes~n"),
 All_results =
   repeat_exec(length(Reduce_processes),
     fun(N) ->
       collect(lists:nth(N+1, Reduce_processes))
     end),
 lists:flatten(All_results).

%%% The mapper process
map_task(Reduce_processes, MapFun) ->
 receive
   {map, Data} ->
     IntermediateResults = MapFun(Data),
     io:format("Map function produce: ~w~n",
               [IntermediateResults ]),
     lists:foreach(
       fun({K, V}) ->
         Reducer_proc =
           find_reducer(Reduce_processes, K),
         Reducer_proc ! {reduce, {K, V}}
       end, IntermediateResults),

     map_task(Reduce_processes, MapFun)
 end.

%%% The reducer process
reduce_task(Acc0, ReduceFun) ->
 receive
   {reduce, {K, V}} ->
     Acc = case get(K) of
             undefined ->
               Acc0;
             Current_acc ->
               Current_acc
           end,
     put(K, ReduceFun(V, Acc)),
     reduce_task(Acc0, ReduceFun);
   {collect, PPid} ->
     PPid ! {result, get()},
     reduce_task(Acc0, ReduceFun)
 end.

%%% Testing of Map reduce using word count
test_map_reduce() ->
 M_func = fun(Line) ->
            lists:map(
              fun(Word) ->
                {Word, 1}
              end, Line)
          end,

 R_func = fun(V1, Acc) ->
            Acc + V1
          end,

 map_reduce(3, 5, M_func, R_func, 0,
            [[this, is, a, boy],
             [this, is, a, girl],
             [this, is, lovely, boy]]).
Reveal More
Added almost 2 years ago by Twitterprofilephoto_normal zh

Conway's Life game with mochiweb

Language: Erlang

-module(conway).
-export([mochiweb_request/1, start/1, handle_request/2]).

start(PortString) ->
    %{Port, _} = string:to_integer(PortString),
    Port = 3001,
    mochiweb_http:start([{port, Port}, {loop, {?MODULE, mochiweb_request}}]), receive stop -> stop end.

% http://www.trapexit.org/String_join_with
string_join(Items, Sep)               -> lists:flatten(lists:reverse(string_join1(Items, Sep, []))).
string_join1([Head | []], _Sep, Acc)  -> [Head | Acc];
string_join1([Head | Tail], Sep, Acc) -> string_join1(Tail, Sep, [Sep, Head | Acc]).

random_matrix(XSize, YSize) ->
    array:from_list([random:uniform(2)-1 ||  _ <- lists:seq(1, XSize*YSize)]).

neighbor_count(CellPos, Matrix, SX, SY) ->
    X = CellPos rem SX,
    Y = erlang:trunc(CellPos/SX),

    % http://ejohn.org/apps/processing.js/examples/topics/conway.html
    lists:sum(
      [
       array:get((X + 1) rem SX      + (Y)*SX,                   Matrix),
       array:get((X)                 + ((Y + 1) rem SY)*SX,      Matrix),
       array:get((X + SX - 1) rem SX + (Y)*SX,                   Matrix),
       array:get((X)                 + ((Y + SY - 1) rem SY)*SX, Matrix),
       array:get((X + 1) rem SX      + ((Y + 1) rem SY)*SX,      Matrix),
       array:get((X + SX - 1) rem SX + ((Y + 1) rem SY)*SX,      Matrix),
       array:get((X + SX - 1) rem SX + ((Y + SY - 1) rem SY)*SX, Matrix),
       array:get((X + 1) rem SX      + ((Y + SY - 1) rem SY)*SX, Matrix)
    ]).

cell_status(2, S) -> S;
cell_status(3, _) -> 1;
cell_status(_, _) -> 0.

next_cell(CellPos, CellState, Matrix, SX, SY) ->
    Neighbors = neighbor_count(CellPos, Matrix, SX, SY),
    cell_status(Neighbors, CellState).

next_iteration(Matrix, SX, SY) ->
    array:map(fun (N, Z) -> next_cell(N, Z, Matrix, SX, SY) end, Matrix).

state_to_symbol(0) -> " ";
state_to_symbol(1) -> "#";
state_to_symbol(2) -> " \n";
state_to_symbol(3) -> "#\n".

handle_request(Req, Path) ->
     SX = 80, % size x of conway grid
     SY = 40, % size y of conway grid
     case Path of
         "/_reset" ->
             Matrix = random_matrix(SX, SY),
             put(matrix, Matrix),
             Req:ok({"text/plain", "Reset OK."});
         _ ->
             OldMatrix = get(matrix),
             Matrix = case OldMatrix of
                 undefined ->
                     random_matrix(SX, SY);
                 _ ->
                     next_iteration(OldMatrix, SX, SY)
             end,
             put(matrix, Matrix),
             % print newlines when we're at a right-edge
             PrettyGrid = array:to_list(array:map(
                                            fun (N, Cell) when N rem SX == 0, N =/= 0 -> state_to_symbol(Cell+2);
                                                (N, Cell) -> state_to_symbol(Cell) end, Matrix)
                                         ),
             Req:ok({"text/plain", PrettyGrid ++ "\n"})
     end.

mochiweb_request(Req) ->
     {Path, _, _} = mochiweb_util:urlsplit_path(Req:get(raw_path)),
     handle_request(Req, Path).
Reveal More
Added almost 2 years ago by Twitterprofilephoto_normal zh

N ring setup and M messages moving around the ring in parallel

Language: Erlang

-module(ring).
-export([benchmark/2]).
 
%% run benchmark for N processes and M messages.
benchmark(N, M) ->
        Pids = makering(N),
        for(1, M, fun() -> spawn(fun() -> start(message, Pids) end) end).
 
%% setting up the process ring for sending
%% messages & return the Pids array
makering(M)     ->
        %% create the processes
        Pids = for(1, M, fun() -> spawn(fun() -> loop() end) end),
        [Head | _T] = Pids,
        %% now setup the ring. one simple init loop to make each
        %% each process aware of its next process in the ring
        %% we need to pass Head head here as we want to connect
        %% the last process back to the head.
        connect(Head, Pids),
        %% return the Pids
        Pids.
 
%% If only two elements are left in the list just point
%% the first process to the next process. And point the
%% the last process to the first process.
connect(Head, [H, N])   ->
        H ! {next, N},
        N ! {next, Head};
%% Connect the head and the next element and move to the
%% next elements
connect(Head, [H, N | T])       ->
        H ! {next, N},
        connect(Head, [N | T]).
 
%% send message from the beggining of the 
%% ring.
start(Mesg, Pids)	->
	[Head|T] = Pids,
	Head ! {lists:last(T), Mesg, length(Pids)}.
 
%% order a mass suicide for all process nodes	
killall(Pids)	->
	lists:foreach(fun(Pid) -> Pid ! die end, Pids).
 
%% message waiting loop. waits for message and sends 
%% it to the next process node. commits sepukku if 
%% it is ordered to die.
loop()	->
	receive
		%% now that we have the next pid, we move into the
		%% the listening loop for that function. remember
		%% the loop/1 will share the same Pid as this, so
		%% no worries.
		{next, NextPid} ->
			io:format("Set next for ~p as ~p~n", [self(), NextPid]),
			wait(NextPid)
	end.
 
wait(NextPid)	->
	receive
		{From, Mesg, NumHops}	when NumHops >= 0 ->
			io:format("~w from ~p to ~p~n", [Mesg, From, self()]),
			NextPid ! {self(), Mesg, NumHops - 1},
			wait(NextPid);
		die -> void
	end.
 
%% custom for loops
for(N,N,F)	->	[F()];
for(M,N,F)	->  [F()|for(M + 1, N, F)].
Reveal More
Added almost 2 years ago by Twitterprofilephoto_normal zh

Generic Web Server/RESTful Router

Language: Erlang

-module(web_server).

-behaviour(gen_server).

-define(SERVER, ?MODULE).
-define(OK, <<"ok">>).

%% API
-export([start_link/1, dispatch_requests/1, stop/0]).

%% gen_server callbacks
%% (Same old, same old. You can skip down to the handle/2 function...)
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
    terminate/2, code_change/3]).

start_link(Port) ->
    gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []).

init([Port]) ->
    mochiweb_http:start(
        [{port, Port},
         {loop, fun(Req) -> dispatch_requests(Req) end}]),
    erlang:monitor(process, mochiweb_http),
    {ok, []}.

stop() ->
    gen_server:cast(?SERVER, stop).

dispatch_requests(Req) ->
    Path = Req:get(path),
    Action = clean_path(Path),
    handle(Action, Req).

handle_call(_Request, _From, State) ->
    Reply = ok,
    {reply, Reply, State}.

handle_cast(stop, State) ->
    {stop, normal, State};

handle_cast(_Msg, State) ->
    {noreply, State}.

handle_info({'DOWN', _, _, {mochiweb_http, _}, _}, State) ->
    {stop, normal, State};

handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, _State) ->
    mochiweb_http:stop(),
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.


%% This was ripped off from the following blog:
%% http://willcodeforfoo.com/2009/07/29/using-mochiweb-to-create-a-webframework-in-erlang/

handle(Path, Req) ->
    CleanPath = clean_path(Path),
    CAtom = erlang:list_to_atom(top_level_request(CleanPath)),    
    ControllerPath = parse_controller_path(CleanPath),
    case CAtom of
        home -> 
            IndexContents = case file:read_file("www/index.html") of
                {ok, Contents} -> 
                    Contents;
                _ -> 
                    "<html><head><title>Error</title></head><body><h1>Uh oh</h1></body></html>"
            end,
            Req:ok({"text/html", IndexContents});
        assets -> 
            Req:ok(assets:get(ControllerPath));
        ControllerAtom ->
            Body = case Req:get(method) of
                'GET' -> ControllerAtom:get(ControllerPath);
                'POST' -> ControllerAtom:post(ControllerPath, decode_data_from_request(Req));
                'PUT' -> ControllerAtom:put(ControllerPath, decode_data_from_request(Req));
                'DELETE' -> ControllerAtom:delete(ControllerPath, decode_data_from_request(Req));
                Other -> subst("Other ~p on: ~s~n", [users, Other])
            end,
            Req:ok({"text/html", Body})
    end.

%% Helper methods:

%% Parse the request body as JSON
decode_data_from_request(Req) ->
    RecvBody = Req:recv_body(),
    Data = case RecvBody of
        <<>> -> 
            erlang:list_to_binary("{}");
        Bin -> 
            Bin
    end,
    {struct, Struct} = mochijson2:decode(Data),
    Struct.

% Parse the URL path
parse_controller_path(CleanPath) ->
    case string:tokens(CleanPath, "/") of
        [] -> 
            [];
        [_RootPath|Rest] -> 
            Rest
    end.

%% Strip off the query string off the URL
clean_path(Path) ->
    case string:str(Path, "?") of
        0 -> 
            Path;
        N -> 
            string:substr(Path, 1, string:len(Path) - (N+1))
    end.

top_level_request(Path) ->
    case string:tokens(Path, "/") of
        [CleanPath|_Others] -> 
            CleanPath;
        [] -> 
            "home"
    end.
Reveal More
Added over 2 years ago by Segal-avatar_normal zdzolton

Re: Re: My initial post

Refactoring of: My initial post

Language: Erlang

%% Damn, Erlang, I forgot my periods...
-module(flowcoder).
-compile(export_all).

read_post() ->
  io:format("Thanks! We missed you!").

%% from my MacBook Pro
Reveal More
Added over 2 years ago by Segal-avatar_normal zdzolton

Re: My initial post

Refactoring of: My initial post

Language: Erlang

-module(flowcoder)
-compile(export_all)

read_post() ->
  io:format("Thanks! We missed you!").

%% from my MacBook Pro
Reveal More
Added over 2 years ago by Atclub_256_normal scottymac

My initial post

Language: Erlang

-module(flowcoder)
-compile(export_all)

read_post() ->
  io:format("Looks great, guys!").

%% from my iPhone
Reveal More
Added over 2 years ago by Segal-avatar_normal zdzolton