Chapter3
Exercise3.1: Evaluating Expression
ここいらはお茶の子さいさいですな〜。
sum(N, N) -> N; sum(N, M) when N < M -> M + sum(N, M-1); sum(_N, _M) -> throw({error, {range_error}}).
Exercise3.2: Creating Lists
正順と逆順のリストを作る方法
いくらでも作り方はあるんだろうけど、正順の方は末尾再帰で、逆順の方はダイレクト再帰で。
create_acc(0, Xs) -> Xs; create_acc(N, Xs) -> create_acc(N-1, [N|Xs]). create(M) when (M >= 1) and is_integer(M) -> create_acc(M, []). reverse_create(0) -> []; reverse_create(M) when (M >= 1) and is_integer(M) -> [M | create(M-1)].
Exercise3.3: Side Effects
リストを順に出力する関数を作れ、と。
% リストを出力 print_num_acc([]) -> true; print_num_acc([H|T]) -> io:format("Number:~p~n", [H]), print_num_acc(T). print_num(N) -> print_num_acc(create(N)). % 奇数の数字のみ出力 print_even_num_acc([]) -> true; print_even_num_acc([H|T]) -> case H rem 2 == 0 of true -> io:format("Number:~p~n", [H]); false -> odd end, print_even_num_acc(T). print_even_num(N) -> print_even_num_acc(create(N)).
Exercise3.4: Database Handling Using Lists
Erlang初心者なので、listsを使えばいい、と言われても即座に反応できなかったりする。
ここは、単にリストで。
-module(db). -export([new/0, destroy/1, write/3, delete/2, read/2, match/2]). % db:new/0 new() -> []. % db:destroy/1 destroy(_) -> ok. % db:write/3 write(Key, Element, Db) -> [{Key, Element} | delete(Key, Db)]. % db:delete/2 delete(Key, Db) -> delete_db(Key, Db). delete_db(_, []) -> []; delete_db(Key, [H|T]) -> case H of {Key, _Element} -> delete_db(Key, T); _Other -> [H | delete_db(Key, T)] end. % db:read/2 read(Key, Db) -> read_db(Key, Db). read_db(_, []) -> {error, instance}; read_db(Key, [H|T]) -> case H of {Key, Element} -> {ok, Element}; _Other -> read_db(Key, T) end. % db:match/2 match(Element, Db) -> match_db(Element, Db). match_db(_, []) -> []; match_db(Element, [H|T]) -> case H of {Key, Element} -> [Key | match_db(Element, T)]; _Other -> match_db(Element, T) end.
Exercise3.5: Manipulating Lists
SICPな人はお茶の子さいさい(ぼくは、よく怪しくなる)
%%% (1) filter filter([], _) -> []; filter([H|T], N) when H =< N -> [H | filter(T, N)]; filter([_|T], N) -> filter(T, N). %%% (2) reverse reverse_acc([], Xs) -> Xs; reverse_acc([H|T], Xs) -> reverse_acc(T, [H|Xs]). reverse(L) -> reverse_acc(L, []). %%% (3) concatenate append([], Ys) -> Ys; append(Xs, []) -> Xs; append([H|T], Ys) -> [H | append(T, Ys)]. concatenate([L]) -> L; concatenate([H1, H2 | T]) -> concatenate([append(H1, H2) | T]). %%% (4) flatten flatten([]) -> []; flatten([H|T]) -> append(flatten(H), flatten(T)); flatten(X) -> [X].
Exercise3.6: Sorting Lists
ここは、id:Ehrenにならって、ちゃんとテスト付きで(というか、ソース泥棒という噂も)。
%% Author: mizutomo %% Created: 2009/12/07 %% Description: Quicksort & Mergesort -module('ex3_6'). %% Include Files -include_lib("eunit/include/eunit.hrl"). %% Exported Functions -export([qsort/1, msort/1]). >%% Test Functions my_sort_test_() -> [ ?_assertEqual(qsort([1,3,2]),[1,2,3]), ?_assertEqual(qsort([3,2,0,1,5,8,4,2,2,7]),[0,1,2,2,2,3,4,5,7,8]), ?_assertEqual(msort([1,3,2]),[1,2,3]), ?_assertEqual(msort([3,2,0,1,5,8,4,2,2,7]),[0,1,2,2,2,3,4,5,7,8]) ]. %% ---------------------------------------------------------- %% Func: qsort/1 %% Desc: Quick Sort %% Returns: sorted list %% ---------------------------------------------------------- select(_, [], _) -> []; select(X, [H|T], 'lessthan') when H =< X -> [H | select(X, T, 'lessthan')]; select(X, [H|T], 'lessthan') when H > X -> select(X, T, 'lessthan'); select(X, [H|T], 'largerthan') when H > X -> [H | select(X, T, 'largerthan')]; select(X, [H|T], 'largerthan') when H =< X -> select(X, T, 'largerthan'). %qsort([]) -> []; %qsort([X|Xs]) -> % qsort(select(X, Xs, 'lessthan')) ++ [X] ++ qsort(select(X, Xs, 'largerthan')). qsort([]) -> []; qsort([X|Xs]) -> qsort([Y || Y <- Xs, Y =< X]) ++ [X] ++ qsort([Y || Y <- Xs, Y > X]). %% ---------------------------------------------------------- %% Func: msort/1 %% Desc: Merge Sort %% Returns: sorted list %% ---------------------------------------------------------- make_sorted_list(Xs, []) -> Xs; make_sorted_list([], Ys) -> Ys; make_sorted_list([X|Xs], [Y|Ys]) -> case X =< Y of true -> [X | make_sorted_list(Xs, [Y|Ys])]; false -> [Y | make_sorted_list([X|Xs], Ys)] end. msort(Xs) when length(Xs) == 1 -> Xs; msort(Xs) -> {Left, Right} = lists:split(length(Xs) div 2, Xs), make_sorted_list(msort(Left), msort(Right)).
残りの問題は力尽きた。というか、最近Twitterで時間を潰しすぎてるようなキモス。
とりあえず、3-8は今後のためにも役に立ちそうなので、勉強会後にでもちゃんとやるようにしましょう。