リスト処理を用いた述語の作成

「リスト処理を用いた述語の作成」の編集履歴(バックアップ)一覧はこちら

リスト処理を用いた述語の作成」(2014/05/07 (水) 12:43:02) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

今回は、リスト処理を学習する際に、よく出現する述語の +member +append +length +reverse について学習します。 ---- ***member/2 -第一アリティの値が、第二アリティのリスト内に存在するか調べる member(X,[X|_]). member(X,[_|T]):- member(X,T). ?-member(a,[a,b,c]). yes ?-member(d,[a,b,c]). no -解説  member述語は2つ定義します。  まず一つ目の述語は、第一アリティと、第二アリティのリストの頭部が一致した場合、trueとし  終了します。    一致しなかった場合、2つ目の述語が実行され、第二アリティを頭部、尾部へ分解し  第一アリティと、尾部を再度、自分自身へ渡します。  &bold(){※注:memberはAz-Prologには組み込み述語として定義されているので、実際に作成してみる際は、述語名を適宜変えてください。} ---- ***append/3 -第一アリティのリストと、第二アリティのリストを結合する append([],Y,Y). append([H|T],Y,[H|R]):- append(T,Y,R). ?-append([a,b,c],[d,e,f],R). R = [a,b,c,d,e,f] yes -解説  append述語は2つ定義します。  まず一つ目の述語は、第一アリティが空リストであれば、第二アリティを第三アリティとユニフィケーションします。  空リストではなければ、第一アリティのリストの頭部を、第三アリティのリストの頭部へ追加  その後、尾部を自分自身へ渡し、再帰処理を行います。  &bold(){※注:appendはAz-Prologには組み込み述語として定義されているので、実際に作成してみる際は、述語名を適宜変えてください。} ・appendの使い方(応用例) リストの分解 ?-append([1,2,3],B,[1,2,3,4,5,6]) B=[4,5,6] 2つのリストに分解できるすべての組み合わせを求める ?-append(X,Y,[1,2,3,4,5,6]) X = [], Y = [1,2,3,4,5,6]; X = [1], Y = [2,3,4,5,6]; X = [1,2], Y = [3,4,5,6]; X = [1,2,3], Y = [4,5,6]; X = [1,2,3,4], Y = [5,6]; X = [1,2,3,4,5], Y = [6]; X = [1,2,3,4,5,6], Y = []; 上記の例のように、ひとつの述語で複数の使い方ができるのがPrologの特徴です。 ---- ***length/2 -第一アリティのリストの要素数をカウントする length([],0):- !. length([_|T],N1):- length(T,N2), N1 is N2 + 1. ?-length([a,b,c],N). N = 3 ?-length([],N). N = 0 -解説  一つ目の述語は、第一アリティが空リストの場合、0を第二アリティへユニフィケーションします。  第一アリティが空リストでは無い場合、尾部をlengthへ渡し、再帰させ、そこでユニフィケーション  された第二アリティに1を足した値を、(自分自身の)第二アリティへユニフィケーションします。  &bold(){※注:lengthはAz-Prologには組み込み述語として定義されているので、実際に作成してみる際は、述語名を適宜変えてください。}   ---- ***reverse/2 -第一アリティのリストの要素を逆順にする reverse([],[]):- !. reverse([H|T],R1):- reverse(T,R2), append(R2,[H],R1). ?-reverse([1,2,3],R). R = [3,2,1] -解説  一つ目の述語は、例によって終了条件です。  第一アリティが空リストでは無い場合、尾部をreverseへ渡し、再帰させ、そこでユニフィケーション  された第二アリティと、頭部をappend述語で結合し、そのリストを(自分自身の)第二アリティへ  ユニフィケーションします。 ・reverseの最適化  上記の定義以外に、以下の書き方も可能です。 reverse2(Ls,R):- reverse2(Ls,[],R). reverse2([],R,R):- !. reverse2([H|T],Y,R):- reverse2(T,[H|Y],R).   reverse2では、reverse2/2にてreverse2/3を定義し、計算の途中結果を格納する為に 第二アリティを使用します。 このように、処理の途中経過と単一化されるものを「累算器」と呼びます。 累算器を使うことによって、二つのリストを連結するという処理が必要ではなくな りますので、効率がかなり改善されます ※AZ-Prologに同封されている、[DEL_APP.PL]によると  reverseの定義では、計算量はO(n^2)オーダーとなり、reverse2ではO(n)オーダーで済むとのこと。  N要素のリストを反転する述語のCall回数は、それぞれ次のようになる。 |N|1|2|10|30|100| |revese|3|6|66|496|5151| |revese2|3|4|12|32|102| ※詳しくは上述のファイルを参照してください。

表示オプション

横に並べて表示:
変化行の前後のみ表示: