Language detail: Erlang
|
number of '+' ratings |
contribution for coverage |
Unsolved challenges
- リングノードベンチマーク (Nested Flatten)
- メソッド数の多い組み込みクラスを列挙 (Nested Flatten)
- 初期設定の読み書き (Nested Flatten)
- printf書式変換 (Nested Flatten)
- loan patternのサンプル (Nested Flatten)
codes
Erlang初投稿です。よろしくお願いします。 とりあえず、システムコールを呼ぶ回数を1回にしました。 erlide(Eclipse)で確認しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | -module(file_size).
-export([file_size/1]).
-include_lib("kernel/include/file.hrl").
file_size(Name) ->
try file:read_file_info(Name) of
{ok,Fileinfo} ->
case Fileinfo#file_info.type of
regular ->
io:format("~B~n",[Fileinfo#file_info.size]);
_ -> ok % except file
end;
_ -> ok % cannot get infomation
catch
_ -> ok % exception
end.
|
file_size.erlで保存し、以下のように実行します。:
$ erl -noshell -s file_size file_size file_size.erl -s init stop 189
存在しないファイル(例えばdummy.txtとする)を指定すると、何も表示されません。:
$ erl -noshell -s file_size file_size dummy.txt -s init stop
1 2 3 4 5 6 7 8 | -module(file_size).
-export([file_size/1]).
file_size(Name) ->
case filelib:is_file(Name) of
false -> ok;
true -> io:format("~B~n", [filelib:file_size(Name)])
end.
|
1 2 3 4 5 6 7 8 9 10 11 | -module(exception).
-export([exception/0]).
f() -> throw("exception").
exception() ->
X = try f()
catch
throw : Y -> "catch : " ++ Y
end,
io:format(X).
|
Erlang のプレーンな例は、他の方が解答されていましたので、あえて lists ライブラリを積極的に使ったパターンを投稿してみます。 ミソは、終了メッセージの選択受信かな?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | -module(doukaku215).
-author('cooldaemon@gmail.com').
-export([run/0]).
run() ->
Pid = self(),
lists:foreach(
fun (CPid) -> receive {CPid, finish} -> ok end end,
lists:map(
fun (Cs) -> spawn(fun () ->
lists:foreach(fun (C) -> io:fwrite("~s", [[C]]) end, Cs),
Pid ! {self(), finish}
end) end,
lists:map(fun (N) -> lists:seq(N, N+8) end, [$1, $A])
)
).
|
以下のようにして実行します。 erlc para.erl erl -noshell -s para para -s init stop
1 2 3 4 5 6 7 8 9 10 11 12 13 | -module(para).
-export([para/0]).
proc(Pid, []) -> Pid ! void;
proc(Pid, [Chr | Str]) ->
io:format("~s", [[Chr]]),
proc(Pid, Str).
para() ->
Pid = self(),
spawn(fun() -> proc(Pid, "0123456789") end),
spawn(fun() -> proc(Pid, "ABCDEFGHIJ") end),
receive _ -> receive _ -> void end end.
|
実行方法: $ cat hoge.txt ID Surname Forename Age 1 Sato Hanako 17 0 Suzuki Taro 18 $ erlc doukaku7723.erl $ erl -noshell -s doukaku7723 main hoge.txt -s init stop ID Forename Surname Age 0 Taro Suzuki 19 1 Hanako Sato 18
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | -module(doukaku7723).
-export([main/1]).
main(Filename) ->
{ok, Bin} = file:read_file(Filename),
A1 = string:tokens(binary_to_list(Bin), "\r\n"),
[H | T] = lists:map(curry(flip(fun string:tokens/2), "\t"), A1),
A2 = lists:map(fun swap23inc4/1, T),
A3 = lists:sort(fun([E1|_], [E2|_]) -> list_to_integer(E1) < list_to_integer(E2) end, A2),
A4 = lists:map(func_comp(fun lists:concat/1, curry(fun intersperse/2, "\t")), [swap23(H) | A3]),
A5 = lists:concat(intersperse("\r\n", A4)),
io:format("~s~n", [A5]).
swap23([A,B,C,D | Rest]) -> [A,C,B,D|Rest].
swap23inc4([A,B,C,D | Rest]) -> [A,C,B,integer_to_list(1+list_to_integer(D)) | Rest].
intersperse(_, []) -> [];
intersperse(_, [X]) -> [X];
intersperse(Sep, [X | XS]) -> [X, Sep | intersperse(Sep, XS)].
curry(F, A) -> fun(B) -> F(A, B) end.
flip(F) -> fun(A, B) -> F(B, A) end.
func_comp(F, G) -> fun(X) -> F(G(X)) end.
|
echoのプロトコル(RFC862)に詳しくないのですが、サーバ側からデータの終わり(eofなど)が返ってこないようなので、タイムアウト(10秒)を設定してみました(汗
送信したデータと比較して、同じならcloseする条件もつけました。
escriptが利用可能な環境であれば、以下のようにコマンドラインから実行可能です。
$ ./スクリプト名 localhost 7 < testfile > newfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #!/usr/bin/env escript
main([Hostname, Port])->
Str = loop(io:get_line(standard_io,''), []),
Res = gen_tcp:connect(Hostname,
list_to_integer(Port),
[binary, {packet, 0}]),
case Res of
{ok, Socket} ->
ok = gen_tcp:send(Socket, Str),
receive_data(Socket, [], lists:flatten(Str));
{error, Why} -> io:format("error ~p~n", [Why]), exit(eError)
end.
receive_data(Socket, _Original, _Original) ->
gen_tcp:close(Socket);
receive_data(Socket, SoFar, Original) ->
receive
{tcp, Socket, Bin} ->
Lines = binary_to_list(Bin),
io:format("~s", [Lines]),
receive_data(Socket, lists:flatten(SoFar ++ [Lines]), Original);
{tcp_closed, Socket} ->
ok
after 10000 ->
gen_tcp:close(Socket)
end.
loop(eof, SoFar)->
lists:reverse(SoFar);
loop(Data, SoFar) ->
loop(io:get_line(''), [Data|SoFar]).
|
しらみつぶしに計算してからsortする方式ですが、その境界の目処はたてるようにしてみました。 http://en.wikipedia.org/wiki/Image:Regular_divisibility_lattice.svg の図を、3次元空間のある象限に存在する三角錐とみて、それを含む直方体の中の格子点を取り出します。最低でも、およそ5/6が無駄なデータなのですが、うまく三角錐の部分だけの格子点を巡回する順序を決めるアルゴリズムが思い浮かばなかったので、そのままにしてあります。
$ erlc スクリプトのファイル名
$ erl -noshell -s len main 100 -s init stop
として実行します。
see: ハミング数
1 2 3 4 5 6 7 8 9 10 11 | -module(len).
-export([main/1]).
main([N|_]) ->
Limit = list_to_integer(atom_to_list(N)),
Factor = math:pow(Limit * math:log(5) * math:log(2)/ (math:log(2) * math:log(3)), 1 / 3),
L = lists:sort([round(math:pow(2, X)*math:pow(3,Y)*math:pow(5,Z)) ||
X <- lists:seq(0,round(1 + Factor * math:log(5) / math:log(2)) ),
Y <- lists:seq(0,round(1 + Factor * math:log(5) / math:log(3)) ),
Z <- lists:seq(0,round(1 + Factor))]),
io:format("~p~n",[lists:sublist(L,Limit)]).
|
実行するには erlc pyramid.erl erl -noshell -run pyramid main 自然数 -s init stop としてください。 http://ja.doukaku.org/comment/7419/ とは違い、0 の場合エラーになります。
1 2 3 4 5 | -module(pyramid).
-export([main/1]).
main([S])->N=list_to_integer(S),[io:format("~*c
",[N-abs(M),$*])||M<-lists:seq(1-N,N-1)].
|
#7419で投稿しましたが、push, popという関数名がそぐわない感じがしたので、 別のスタイルで書いてみました。 改行を含む文字列を前後両側に伸ばしていく感じです。 実行方法は#7419同様です。
1 2 3 4 5 6 7 8 9 10 11 12 13 | -module(pyramid).
-export([main/1]).
main([N])->
Len=list_to_integer(atom_to_list(N)),
s(Len,p(Len)).
s(0,_)->0;
s(1,S)->io:format("~s", [S]);
s(N,S)->s(N - 1, p(N - 1) ++ S ++ p(N - 1)).
p(0)-> [$\n];
p(N)-> "*" ++ p(N - 1).
|
実行するには、以下のようにコマンド入力します。 コマンドの引数として数値を与えています。 一応、0のケースも入れておきました。 erlc スクリプトファイル名 erl -noshell -s pyramid main 自然数 -s init stop 実行例 $ erl -noshell -s pyramid main 0 -s init stop $ erl -noshell -s pyramid main 1 -s init stop * $ erl -noshell -s pyramid main 3 -s init stop * ** *** ** *
1 2 3 4 5 6 7 8 9 10 11 | -module(pyramid).
-export([main/1]).
main([N])-> push(list_to_integer(atom_to_list(N)),[]).
push(0,_)->0;
push(1,L)->io:format("~s~n",[L ++ "*"]), pop(L ++ "*");
push(N,L)->io:format("~s~n",[L ++ "*"]), push(N - 1, L ++ "*").
pop("*")-> 0;
pop([_|L])-> io:format("~s~n",[L]), pop(L).
|
実行する場合は以下のようにコマンドを実行します。 数値はコマンドの引数として与えます。 erlc ファイル名 erl -noshell -s kuraidori put 数値 -s init stop 実行例 $ erl -noshell -s kuraidori put 1234567890 -s init stop 1.2G $ erl -noshell -s kuraidori put 12345678901234 -s init stop 12.3T
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | -module(kuraidori).
-export([put/1]).
put([S]) -> loop(list_to_integer(atom_to_list(S))," KMGTPEZY").
loop(S,[H|[]]) -> pr(S,H);
loop(S,[H|_]) when S < 1000 ->
if
is_integer(S) -> pri(S,H);
true -> pr(S,H)
end;
loop(S,[_|L]) -> loop(S / 1000, L).
pr(S,K) -> io:format("~.1f~s~n",[S,[K]]).
pri(S,K) -> io:format("~.10B~s~n",[S,[K]]).
|
erl_evalと Erlang特有のN進法表記(N#M, 基数Nは36以下)を 使ってみたらどうだろうと思って書いてみました。 基数に上限があるので汎用性に欠けると思います。 プログラムを bai13.erl というファイル名で保存して、 $ erl -noshell -s bai13 getfirst -s init stop のようにして起動します。
see: Erlangのevalってこうやるのか
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | -module(bai13).
-export([getfirst/0]).
getfirst() ->
loop(10).
loop(N) ->
case (eval("13#" ++ integer_to_list(N) ++ ".") rem N) of
0 -> io:format("~p~n",[N]);
true -> loop(N + 1)
end.
eval(Expr)->
{ok, Tokens, _}=erl_scan:string(Expr),
{ok,[Expression]} = erl_parse:parse_exprs(Tokens),
{value, Ret,_} = erl_eval:expr(
Expression ,erl_eval:bindings(erl_eval:new_bindings())
),
Ret.
|
Erlangのインタプリタコマンドであるescriptで実行するとしたケースです。 その場合、コードの最初の行は無視されるので、コメント行となっています。 入力となる10進数は、標準入力から与えます。 実行例(スクリプトファイル名を t.erl とします) $ escript t.erl 2 10 $
1 2 | %
main(_)->{V,_}=string:to_integer(io:get_line('')),io:format("~.2B~n",[V]).
|
スクリプト内のリテラルとして、300という整数を与えています。 escript スクリプトのファイル名 として実行します。 この場合、最初のコメント行は必須です。
1 2 3 4 5 | %
s(X,Y)when X < 10->erlang:display(Y);
s(X,Y)when X rem 10=:=0->s(X div 10,Y);
s(_,_)->0.
main(_)->[s(X,X)||X<-lists:seq(0,300)].
|
申し訳ありません、動かないコードを投稿してしまいました。
最初に投稿したものは、最初に空行が必要でした。
(escriptコマンドは、最初の行を無視するため)
最初の行をコメントとして、コードも多少短くしたものを再投稿いたします。
実行方法と結果は、以下のように、元記事と同様です。
escript スクリプトのファイル名
[{2009,2,13},
{2009,3,13},
{2009,11,13},
{2010,8,13},
{2011,5,13},
{2012,1,13},
{2012,4,13},
{2012,7,13},
{2013,9,13},
{2013,12,13}]
10 days
1 2 3 4 | %%
main(_)->M=[{X,Y,13}||{X,Y,13}<-a(date(),{2013,12,31}),calendar:day_of_the_week({X,Y,13})=:=5],io:format("~p~n~p days~n",[M,length(M)]).
a(X,X)->[X];
a(X,Y)->[X]++a(calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(X)+1),Y).
|
大元になる日付のリストは素直に1日ごとのものを生成しています。
escript ファイル名
として実行します。
実行結果例(2008/8/7に実行)
[{2009,2,13},
{2009,3,13},
{2009,11,13},
{2010,8,13},
{2011,5,13},
{2012,1,13},
{2012,4,13},
{2012,7,13},
{2013,9,13},
{2013,12,13}]
10 days
1 2 3 4 5 6 7 8 | main(_) ->
L=a(date(),{2013,12,31}),
M=[{X,Y,13} || {X,Y,13} <- L, calendar:day_of_the_week({X,Y,13}) =:= 5],
io:format("~p~n~p days~n", [M, length(M)]).
a(X,X) -> [X];
a(X,Y) -> [X] ++ a(calendar:gregorian_days_to_date(
calendar:date_to_gregorian_days(X)+1),Y).
|
Erlang 版を縮めてみました。
1 | S=string,S:join([[S:to_upper(H)]++T||[H|T]<-S:tokens("LL day and night"," ")]," ").
|
Erlang 版を 1 文字削り損ねてました。
1 | S=string,S:join([[S:to_upper(H)|T]||[H|T]<-S:tokens("LL day and night"," ")]," ").
|






yamamoto
#9149()
[
Erlang
]
Rating0/0=0.00
Scala(#9133)をErlangに移植しました。 効率はともかく、例外処理をしているので・・・
関数の仕様は、Erlang的で、成功時は {ok,****} のようなタプルが返ります。失敗時はok以外のアトム。
-module(netmask). -export([numbits_of/1,from_numbits/1,test/0]). numbits_of(StrMask) -> try {ok,Mask} = inet_parse:address(StrMask) , {Class,MaskByte} = case Mask of {255,255,255,X} -> {24,X}; {255,255, X,0} -> {16,X}; {255, X, 0,0} -> { 8,X}; _ -> throw("bad mask") end, {ok, case MaskByte of (256- 1)-> 8; (256- 2)-> 7; (256- 4)-> 6; (256- 8)-> 5; (256- 16)-> 4; (256- 32)-> 3; (256- 64)-> 2; (256-128)-> 1; 0 -> 0 end + Class }% <--- result catch throw:E -> {thrown,E}; exit :E -> {exited,E}; error:E -> {error ,E} end. from_numbits(Numbits)-> try {Class,Maskbits} = case Numbits of N when N>=24 -> {24,N-24} ; N when N>=16 -> {16,N-16} ; N when N>= 8 -> { 8,N- 8} end , Maskbyte = case Maskbits of 8 -> (256- 1) ; 7 -> (256- 2) ; 6 -> (256- 4) ; 5 -> (256- 8) ; 4 -> (256- 16) ; 3 -> (256- 32) ; 2 -> (256- 64) ; 1 -> (256-128) ; 0 -> 0 end , % {ok , case Class of 24 -> inet_parse:ntoa( {255,255,255,Maskbyte} ) ; 16 -> inet_parse:ntoa( {255,255,Maskbyte ,0} ) ; 8 -> inet_parse:ntoa( {255,Maskbyte ,0,0} ) end }% <--- result catch throw:E -> {thrown,E}; exit :E -> {exited,E}; error:E -> {error ,E} end. test()-> lists:foreach(fun(I)-> {ok , M} = from_numbits(I), {ok , N} = numbits_of(M), io:format("Numbits=~p , Mask=~p , Result=~p~n",[I,M,(I==N)]) end , lists:seq(8,31) ).Rating0/0=0.00-0+