2

is_multi(M)次のように定義された predicate を記述しようとしています。

  • のすべての要素のM形式は ですX / N。ここXで、 はアトムで、Nは 0 より大きい整数です。
  • M何のために、同じ原子を持つ 2 つの要素を含まない

    is_multi([]).
    is_multi([a / 2, b / 2]).
    

    満足していますが、

    is_multi([a, b/2]).
    is_multi([a/0, b/2]).
    is_multi([a/2, 2/4])
    is_multi([a/2, b/3, a/2])
    is_multi([a/3, b/-4, c/1])
    

    ではありません。

これまでに書いたものは次のとおりです。

is_multi(M) :- M = [].
is_multi(M) :-
    M = [Head|Tail],
    Head = X/N,
    integer(N),
    N > 0,
    is_multi(Tail).

ただし、同じ原子の場合は 2 つの要素を比較しません。たとえば、is_multi([a/2, a/3])満たされていない。私はこれで1日立ち往生しました。誰かが私にいくつかのヒントを与えることができますか?

4

2 に答える 2

4

まず、統合の一部を body から head に移動することで、コードを大幅に簡素化できます。

is_multi([]).
is_multi([X/N|Tail]) :-
  integer(N), N > 0,
  is_multi(Tail).

それをクリーンアップすると、ここで行っていないことの 1 つが明らかになります。それは、仕様にある、それXがアトムであることを確認することです。atom(X)本体に追加して修正します。

OK、これで基本的な形は処理されますが、アトムが繰り返されないことは保証されません。最も簡単な方法は、これを 2 つのチェックに分割することです。1 つは各項目が整形式であることをチェックし、もう 1 つはリストが整形式であることをチェックします。maplist/2実際、単一の要素をチェックする述語を使用する傾向があります。しかし、あなたが本当にしなければならないのは、次のようなことだけです:

is_valid([]).
is_valid([X/_|T]) :- is_valid(T), \+ memberchk(X/_, T).

これは単に空のリストが有効であることを示しており、末尾が有効な場合、末尾に何かに対する X が発生しなければリストは有効です。

それがあなたが望むすべてであるなら、そこで読むのをやめてください. リファクタリングしたい場合は、次のようにアプローチします。

well_formed(X/N) :- atom(X), integer(N), N > 0.

no_repeating_numerators([]).
no_repeating_numerators([X/_|T]) :- no_repeating_numerators(T), \+ memberchk(X/_, T).

is_multi(L) :- maplist(well_formed, L), no_repeating_numerators(L).
于 2013-07-16T04:30:56.740 に答える