新規ドキュメント


忘れていく脳のための備忘録
by w_l_s
プロフィールを見る
画像一覧

プロセスの輪っかを作る

オライリーの Erlang 本にあった問題を解いてみたけど、思いのほか時間がかかった。

N 個のプロセスを作り、輪になるようにつなげましょう、という問題。
ring:start(M. N, Msg) の形に沿って無いけど、ひとまずそれっぽい動きをしてくれる。

-module(process2).
-export([start/0, child/0]).

start() ->
register(echo, spawn(process2, child, [])),
echo ! {self(), 5},
receive
{_Pid, Msg} ->
io:format("~w~n", [Msg]);
child_end ->
io:format("Return to start process.~n")
end,
echo ! stop.

child() ->
receive
{From, Count} when Count > 0 ->
Pid = spawn(process2, child, []),
io:format("self pid = ~w~n", [self()]),
io:format("child: ~w~n", [Count]),
io:format("~w~n", [Pid]),
Pid ! {From, Count - 1},
child(Pid);
{From, 0} ->
io:format("terminal~n"),
From ! child_end;
stop ->
io:format("child/0 stop"),
true
end.
child(NextPid) ->
receive
stop ->
io:format("stoping ~w~n", [self()]),
io:format("child/1 stop~n"),
NextPid ! stop
end.


実行するコードがなくなるとプロセスが終了してしまうので、作ったプロセスの ID を引数に持つchild/1 を呼び出している。こいつは終了メッセージを受け取って、自分が生成した子プロセスに終了メッセージを送信して終了する。後片付けするためだけの関数です。

プロセスが消える条件をすっかり忘れていたので、最初はすでに消えたプロセスにメッセージを送ったりして大変でした。
[PR]
by w_l_s | 2011-08-09 01:29 | erlang

関数の評価順

オライリー本の最初でつまずいた。
エクササイズの 3-3 で、偶数なら表示しろという問題が出てきたので、以下のプログラムを書いた

-module(print).
-export([print/1, print/2, even_print/1, even_print/2]).

print(N) when N > 0 ->
print(1, N).
print(C, N) when C < N ->
io:format("Number:~p~n", [C]),
print(C + 1, N);
print(C, N) when C == N ->
io:format("Number:~p~n", [C]).

even_print(N) ->
even_print(1, N).
even_print(C, N) when (C rem 2) == 0 ->
io:format("Number:~p~n", [C]),
even_print(C + 1, N);
even_print(C, N) when (C rem 2) /= 0 ->
even_print(C + 1, N);
even_print(C, N) when C == N ->
print(C, N).

これで even_print() を動かすと、無限に表示を続けてしまう。
どうやら、ソースコードの上から順番にガードを評価して関数を選んでるみたい。


-module(print).
-export([print/1, print/2, even_print/1, even_print/2]).

print(N) when N > 0 ->
print(1, N).
print(C, N) when C < N ->
io:format("Number:~p~n", [C]),
print(C + 1, N);
print(C, N) when C == N ->
io:format("Number:~p~n", [C]).

even_print(N) ->
even_print(1, N).
even_print(C, N) when C == N ->
print(C, N);
even_print(C, N) when (C rem 2) == 0 ->
io:format("Number:~p~n", [C]),
even_print(C + 1, N);
even_print(C, N) when (C rem 2) /= 0 ->
even_print(C + 1, N).

順番を変えて、最初に C == N かどうかを確認させたら意図した動きになった。

ガードの中身を考え直すか、関数で条件分岐するべきかな?
[PR]
by w_l_s | 2011-05-20 01:05 | erlang

erlangでproject eulerを解く

project euler 1問目
1000未満の数のうち、3か5の倍数の和を求める。

まるで手続き型言語のようなソース!

int_arrayで数字のリストを作り、euler_01_solverでリストから一個ずつ数字を取り出す。取り出した数字をadderに突っ込んで、条件にあえば足し算して結果を返す。

euler_01_solverは、リストが空になるまで自己再帰を行う。
リストが空になると最後の数字をadderに突っ込んで計算を行う。
その結果を一個前のeuler_01_solverに返し、一個前に取り出した数字とその結果をadderに入れて計算し、というのを繰り返す。

  1 -module(euler_01).
2 -export([int_array/2, int_array/3]).
3 -export([euler_01/2, euler_01_solver/2, adder/2]).
4
5 int_array(X, Y) ->
6 if
7 X < Y ->
8 int_array(X + 1, Y, [X]);
9 true ->
10 false
11 end.
12
13 int_array(X, Y, List) ->
14 if
15 X < Y ->
16 int_array(X + 1, Y, [X | List]);
17 X == Y ->
18 lists:reverse([X | List]);
19 true ->
20 false
21 end.
22
23 euler_01(X, Y) when is_integer(Y) == true ->
24 List = int_array(X, Y),
25 euler_01_solver(0, List).
26
27 euler_01_solver(All, [X | Y]) when is_list(Y) == true ->
28 if
29 Y == [] ->
30 adder(All, X);
31 Y /= [] ->
32 Value = euler_01_solver(All, Y),
33 adder(Value, X)
34 end.
35
36
37 adder(All, X) ->
38 if
39 X rem 3 =:= 0; X rem 5 =:= 0 ->
40 All + X;
41 true ->
42 All
43 end.


追記
会社でいいアルゴリズムを教えてもらったのでそれでといてみた。
ソースがだいぶ短くなったよ。

  1 -module(euler_01_another).
2
3 -export([euler_01_ask/1, sequence_adder/1]).
4
5 euler_01_ask(X) ->
6 sequence_adder(trunc(X / 3)) * 3 +
7 sequence_adder(trunc(X / 5)) * 5 -
8 sequence_adder(trunc(X / 15)) * 15.
9
10 sequence_adder(X) ->
11 if
12 X > 0 ->
13 Value = sequence_adder(X - 1),
14 Value + X;
15 true ->
16 X
17 end.


1 ~ 1000までの数値のうち、3の倍数の数は 1000 / 3 = 333(個)
その和は(1 + 2 + ... + 333) * 3で求められる。
同じように5の倍数の時を計算して足し合わせ、3と5の最小公倍数である15の倍数の和を引けば出来上がり。
[PR]
by w_l_s | 2010-06-18 06:07 | erlang

CentOS5.2にerlangをインストールする

CentOS5.2にerlang(otp_src_R12B-4)をインストールする際、make中にエラーが起きてインストールできなかった。

対策を探して見ると、ここのページを発見。この修正を行うとすんなりインストールできた。(kgbuさんに感謝!)

-------------------- 修正内容 --------------------
--- lib/ssl/c_src/Makefile.in2008-03-27 13:43:04.000000000 +0300
+++ lib/ssl/c_src/Makefile.in2008-03-27 14:03:27.000000000 +0300
@@ -38,7 +38,7 @@
CC = @CC@
LD = @LD@
SHELL = /bin/sh
-LIBS = @LIBS@
+LIBS = @LIBS@ -lkeyutils -lselinux
PLAIN_CFLAGS = @CFLAGS@
------------------------------------------------

以前もCentOSにerlangを入れようとしてだめだったんだけど、これのせいだったのかな?
[PR]
by w_l_s | 2008-11-02 01:36 | erlang

カテゴリ

全体
erlang
Python
c言語
作って遊ぼう
シェルスクリプト
OS
javascript
jQuery
反省
vim
未分類

お気に入りブログ

メモ帳

最新のトラックバック

ライフログ

検索

タグ

ファン

記事ランキング

ブログジャンル

画像一覧