Prologのトレーニングのために「どう書く」を最初から解いてみようと考えたまではよかったのですが。
1問目で頭から湯気が出そうになりました。
いま使っているPrologの処理系SWI-Prologのライブラリでは、リストをsort
すると重複する要素がまとめられてしまいます(Prolog標準ライブラリの仕様なんでしょうか?)。
?- sort([5,4,4,3,3,3,2,2,2,2,1,1,1,1,1], X). X = [1, 2, 3, 4, 5].
これでは目的とした動作ができないので「M.Hiroi's Home Page / Prolog Programming」からクイックソートを拝借してどうにかこうにか1問を書き下したところ。少し頭冷やさないと次に進める気がしません。ぷしゅぅうう…。
% クイックソートのコード( qsort/2 および partition/4 )は、 % 下記の「お気楽 Prolog プログラミング入門」から拝借致しました % http://www.geocities.jp/m_hiroi/prolog/prolog04.html#chap19 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([], _, [], []). qsort([X|Xs], Ys) :- partition(Xs, X, Littles, Bigs), qsort(Littles, Ls), qsort(Bigs, Bs), append(Ls, [X | Bs], Ys). qsort([], []). split([], []). split([_,49,48|Xs], [10|Ys]) :- split(Xs, Ys), !. split([_,X|Xs], [Y|Ys]) :- Y is X - 48, split(Xs, Ys), !. unique([X], [[1,X]]). unique([X|Xs], [[N,X]|Ys]) :- unique(Xs, [[N1,X]|Ys]), N is N1 + 1. unique([X|Xs], [[1,X]|Ys]) :- unique(Xs, Ys). hand([ [1,_], [1,_], [1,_], [2,_] ], "1P") :- !. hand([ [1,_], [1,_], [3,_] ], "3K") :- !. hand([ [1,_], [2,_], [2,_] ], "2P") :- !. hand([ [1,_], [4,_] ], "4K") :- !. hand([ [2,_], [3,_] ], "FH") :- !. hand(_, "--") :- !. solve(X, Y) :- split(X, A), qsort(A, B), unique(B, C), sort(C, D), hand(D, Y), !. test(X, F, E) :- call(F, X, A), format("expected = ~s, actual = ~s~n", [E, A]), E == A. sample1 :- test("D3C3C10D10S3", solve, "FH"), test("DASAD10CAHA", solve, "4K"), test("S10HAD10DAC10", solve, "FH"), test("S3S4H3D3DA", solve, "3K"), test("SASJDACJS10", solve, "2P"), test("H10D10H3HJCK", solve, "1P"), test("S3SJDAC10SQ", solve, "--").
実行結果。
$ swipl -s sample1.pl -g sample1 -t halt expected = FH, actual = FH expected = 4K, actual = 4K expected = FH, actual = FH expected = 3K, actual = 3K expected = 2P, actual = 2P expected = 1P, actual = 1P expected = --, actual = --