これは、戦略を再考することで解決できます。
まず、基本ケースは何ですか?
- 入力として空のリストになります
- あなたが持っている
I > J
どちらの場合も、空のリストをこれまでのすべてのものに追加し、それを良いと呼びます。
次に、気になるエッジケースは何ですか?
J
リストの終わりを超えています
I
リストの先頭の前です
最初のケースでは、入力リストの最後までトラバースします。2 番目では、入力リストの先頭から開始します。
さて、それを実装してみましょう。アキュムレータを使用して、呼び出しをラップします。
sublist(L1, L2, I, J):-
sublist(L1, Temp, I, J, []),
!,
reverse(Temp, L2).
入力 list L1
、出力 list として統合する変数、およびL2
インデックス とを取ります。他のソリューションのバックトラックを心配する必要がないように使用しており、蓄積されたリストが逆に構築されているため、それを逆にします。I
J
cut
ベースケースに取り組みましょう。
入力として空のリスト。アキュムレータを出力リストと統合するだけです。この時点では、インデックスは気にしません。J
結局のところ、これは がリストの末尾を超えているというエッジ ケースも満たしています。その時点で、すべての入力リストがアキュムレータに蓄積され、まだ J 値が残っているためです。
sublist([], L2, _I, _J, L2).
I > J で、アキュムレータを出力リストと統合します。入力リストはもう気にしません。
sublist(_L1, L2, I, J, L2):-
I > J.
今、エッジケース。
J
リストの終わりを超えて上で解決されました。
I
リストの先頭の前にある場合は、そのインデックスを 0 に設定して先に進みます。
sublist(L1, L2, I, J, L2):-
I < 0,
sublist(L1, L2, 0, J, L2).
あとは実際のロジックを実装するだけです。正しいものから始めて累積したいだけですI
。それでは、I
目的の場所に到達するまで、入力リストの一部をデクリメントして破棄しましょう。インデックスの最後を一致させるために、デクリメントJ
も必要です。このようにして、インデックス間の距離を同じに保ちます。
sublist([_L|Ls], L2, I, J, Acc):-
I > 0,
sublist(Ls, L2, I-1, J-1, Acc).
私たちはついに私たちがなりたい場所にいます。それでは、入力リストの一部を使ってリストを作成してみましょう。これは、基本ケースの 1 つに到達するまで続きます。sublist
その後、アキュムレータは元の節に戻されます。
sublist([L|Ls], L2, I, J, Acc):-
sublist(Ls, L2, I, J-1, [L|Acc]).
すべてをまとめると、次のようになります。
sublist(L1, L2, I, J):-
sublist(L1, Temp, I, J, []),
!,
reverse(Temp, L2).
sublist([], L2, _I, _J, L2).
sublist(_L1, L2, I, J, L2):-
I > J.
sublist(L1, L2, I, J, L2):-
I < 0,
sublist(L1, L2, 0, J, L2).
sublist([_L|Ls], L2, I, J, Acc):-
I > 0,
sublist(Ls, L2, I-1, J-1, Acc).
sublist([L|Ls], L2, I, J, Acc):-
sublist(Ls, L2, I, J-1, [L|Acc]).
そして、次のようにテストできます。
?- sublist([1,2,3,4,5], S, 0,3).
S = [1, 2, 3, 4].
?- sublist([1,2,3,4,5], S, -1,30).
S = [1, 2, 3, 4, 5].
?- sublist([1,2,3,4,5], S, 3,1).
S = [].
?- sublist([1,2,3,4,5], S, 3,3).
S = [4].
?- sublist([1,2,3,4,5], S, 3,4).
S = [4, 5].