How to make the predicate spent(Passengers, Year, Sum) in prolog? - prolog

I need to write a predicate "spent" that would find the total costs for tickets of passengers from
of the "Passengers" list in the given year "Year".
I have these facts:
trip(01, Tokio, Toronto, 1500). /trip (Id, From, To, Price)/
trip(02, California, London, 700).
ticket(01, Sara, 2021-12-26). /ticket (Id, Passenger, Date)/
ticket(02, Jane, 2021-05-21).
I wrote this code, but it is not enough to complete the task, please help.
sum_cash(Price) :- spent(sum(A), trip(_, _, _, A), Price).

Related

How to add limit in prolog?

Previously I wrote the predicate, reach(Arrivals,Departure) to find a list of names of departure points from which I can get to a given point arrivals. Now, how can I make sure that the total cost from the calculated route does not exceed a given limit, for example now it`s work like this:
?-reach(krum, Departure).
Answer: Departure = [uzhorod].
in this example, the total cost of the route = 6000, how can it be implemented if 7000 is entered, it is false and if 6000 is true.
This is my facts:
trip(01, kuiv, odessa, 1500).
trip(02, kuiv, lviv, 700).
trip(08, lviv, zaporizhya, 700).
trip(03, uzhorod, krum, 6000).
trip(04, vunohradiv, odessa, 2540).
trip(05, ternopil, kuiv, 3800).
trip(06, zaporizhya, donetsk, 900).
trip(07, lytsk, mariupol, 7500).
trip(Id, Departure, Arrivals, Price)
This is my code:
reachable(D, D, _).
reachable(Departure, Arrival, Visited) :-
trip(_, Departure, Point, _),
\+ member(Point, Visited),
reachable(Point, Arrival, [Point|Visited]).
reachable(Departure, Arrival) :-
reachable(Departure, Arrival, [Departure]).
reach(Arrival, Departures) :-
setof(
Departure,
reachable(Departure, Arrival),
Departures
).

Prolog: How to get oldest and youngest in bloodline

Let's say that I have a bloodline of male population Williams and Skywalker families as my knowledge base:
father(phil,tom, williams).
father(tom, bob, williams).
father(bob, robert, williams).
father(robert, steve, williams).
father(anakin, luke, skywalker)
father(luke, finn, skywalker)
father(finn, andrew, skywalker)
father( andrew, charles, skywalker)
Which rule can I use to know the oldest and youngest in bloodline?
For example
?- oldestYoungest(skywalker,X,Y)
should return
X = anakin
Y = charles
This works with your Knowledge Base (KB) looking the way it does now.
youngest(LastName, Son) :-
father(_, Son, LastName),
\+father(Son, _, LastName).
oldest(LastName, Father) :-
father(Father, _, LastName),
\+father(_, Father, LastName).
oldestYoungest(LastName, Oldest, Youngest) :-
youngest(LastName, Youngest),
oldest(LastName, Oldest).
You should note that Prolog variables are upper-case and constants (or facts) are lower-case.
Technically, this answer finds oldest as the person with no father in the KB and the youngest and the person with no son in the KB. It works because your KB is defined that way.

Prolog find flights

I'm having some issues with the findall/3 in Prolog.
Facts:
%
country(dublin,ireland).
country(cork,ireland).
country(london,uk).
country(rome,italy).
country(moscow,russia).
country(hongkong,china).
country(amsterdam,holland).
country(berlin,germany).
country(paris,france).
country(newyork,usa).
country(chicago,usa).
country(sao_paulo,brazil).
country(rio,brazil).
I need to write predicate to show the connections from city X to city Y (one by one). X and Y are the two inputs (city) and T is the output. Each solution T is a list of all the cities connecting X to Y (X and Y included).
Example:
| ?- trip(rome,dublin,T).
T=[rome,london,dublin] ;
//first solution T=[rome,paris,dublin];
//second solution
my try is
path(X,Y,[X|Y]):- edge(X,Y).
path(X,Y,[]):- edge(X,Z),not(member(Z,V)),path(Z,Y,[Z|V]).
Any ideas would be greatly appreciated.
Cheers,
I think your question is: "how can I display all possible trip between two country ?". If so I advice you to do something like that:
trip(X,Y,T) :- X \= Y,
path(X, Y, [X], T).
path(Departure, Arrival, Visited, go(Departure, Arrival)) :- direct(Departure, Arrival) , !.
path(Departure, Arrival, Visited, go(Departure, Intermediate, GO)) :-
direct(Departure, Intermediate),
Intermediate \= Departure,
\+ member(Intermediate,Visited),
path(Intermediate, Arrival, [Intermediate|Visited], GO).
So I also advice you to modify the facts in your knowledge base like:
direct(rome, moskow).
direct(moskow, paris).
direct(paris, chicago).
direct(sau_paolo, rio).
direct(rio, honkong).
and so on.
What you did is logically uncorrect. How can you know if you can travel from a city to another only knowing where they are? There should be some facts that state that is possible travel from a city to another, e.g. direct(rome, milan) (or travel(rome, milan), you choose the functor).
I hope to have help you.
If you have some dubt, just ask ;)
by use prolog
Timetable of air routes
Each air route can be described by a structure:
country of departure, country of landing, date of departure, time of departure, duration, tariffs.
Tariff can described by a structure:
price for business class, price for economy class.
Implement the following rules:
• Find all routes from the given country
• Find all routes to the given country with duration less then than the given number
• Find all routes with the cheapest price for economy class
• Find all prices for flying from one given country to another given country

Family database prolog query

I am using the below family database to practice prolog. I want to...
'Find the first name and surname of mothers whose children’s combined incomes are
greater than £140,000, where at least one child is unemployed. The rule should also return
the first name of the unemployed child/children, and the value of the children’s combined
incomes'
so far I have this code...Help would be appreciated, really struggling on this exercise. thanks :)
(Fname,Sname,Income):-
family(person(_,_,_,_),person(Fname,Sname,_,_),Children),
total(Children,Income),
Income > 140000.
.
total([Person|List],Sum):-
salary(Person,S), % S: salary of the first person
total(List,Rest), % Rest: sum of salaries of others
Sum is S + Rest.
.
family(
person(pat,marx,date(10,march,1944),unemployed),
person(charlotte,marx,date(11,february,1946),unemployed),
[
person(aine,marx,date(17,april,1985),unemployed),
person(louis,marx,date(25,june,1980),works(harriott,32000)),
person(pearl,marx,date(10,june,1981),unemployed),
person(pat_jr,marx,date(11,march,1983),works(world_of_food,850000)),
person(ricky,marx,date(18,february,1987),unemployed)
]
).
family(
person(fred,chomsky,date(3,october,1955),works(bean_counters,100000)),
person(sarah,chomsky,date(19,october,1961),works(supercomms, 60000)),
[
person(amos,chomsky,date(1,july,1984),works(sell_cell, 80000))
]
).
family(
person(ted,marx,date(10,july,1948),unemployed),
person(adelheid,marx,date(9,december,1948),unemployed),
[ person(ted_jr,marx,date(14,april,1988),works(world_of_food,90000)),
person(jenny,marx,date(23,may,1984),unemployed),
person(margaret,marx,date(23,may,1984),unemployed),
person(sadie,marx,date(23,may,1984),unemployed),
person(louis,marx,date(22,august,1979),unemployed),
person(alan,marx,date(9,may,1990),unemployed)
]
).
family(
person(ted,russell,date(21,may,1938),retired),
person(victoria,russell,date(9,november,1944),retired),
[ person(betty,russell,date(18,august,1971),works(boat_house,65000)),
person(jack,russell,date(27,may,1965),works(green_machine,15000)),
person(joan,russell,date(9,april,1963),works(green_machine,15000)),
person(penelope,russell,date(9,april,1963),works(green_machine,15000)),
person(enda,russell,date(2,november,1968),works(exc-u-vate,15000)),
person(amos,russell,date(27,may,1965),works(green_machine,15000)),
person(algernon,russell,date(2,november,1968),works(exc-u-vate,15000)),
person(cal,russell,date(9,october,1970),works(sell_cell,30000))
]
).
family(
person(bill,kant,date(7,august,1942),works(fibrefast,100000)),
person(ann,kant,date(9,october,1945),works(roulada,100000)),
[ person(mark,kant,date(25,april,1970),works(harriott,36000)),
person(cal,kant,date(22,december,1966),works(harriott,35000)),
person(simon,kant,date(27,january,1965),works(harriott,31000)),
person(sol,kant,date(17,november,1964),unemployed),
person(andrew,kant,date(9,march,1968),works(harriott,32000)),
person(joan,kant,date(27,january,1965),works(harriott,34000))
]
).
family(
person(ted,russell,date(6,june,1950),works(mopper-ups,25000)),
person(helen,russell,date(10,june,1951),works(harriott,110000)),
[ person(maura,russell,date(21,february,1972),works(sparrow_hotel,19000)),
person(simon,russell,date(24,december,1970),works(zoom-away,50000)),
person(victoria,russell,date(23,january,1971),works(volts,49000)),
person(andrew,russell,date(24,june,1969),works(sparrow_hotel,35000)),
person(cal,russell,date(15,april,1974),works(sparrow_hotel,55000)),
person(milly,russell,date(21,february,1972),works(sparrow_hotel,19000))
]
).
This is a very odd database layout, but that doesn't need to stop us. First the head of the rule with the things we're going to return:
q(MotherFirst, MotherLast, UnemployedKids, CombinedIncome) :-
We're considering families here, so let's match them and pull out the mother's info:
family(_, person(MotherFirst, MotherLast, _, _), Children),
The underscores there correspond to the father, the mother's date-of-birth and occupation. None of those are relevant to the problem so forget 'em. Next we need to do some processing on the kids: we need to find the ones that are unemployed and get the combined income. I will do two traversals because it's simpler for me. First the sum of their income:
total_income(Children, CombinedIncome),
CombinedIncome > 140000,
unemployed(Children, UnemployedKids),
UnemployedKids = [_|_]. % ensure we have at least one unemployed kid
I've broken the task down a little bit; let's go ahead and write some helpers:
% compute the total income for a list of people
total_income([], 0).
total_income([person(_, _, _, works(_, Amount) | People], Total) :-
total_income(People, Subtotal),
Total is Subtotal + Amount.
% find the unemployed people in a list of people
unemployed([], []).
unemployed([person(FN, LN, DOB, unemployed) | People],
[FN | Unemployed]) :-
!, % cut so that we don't enter the next rule with someone who is unemployed
unemployed(People, Unemployed).
unemployed([_|People], Unemployed) :- unemployed(People, Unemployed).
Both of those could be simplified considerably using library(aggregate) or even some folds (perhaps with library(lambda) but this is a straightforward "classic" (wordy) solution.

Prolog oldest Successor

I'm working on a simple program that has a database of people. When given a year it should state the "King" of that year, where the king is the eldest living man.
For simplicity, all people in the database are eligible as long as they are alive at the given year and I'm assuming there are no twins.
My problem is picking the "oldest" person alive during a given year. I can't seem to figure out how to ask Prolog to examine all possible kings and pick the oldest.
male(jack).
male(roy).
male(ele).
born(jack,2000).
born(dave,1999).
born(roy,1980).
born(ele,1990).
died(jack, 2100).
died(dave, 2099).
died(roy, 1990).
died(ele, 1999).
% compare X against all other possibleSuccessors and make sure he was born 1st.
eldest(X,Year):-
born(X,T1),
born((possibleSuccessor(Year,_)),T2),
T1 < T2.
% must be male and have been born before or during the given year and must not be dead.
possibleSuccessor(Year, X):-
male(X),
born(X,B),
died(X,D),
(B =< Year),
(D >= Year).
successor(Year):-
possibleSuccessor(Year,X),
eldest(X,Year),
write(X).
Any help on comparing all possible answers vs one another would be appreciated. I attempted to use findall before but was unsuccessful.
Prolog offers a restricted form of negation (negation by failure) that solve your problem:
eldest(X,Year):-
born(X,Year),
\+((born(_,T), T<Year)).
this says that X is eldest if we can't find any other born before him.
alternatively, setof/3 can be used:
eldest(X,Year):-
setof((Y,K), born(K,Y), [(Year,X)|_]).
this works sorting all pairs (Y,K), then we can pick just the head of the result.
edit this should solve the problem, but I've introduced a service predicate
eldest(X, Year):-
alive(X, Year, B),
\+((alive(_, Year, T), T<B)).
alive(X, Year, B) :- born(X, B), B =< Year, \+ (died(X, D), D < Year).
% must be male and have been born before or durring the given year and must not be dead.
possibleSuccessor(Year,X):-
male(X),
alive(X, Year, _).
successor(Year):-
possibleSuccessor(Year,X),
eldest(X,Year),
write(X).

Resources