Как определить сумму двух чисел из списка - PullRequest
1 голос
/ 27 апреля 2019

Попытка определить, соответствуют ли два числа в списке заданному значению.

Я прочитал множество вопросов и большую часть lists.pl из документации swi-prolog. Я могу определить, как узнать, равна ли сумма всех элементов в списке заданному значению, но нет, если любые два элемента равны заданному значению.

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
?- sum([1,2,3,4], 10).

Возвращает true, потому что сумма элементов списка равна 10, но ...

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

возвращает false, и мне нужно, чтобы оно возвращало true, потому что 4 + 2 = 6.

Ответы [ 4 ]

3 голосов
/ 27 апреля 2019

Ясно, что случай для DCG:

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

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

Или, как минимум, более эффективный:

sum_of_2_items(Xs, N) :-
   phrase(( ..., [A], ..., [B], {N is A+B}, ...), Xs).
0 голосов
/ 27 апреля 2019

Предикат учебника для этого - select/3. Это истинная связь между списком, элементом в списке и остальной частью списка.

?- 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].

Так что вы просто используете его дважды:

sum_of_two(List, Sum) :-
    select(X, List, L0),
    select(Y, L0, _),
    plus(X, Y, Sum).
0 голосов
/ 27 апреля 2019

Вы можете быть более общим, проверьте, является ли число суммой чисел в списке.

Существует два базовых случая:

N является членом списка

sum(L, N) :- 
   member(L, N).

N может быть суммой двух чисел:

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

Теперь общий случай:

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

Обратите внимание, что этот код работает только для положительных чисел. Может бытьмного решений, поэтому мы можем просто проверить, что есть решение с Once / 1 .Итак:

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).
0 голосов
/ 27 апреля 2019

append/3 ваш друг, когда дело доходит до разложения списков.

Попробуйте что-то вроде этого:

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 ).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...