3
:- use_module(library(clpfd)). % load constraint library

% [constraint] Compute a list of distinct odd numbers (if one exists), such that their sum is equal to a given number.

odd(Num) :- Num mod 2 #= 1.

sumOfList([],N,N) :- !.
sumOfList([H|T],Counter,N) :-
  NewN #= H + Counter,
  sumOfList(T,NewN,N).

buildOddList(N,InputList,L) :-
  %return list when sum of list is N
  V in 1..N,
  odd(V),
  append(InputList,[V],TempL),
  sumOfList(TempL,0,N)->
    L = TempL;
    buildOddList(N,TempL,L).

computeOddList(N) :-
  buildOddList(N,[],L),
  label(L).

これは私のコードです。正しい出力が得られないようです。コード評論家はいますか? :)

4

4 に答える 4

3

nonNegInt_oddPosSummands/2ここで、述語と補助述語によって実現されたこの質問に対する私の見解list_n_sum/3:

:- use_module(library(clpfd)).

list_n_sum([],_,0).
list_n_sum([Z|Zs],N,Sum) :-
    Z #>= 1,
    Z #=< N,
    Z mod 2 #= 1,
    Sum  #=  Z + Sum0,
    Sum0 #>= 0,
    list_n_sum(Zs,N,Sum0).

nonNegInt_oddPosSummands(N,List) :-
    length(_,N),
    list_n_sum(List,N,N),
    chain(List,#<),
    labeling([],List).

それでは、いくつかのクエリに進みましょう。

まず、「どのリストに分解できますか?」:

?- nonNegInt_oddPosSummands(19,Zs).
Zs = [19] ;
Zs = [1, 3, 15] ;
Zs = [1, 5, 13] ;
Zs = [1, 7, 11] ;
Zs = [3, 5, 11] ;
Zs = [3, 7, 9] ;
false.

次に、ソリューション セットが無限であるため終了しない、より一般的なクエリです。「長さが 2 の場合、どの正の整数Nに分解できますか?」ZsZs

?- Zs=[_,_], nonNegInt_oddPosSummands(N,Zs).
N = 4,  Zs = [1,3] ;
N = 6,  Zs = [1,5] ;
N = 8,  Zs = [1,7] ;
N = 8,  Zs = [3,5] ;
N = 10, Zs = [1,9] ...

最後に、最も一般的なクエリです。上記のように、解集合が無限であるため、終了しません。ただし、すべての分解と対応する正の整数を公平に列挙します。

?- nonNegInt_oddPosSummands(N,Zs).
N = 0,  Zs = []      ;
N = 1,  Zs = [1]     ;
N = 3,  Zs = [3]     ;
N = 4,  Zs = [1,3]   ;
N = 5,  Zs = [5]     ;
N = 6,  Zs = [1,5]   ;
N = 7,  Zs = [7]     ;
N = 8,  Zs = [1,7]   ;
N = 8,  Zs = [3,5]   ;
N = 9,  Zs = [9]     ;
N = 9,  Zs = [1,3,5] ;
N = 10, Zs = [1,9] ...
于 2015-03-31T10:47:14.537 に答える
1

他の人がすでに完全な解決策を投稿しているのを見ます。それでも、わずか2つの変更を加えるだけで、コードを機能させることができます。

  1. computeOddListそのようなリストが存在するかどうかをテストするだけです。どのリストが制約に一致するかを知るには、それを返すだけです。したがって:

    computeOddList(N, L) :-
        ...
    
  2. 現在、リストTempLに重複が含まれている可能性があります。それを修正するためにall_different(TempL)後に置いてください。append

computeOddListこれで、異なる奇数のリストが存在する場合は、少なくとも1つ返されます。それでも、たとえば、computeOddList(17, L)すべてのリストが返されるわけではありません。私はclpFDを自分で知らないので、コードをXonixのコードと比較することを提案する以外は、私は本当にあなたを助けることはできません。

于 2009-11-24T08:13:31.050 に答える
1

この解決策を提案できます:

:- use_module(library(clpfd)).

all_odd([]) :-!.
all_odd([H | T]) :-
 H mod 2 #= 1,
 all_odd(T).

solve(N,L) :-
 N2 is floor(sqrt(N)),
 Len in 1..N2,
 label([Len]),

 length(L, Len),

 L ins 1..N,

 all_different(L),
 all_odd(L),

 sum(L,#=,N),

 label(L),

 % only show sorted sets
 sort(L,L).

例:

?- solve(17,L).
L = [17] ;
L = [1, 3, 13] ;
L = [1, 5, 11] ;
L = [1, 7, 9] ;
L = [3, 5, 9] ;
false.
于 2009-11-24T01:54:15.870 に答える
0
:- use_module(library(clpfd)). % load constraint library

% [constraint] Compute a list of distinct odd numbers (if one exists), such that their sum is equal to a given number.

odd(Num) :- Num mod 2 #= 1.

sumOfList([],N,N) :- !.
sumOfList([H|T],Counter,N) :-
  NewN #= H + Counter,
  sumOfList(T,NewN,N).

oddList([]) :- !.
oddList([H|T]) :-
  odd(H),
  oddList(T).

computeOddList(N,L) :-
  (L = [];L=[_|_]),
  length(L,V),
  V in 1..N,
  L ins 1..N,
  all_different(L),
  oddList(L),
  sumOfList(L,0,N).

なんとか解決できたのですが、ケースがなくなってしまったらちゃんと終わらない。うーん。

于 2009-11-23T22:34:03.637 に答える