How to correctly filter a clause that returns multiple duplicated values?

…衆ロ難τιáo~ 提交于 2019-12-24 01:00:18

问题


I'm trying to correctly filter the values returned from a clause (it is returning multiple duplicated values). I'm having a hard time understanding the logic programming, sorry if its an stupid question.

These are my facts/predicates:

home(peter, sanFrancisco, 1000).
home(ash, sanFrancisco, 100).
home(juan, sanFrancisco, 400).
home(juan, california, 700).
home(ash, california, 600).
home(peter, california, 500).
home(peter, vegas, 100).
home(ash, vegas, 80).
home(juan, vegas, 60).

What im trying to do is to retrieve the name; the condition is that I have to retrieve only the ones that from a certain city their home is the most expensive from there but also if the second most expensive home from that same city is less than half the price of the first. I cannot use lists.

The most expensive from each city:

home(peter, sanFrancisco, 1000).
home(juan, california, 700).
home(peter, vegas, 100).

Second most expensive from each city:

home(juan, sanFrancisco, 400).
home(ash, california, 600).
home(ash, vegas, 80).

What I expect as a result:

peter.

What I have tried so far but with no success..

%Return the most expensive from each city.
theMostExpensive(Name, City):-
    home(Name, City, Price),
    fromEach(City, Price).

fromEach(City, Price):-
    forall(home(_, City, Price2), Price>= Price2).

%Return the second most expensive from each city. Not sure if working correctly.
secondMostExpensive(Name, City):-
    owner(home),
    not(theMostExpensive(Name, City)),
    theMostExpensive(Name2, City),
    Name \= Name2.

%Return a lot of duplicated values and wrong..
superExpensive(Name):-
    theMostExpensive(Name, City),
    secondMostExpensive(Name2, City),
    Name \= Name2,
    City \= City2,
    home(Name, City, Price),
    home(Name2, City2, Price2),
    Price > Price2 + (Price / 2).

I think somewhere in superExpensive is doing something like everyone * everyone?


回答1:


The most expensive home in a town is such that no other home in that town is more expensive than it:

most_expensive( home( Name, Town, Price)):-
  home( Name, Town, Price),
  \+ (home( _, Town, P), P > Price).

This gets us

5 ?- most_expensive( H ).
H = home(peter, sanFrancisco, 1000) ;
H = home(juan, california, 700) ;
H = home(peter, vegas, 100) ;
false.

The second most expensive home in a town is such that is the most expensive among the homes which are not the most expensive home in that town:

second_most_expensive( home( Name, Town, Price)):-
  most_expensive( home( _, Town, TopPrice) ),
  home( Name, Town, Price), Price < TopPrice,
  \+ (home( _, Town, P), P < TopPrice, P > Price).

And this gets us

8 ?- second_most_expensive( H ).
H = home(juan, sanFrancisco, 400) ;
H = home(ash, california, 600) ;
H = home(ash, vegas, 80) ;
false.

So then, with

top_house_owner( Name ) :-
  most_expensive( home( Name, T, P) ),
  second_most_expensive( home( _, T, P2 ) ),
  P2 < P div 2.

we get

12 ?- top_house_owner( N ).
N = peter ;
false.



回答2:


You can find a simple solution if you think of the problem in the following way.

A person X meets your conditions if and only if X has a house in some city Y, and there is no one else in Y with a house costing at least half of the price of X's.

% true if Name2's home is at least half of the price of Name1's
aboveHalf( City, Name1, Name2 ) :-
  home( Name1, City, P1 ),
  home( Name2, City, P2 ),
  Name1 \= Name2,
  P2 > P1 div 2.

superExpensive( Name ) :-
  home( Name, City, _ ),
  \+ aboveHalf( City, Name, _ ).


来源:https://stackoverflow.com/questions/56573203/how-to-correctly-filter-a-clause-that-returns-multiple-duplicated-values

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!