一般的な再帰スキーム
ここでは、通常、Prolog で再帰を実行する方法を示します。リストは「後方」に構築されているため、初心者にとって取得するのは簡単ではありません。リストの最後に到達するまで、実際には何も構築されません。
この「後方構築」の原則の理由は、変数が設定されると、それを別の値に設定することができないためです。たとえば、結果が[1]
再帰の最初のステップにあり、次にになり[1, 2]
ます。代わりに、Prolog で言うことは、結果の先頭は1
再帰呼び出しの結果であり、結果の末尾は再帰呼び出しの結果であるということです (そう、面倒な場合は 2 回読んでください : d)。したがって、基本ケース (再帰が実行されないケース) にヒットしない限り、変数を明確にバインドしません (つまり、常に項の一部をバインド解除します)。
rec/2: rec(Input, Result)
要素を でリンクすることによって入力リストから結果リストを生成する述語の場合、次のsomepredicate/2
ように記述します。
rec([InputHead|InputTail], [ResultHead|ResultTail]) :-
somepredicate(InputHead, ResultHead),
rec(InputTail, ResultTail).
それを表すために。
ResultHead
ここで、結果の先頭は であり、その末尾は呼び出しのおかげで計算されると述べたことがわかります。rec(InputTail, ResultTail).
これで問題ありませんが、たとえばリストが空の場合など、ある時点で停止する必要があります。次のように書きます。
rec([], []).
つまり、入力リストが空の場合、結果リストも空です。
述語への適用
問題を解決するには、まず再帰句を修正する必要があります。
findPair(Teams,[HL|TL],Rest) :-
findMinMax(Teams,Min,Max),
delete(Teams,Min,TeamsNoMin),
delete(TeamsNoMin,Max,Rest),
createPair(Min,Max,Pair), %Pair = "["Min_team","Max_team"]"
append(HL,[Pair],TL),
findPair(Rest,TL,[]).
になるだろう
findPair(Teams, [Pair|Tail], LeftOver) :-
findMinMax(Teams, Min, Max),
delete(Teams, Min, TeamsNoMin),
delete(TeamsNoMin, Max, Rest),
createPair(Min, Max, Pair), %Pair = "["Min_team","Max_team"]"
findPair(Rest, Tail, LeftOver).
重要な注意事項:Rest
は 2 つの別個の変数になりました。の最後の引数はfindPair/3
もう変更されません。再帰呼び出しではそれについてまだ何もわからないため、それをバインドすることができず、Rest
したがって in-predicate は独立しており、まだ変更されていないチームを表すだけです。まだ処理されていないため、結果リストの末尾 (およびLeftOver
) に関心があります。
次に、基本ケースを処理する必要があります。
チームが残っていないとき
findPair([], [], []).
ここで、 whenTeams
が空であると言うと、Result
andもそうLeftOver
です。
チームが1つ残っているとき
findPair([Last], [], [Last]).
ここで、whenTeams
は要素が 1 つしかない、LeftOver
等しい、Teams
およびResult
空であると言います。
結果のコードは次のとおりです。
findPair([], [], []).
findPair([Last], [], [Last]).
findPair(Teams, [Pair|Tail], LeftOver) :-
findMinMax(Teams, Min, Max),
delete(Teams, Min, TeamsNoMin),
delete(TeamsNoMin, Max, Rest),
createPair(Min, Max, Pair), %Pair = "["Min_team","Max_team"]"
findPair(Rest, Tail, LeftOver).
Teams
句を排他的[Not, Empty|AtAll]
にするには、最後の句が長さ 2 以上のリストでのみ使用されるように置き換えるかTeams = [_, _|_],
、句の先頭などにガードを追加するだけです。
それが役に立てば幸いです。コメントで説明を求めることを躊躇しないでください:)