現在の閲覧者数:

差分リスト

アイデアとして、リストを [リスト]ー[リスト] のように差で表現する方法があります。

♪ 例えば、

次は、同じ[a,b,c]を表しています。そうです決めたのです。
[a,b,c,d,e]-[d,e]              => [a,b,c]
[a,b,c,d,e,f,g,h]-[d,e,f,g,h]  => [a,b,c]
[a,b,c,m]-[m]                  => [a,b,c]
[a,b,c]-[]                     => [a,b,c]

上の4行を一般化して表現すると

[a,b,c|E]-E 

となります。

上の4行が、一般化式とパターンマッチングするか試してみます。

?- [a,b,c,d,e]-[d,e]               = [a,b,c|E]-E.
E = [d, e].

?- [a,b,c,d,e,f,g,h]-[d,e,f,g,h]   = [a,b,c|E]-E.
E = [d, e, f, g, h].

?- [a,b,c,m]-[m]                   = [a,b,c|E]-E.
E = [m].

?- [a,b,c]-[]                      = [a,b,c|E]-E.
E = [].

?-

パターンマッチングすることがわかりました。

上の差分リストは、リストの結合に使うと効率的に働くようです。

普通リストの結合は、次のように定義されますが、
続けて差分リストでの方法を示します。

♪ プログラムコード code

% dl_append.pl

% 通常

a_append( [], A, A ).
a_append( [X|A], B, [X|C] ) :- a_append( A, B, C ).


% 差分リスト

d_append(I-M, M-O, I-O).

実行してみましょう。

love:uema% swipl -q -s dl_append.pl
?- a_append( [a,b,c], [x,y,z], A ).
A = [a, b, c, x, y, z].

?- d_append([a,b,c|E]-E,  [x,y,z|W]-W,  A).
E = [x, y, z|W],
A = [a, b, c, x, y, z|W]-W.

?-


一般形から読み解くと、[a,b,c]+[x,y,z]=>[a,b,c,x,y,z]となり結合を表しています。


M.Hiroiさんにならって take_integer.pl code
(同一ではありません。差分リストの表現が違う)

% take_integer.pl

take_integer(X, Y) :- take_int_sub(X, Y-[]).
take_int_sub([X | Xs], Ys-Zs) :-
		take_int_sub(X, Ys-Ys1), take_int_sub(Xs, Ys1-Zs), !.
take_int_sub(X, [X | Xs]-Xs) :- integer(X), !.
take_int_sub(_, Ys-Ys).

実行してみます。

$ swipl -qs take_integer.pl
?- take_integer([a, 1, [b, 2]], Z).
Z = [1, 2].

?- q.
$

♪クイックソート code

love:uema% cat quick.pl
% quick.pl
% 通常版
quick1(Xs, Ys) :- quick_sub(Xs, [Ys, []]).
quick_sub([X | Xs], [Ys, Zs]) :-
	partition(Xs, X, Littles, Bigs),
	quick_sub(Littles, [Ys, [X | Ys1]]),
	quick_sub(Bigs, [Ys1, Zs]).
quick_sub([], [Xs, Xs]).

% 差分リスト版
quick2(Xs, Ys) :- quick_sub2(Xs, Ys - []).
quick_sub2([X | Xs], Ys - Zs) :-
	partition(Xs, X, Littles, Bigs),
	quick_sub2(Littles, Ys - [X | Ys1]),
	quick_sub2(Bigs, Ys1 - Zs).
quick_sub2([], Xs - Xs).

% quick1, quick2, 共通
partition([X | Xs], Y, [X | Ls], Bs) :-
	X =< Y, partition(Xs, Y, Ls, Bs).
partition([X | Xs], Y, Ls, [X | Bs]) :-
	X > Y, partition(Xs, Y, Ls, Bs).
partition([], _, [], []).
love:uema%

♪ 実行してみます。

love:uema% swipl -q -s  quick.pl
?- quick1([5, 3, 7, 6, 9, 8, 1, 2, 4], X).
X = [1, 2, 3, 4, 5, 6, 7, 8, 9] ;
false.

?- quick2([5, 3, 7, 6, 9, 8, 1, 2, 4], X).
X = [1, 2, 3, 4, 5, 6, 7, 8, 9] ;
false.

?-




♪ 図解します( append )。

                      (A2)                    
A1                     Z1                      Z2
|-----------L1---------|----------L2-----------|-------------------

|----------------------L3----------------------|

結合
       L1 = A1 - Z1    +    L2 = A2 - Z2   ==>   L3 = A1 - Z2,    (Z1==A2:でなければならない)
inserted by FC2 system