Расчет обработки списка в Прологе, чтобы найти пункт назначения, который посетят друзья - PullRequest
0 голосов
/ 16 марта 2020

Я пытаюсь написать предикат, который подсчитывает, какой пункт назначения посетит группа друзей. Друзья перечисляют свои предпочтения в следующих странах:

choice(marie, [peru,greece,vietnam]). 
choice(jean, [greece,peru,vietnam]). 
choice(sasha, [vietnam,peru,greece]). 
choice(helena,[peru,vietnam,greece]). 
choice(emma, [greece,peru,vietnam]).

Я хочу написать предикат , где , который принимает 2 аргумента для выполнения вычисления. Я имею в виду формулу: первая страна стоит 3 балла, вторая - 2 балла, а последняя - 1 балл.

Вот пример того, чего я пытаюсь достичь.

?- where([marie,jean,sasha,helena,emma],Country). 
peru .

Пока у меня есть это

where([], X).
where([H|T], N) :- choice(H, [A|B]), where(T,N).

Это позволяет мне перебирать всех разных друзей и показывает их выбор, но я не могу перебрать список вариантов и назначить точки для пунктов назначения.

Как мне go рассказать об итерациях по списку вариантов для каждого друга и назначить точки для расчета лучший пункт назначения?

Ответы [ 2 ]

2 голосов
/ 16 марта 2020

Хотя это решит вашу проблему, я знаю, что в нем используется много предикатов, которые вы не видели. Так что подумайте об этой возможности преуспеть и многому научиться.

Даже если вы не понимаете всего этого, в тесте достаточно деталей и промежуточных результатов, чтобы вы могли ориентироваться на пути к правильное решение, которое вы создаете.

Также это ни в коем случае не является эффективным, это было просто быстрое подтверждение концепции, которую я сделал, чтобы увидеть, как это можно сделать.

choice(marie, [peru,greece,vietnam]).
choice(jean, [greece,peru,vietnam]).
choice(sasha, [vietnam,peru,greece]).
choice(helena,[peru,vietnam,greece]).
choice(emma, [greece,peru,vietnam]).

destinations(Destinations) :-
    findall(D1,choice(_,D1),D2),
    flatten(D2,D3),
    list_to_set(D3,Destinations).

init_weights(Destinations,Weights) :-
    empty_assoc(Assoc),
    init_weights(Destinations,Assoc,Weights).

init_weights([],Weights,Weights).
init_weights([H|T],Assoc0,Weights) :-
    put_assoc(H,Assoc0,0,Assoc1),
    init_weights(T,Assoc1,Weights).

update_weights([C1,C2,C3],Weights0,Weights) :-
    del_assoc(C1,Weights0,Value0,Weights1),
    Value1 is Value0 + 3,
    put_assoc(C1,Weights1,Value1,Weights2),
    del_assoc(C2,Weights2,Value2,Weights3),
    Value3 is Value2 + 2,
    put_assoc(C2,Weights3,Value3,Weights4),
    del_assoc(C3,Weights4,Value4,Weights5),
    Value5 is Value4 + 1,
    put_assoc(C3,Weights5,Value5,Weights).

person_weight(Person,Weights0,Weights) :-
    choice(Person,[C1,C2,C3]),
    update_weights([C1,C2,C3],Weights0,Weights).

people(People) :-
    findall(Person,choice(Person,_),People).

choice(Destination) :-
    destinations(Destinations),
    init_weights(Destinations,Weights0),
    people(People),
    update_choices(People,Weights0,Weights1),
    cross_ref_assoc(Weights1,Weights),
    max_assoc(Weights, _, Destination),
    true.

cross_ref_assoc(Assoc0,Assoc) :-
    assoc_to_list(Assoc0,List0),
    maplist(key_reverse,List0,List),
    list_to_assoc(List,Assoc).

key_reverse(Key-Value,Value-Key).

update_choices([],Weights,Weights).
update_choices([Person|People],Weights0,Weights) :-
    person_weight(Person,Weights0,Weights1),
    update_choices(People,Weights1,Weights).

Тесты

:- begin_tests(destination).

test(destinations) :-
    destinations([peru, greece, vietnam]).

test(init_weights) :-
    destinations(Destinations),
    init_weights(Destinations,Weights),
    assoc_to_list(Weights,[greece-0, peru-0, vietnam-0]).

test(update_weights) :-
    destinations(Destinations),
    init_weights(Destinations,Weights0),
    update_weights([peru,greece,vietnam],Weights0,Weights),
    assoc_to_list(Weights,[greece-2,peru-3,vietnam-1]).

test(person_weight) :-
    destinations(Destinations),
    init_weights(Destinations,Weights0),
    person_weight(jean,Weights0,Weights),
    assoc_to_list(Weights,[greece-3,peru-2,vietnam-1]).

test(people) :-
    people([marie,jean,sasha,helena,emma]).

test(update_choices) :-
    destinations(Destinations),
    init_weights(Destinations,Weights0),
    people(People),
    update_choices(People,Weights0,Weights),
    assoc_to_list(Weights,[greece-10,peru-12,vietnam-8]).

test(cross_ref_assoc) :-
    List0 = [1-a,2-b,3-c],
    list_to_assoc(List0,Assoc0),
    cross_ref_assoc(Assoc0,Assoc),
    assoc_to_list(Assoc,[a-1,b-2,c-3]).

test(choice) :-
    choice(peru).

:- end_tests(destination).
1 голос
/ 16 марта 2020

Как предлагает GuyCoder, вам нужен аккумулятор для суммирования предпочтений каждого человека, и foldl / N позволяет делать именно это.

choice(marie, [peru,greece,vietnam]).
choice(jean,  [greece,peru,vietnam]).
choice(sasha, [vietnam,peru,greece]).
choice(helena,[peru,vietnam,greece]).
choice(emma,  [greece,peru,vietnam]).

where(People,Where) :-
    foldl([Person,State,Updated]>>(choice(Person,C),update(State,C,Updated)),
          People,
          [0=greece,0=peru,0=vietnam],
          Pref),
    aggregate(max(S,S=W),member(S=W,Pref),max(_,_=Where)).
%    sort(Pref,Sorted),
%    last(Sorted,_=Where).

update(S0,[A,B,C],S3) :-
    update(S0,3,A,S1),
    update(S1,2,B,S2),
    update(S2,1,C,S3).

update(L,V,C,U) :-
    append(X,[Y=C|Z],L),
    P is Y+V,
    append(X,[P=C|Z],U).

Я оставил комментарий к двум последним цели заменены на единую совокупность целей / 3, поэтому вы можете попытаться понять синтаксис ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...