1
votes

Comment déterminer la somme de deux nombres à partir d'une liste

Essayer de déterminer si deux nombres dans la liste sont égaux à une valeur donnée.

J'ai lu de nombreuses questions et la plupart des lists.pl de la documentation swi-prolog. Je peux déterminer comment savoir si la somme de tous les éléments de la liste est égale à une valeur donnée, mais pas si deux des éléments sont égaux à la valeur donnée.

?- sum([1,2,3,4], 6).
?- sum([1,2,3,4], 10).

Renvoie true car la somme des éléments de la liste est de 10, mais ...

sum([ ],0). %Pretty sure this makes the list(?)
sum([H|T],Sum) :- sum(T, Temp), Sum is Temp + H. %recursively adds the numbers
%maybe my base case is off

renvoie false, et j'en ai besoin pour renvoyer true car 4 + 2 = 6.


0 commentaires

4 Réponses :


0
votes

append / 3 est votre ami lorsqu'il s'agit de décomposer des listes.

Essayez quelque chose comme ceci:

sum_of_2_items(L,N) :-
  take2( L, X, Y ),
  N =:= X + Y
  .

take2( L , X , Y ) :-
  append( Pfx, [X|Sfx], L ),
  gety( Pfx, Sfx , Y )
  .

gety( L, _, Y ) :- gety( L, Y ).
gety( _, L, Y ) :- gety( L, Y ).

gety( [Y|_],  Y ).
gety( [_|Ys], Y ) :- gety( Ys, Y ).


6 commentaires

Ou même take2ordered (XsYs, X, Y): - append (_, [X | Ys], XsYs), append (_, [Y | _], Ys).


@jschimpf ... et pour autant que je sache, append (_, [X | Ys], L) est exactement identique à select (X , L, Ys) ?


@ User9213 pas exactement, avec ajouter Ys est le reste de la liste après X, avec select c'est toute la liste sans X. C'est pourquoi les solutions basées sur la sélection sont un peu inefficaces, elles regardent chaque paire de valeurs deux fois (dans un ordre différent) .


@jschimpf Je comprends maintenant¸ merci! Donc, en gros, en utilisant append, vous ajoutez une "contrainte" de position sur les éléments que vous choisissez - certainement utile. Si vous n'écrivez pas votre commentaire comme réponse, je le ferai ;-)


@ User9213 allez-y;)


@jschimpf ah, ça ne vaut pas la peine. false a tué le fil avec ses points de suspension.



0
votes

Le prédicat du manuel pour cela est select / 3 . C'est une vraie relation entre une liste, un élément de la liste et le reste de la liste.

sum_of_two(List, Sum) :-
    select(X, List, L0),
    select(Y, L0, _),
    plus(X, Y, Sum).

Donc, vous ne l'utilisez que deux fois:

?- select(X, [1,2,3,4], Rest).
X = 1,
Rest = [2, 3, 4] ;
X = 2,
Rest = [1, 3, 4] ;
X = 3,
Rest = [1, 2, 4] ;
X = 4,
Rest = [1, 2, 3].


0 commentaires

0
votes

Vous pouvez être plus général, vérifiez si un nombre est la somme des nombres d'une liste.

Il y a deux cas de base:

N est un membre de la liste

XXX

N peut être la somme de deux nombres:

check_sum(L, N) :-
    once(sum(L, N)).

sum(L, N):-
    select(N, L, _).

sum(L, N) :-
    select(A, L, L1),
    select(B, L1, _),
    N =:= A+B.

sum(L, N):-
    select(A, L, L1),
    N1 is N-A,
    N1 >= 0,
    sum(L1, N1).

Maintenant le cas général:

sum(L, N):-
    select(A, L, L1),
    N1 is N-A,
    N1 >= 0,
    sum(L1, N1).


0 commentaires

4
votes

Clairement un cas pour les DCG:

sum_of_2_items(Xs, N) :-
   phrase(( ..., [A], ..., [B], {N is A+B}, ...), Xs).

Ou, un peu plus efficace:

sum_of_2_items(Xs, N) :-
   phrase(( ..., [A], ..., [B], ...), Xs),
   N is A+B.

... --> [] | [_], ... .


0 commentaires