Getting the Helper function to compile - list

I am trying to get this list to parse through a knowledge base, but I am having trouble getting the helper function to work.
The program I am trying to create, outputs a list of quests from a knowledge base which comes from at least 2 quest types, and has to have a total experience value below a cutoff.
format of allquest is:
allquest(Questtext,QuestType,ExpvalueofQuest).
allquest(water for village,Main quest, 2000).
allquest(get book for elder,fetch quest,1000).
allquest(kill 20 birds, bounty quest, 1000).
questCheck([], [_], Tot) :- Tot >= CUTOFF.
questCheck([H|T], [ListOfTypes], Tot) :- allQuests(H, Type, Exp), T2 is Tot + Exp,
questCheck(T, [Type|ListOfTypes], T2).
questCheckH([H|T]) :- allQuests(H, Type, Exp), questCheck(H, [Type], Exp).
Overall the logic of the ruleset is that it takes in a list as a parameter, iterates through that list keeping track of the exp total of each quest, Once the list has been completely iterated through it checks the total against some numbers to make sure it's 'Ok.', then it returns.
However if I input an uninstanctiated list [A], it should return list combination that fulfill my requirements.
the code should work like this if CUTOFF = 3000
?-questCheckH([A]).
water for village,get book for elder
;water for village, kill 20 birds
;get book for elder, water for village
;get book for elder, kill 20 birds, water for village
;kill 20 birds, water for village
;kill 20 birds, get book for elder, water for village
I know I need to work a T into the questCheckH with an additional predicate but am not sure how to word the predicate I need.

Related

Prolog - split a list into lists of lists

The list to be split is a list of guests that attend a dinner. The dinner has three meals (appetizer, main, and dessert). The result of the type list of lists should be a list for each of the meals with the sub-lists showing the people who eat that meal together.
eg.:
Appetizer: [[Tick, Trick, Track],[Tic, Tac, Toe], [Jerry, Larry, Harry]]
Main: [[Tick, Tic, Jerry], [Trick, Tac, Larry],[Track, Toe, Harry]]
Dessert: [[Tick, Tac, Larry], [Trick, Toe, Harry], [Track, Tic, Jerry]]
The function I have to code:
make_dinner(?Starters, ?Main, ?Dessert, +List_of_Persons, +Group_size):-
Group size is the size of the groups (in the example above three)
I don't know how to approach this problem using prolog language. I can easily code this in Java, which I'm really good at. But the recursion and logic here are very confusing to me. There's no "return" argument, no "if" statement", just a bunch of commas :")
My idea was to:
find out how many groups I need (depends on group size and list length)
fill the appetizer list with the original order of the list. Count it off and split the list after every group size position to get the list of lists for an appetizer (the most intuitive way I think)
fill the first sub-list of the "main" list with the first element of the list, then the second element of the other sub-lists from the "appetizer" list. Fill the second sub-list with the second element of the first sub-list of "appetizer", then the third element of the next sub-lists in "appetizer", and so on and so forth.
If the number doesn't match (eg. list length 10 but group size 3), I will simply have one group that's smaller. No person eats twice with the same person.
Does my idea work in Prolog? Can I implement that logic?
I don't really know how to approach this task because I'm very new to Prolog. I will have the main function below, then I need a helper_function called get_number_of_groups to know how many elements go into each list. And I have one function to get the size of the list.
How do I make the starters, main, and dessert into a list of lists? I know about recursion but somehow I don't know where to go from here.
%make_rudi: main function
%return: starters, main, and dessert; each list of lists
make_rudi(Starters, Main, Dessert, List_of_Persons, Group_size):-
get_number_of_groups(List_of_Persons, Group_size, Number),
%get_number_of_groups(+List_of_Persons, +Group_size, ?Number)
%return: the number of groups I have for each meal
get_number_of_groups(List_of_Persons, Group_size, Number):-
Number is list_length(Xs, List_of_Persons)/Group_size.
%list_length(?Xs,+L)
%the length of the list
list_length(Xs,L) :-
list_length(Xs,0,L) .
list_length( \[\] , L , L ) .
list_length( \[\_|Xs\] , T , L ) :-
T1 is T+1 ,
list_length(Xs,T1,L).

Search all fathers with conditions in Prolog

I have a family tree program in Prolog that contain next facts:
male(alex).
male(david).
male(peter).
etc
...
female(sofia).
etc
....
parent(alex, peter).
parent(sofia, peter).
etc
....
and some rules such as:
father(X, Y) :- parent(X, Y), male(X).
mother(X, Y) :- parent(X, Y), female(X).
etc
....
I need to find all fathers who has two or more children.
I think that I need to go through all fathers im my program, put their children to list and count it's length, then if >=2 I add this father to another list or just print him and go further.
Although in the general case when you want to find all fathers with at least N children your approach would be required, a much simpler approach is available when you are dealing with only two children: find a child twice, and see if the two children are different.
In Prolog this rule would look like this:
father_of_two(X) :-
father(X, A),
father(X, B),
A \= B.
All you need to do now is collecting all people who match father_of_two predicate into a list.

Prolog list not printing all the elements on console

I am using SWI-PROLOG version 6.6.6
I want to print all the attributes of a particular predicate type.
I have a predicate called law with arity 2.
Some of the facts are
law(borrow,'To borrow Money on the credit of the United States').
law(commerce,'To regulate Commerce with foreign Nations, and among the several States, and with the Indian Tribes').
law(unifomity,'To establish an uniform Rule of Naturalization, and uniform Laws on the subject of Bankruptcies throughout the United States').
law(money,'To coin Money, regulate the Value thereof, and of foreign Coin, and fix the Standard of Weights and Measures').
law(punishment,'To provide for the Punishment of counterfeiting the Securities and current Coin of the United States').
law(establishment,'To establish Post Offices and post Roads').
law(exclusiverights,'To promote the Progress of Science and useful Arts, by securing for limited Times to Authors and Inventors the exclusive Right to their respective Writings and Discoveries').
law(court,'To constitute Tribunals inferior to the supreme Court').
etc.
Now I want to access a law by entering its type.
Such as,
power(X) :- law(X,Y), display('\nCongress has the power : '),display(Y).
powers(ALL) :- display('\nCongress has the powers : '), law(_,Y), display('\n'), display(Y).
This works perfectly. Now, I also want the user to know what all types of laws are there so that the user can enter it as a query to get the corresponding law.
ex power(money).
For this, I made a query to get all these keywords and add them to a list and display the list.
But the list that is finally printed is not complete.
powerList(L) :- findall(X,law(X,_), L).
I use this code to get the list.
But the output on the console is
L = [borrow, commerce, unifomity, money, punishment, establishment, exclusiverights, court, piracyfelony|...].
But, there are more law types even after piracyfelony and they are not getting printed to the console. How do I get them printed?
This is a feature of Prolog's toplevel loops that tries to keep the output short.
To find out how you might change it, ask which Prolog flags your Prolog supports that have a value being a list of at least two elements:
?- current_prolog_flag(F,Options), Options = [_,_|_].
F = debugger_print_options,
Options = [quoted(true), portray(true), max_depth(10), attributes(portray), spacing(next_argument)] ;
F = toplevel_print_options,
Options = [quoted(true), portray(true), max_depth(10), spacing(next_argument)] ;
F = argv,
Options = [swipl, '-f', none] ;
false.
Now modify it accordingly:
?- length(L,10).
L = [_G303, _G306, _G309, _G312, _G315, _G318, _G321, _G324, _G327|...].
?- set_prolog_flag(toplevel_print_options,[quoted(true), portray(true), max_depth(0), spacing(next_argument)]).
true.
?- length(L,10).
L = [_G303, _G306, _G309, _G312, _G315, _G318, _G321, _G324, _G327, _G330].
(In newer versions starting with SWI 7 there is another flag value, answer_write_options.)

Clingo: assert partial constraints

I am trying to implement a program in clingo that solves one of those classic riddles where you have a series of assertions of facts and constraints and you have to deduce other facts. Here goes the problem:
Five men of different nationalities live in five side-by-side houses, each of a different color; they all have different jobs, a different favourite animal and favourite beverages. We know that:
The English man lives in the red house.
The Spanish man's favourite animal is the dog.
The Japanese man is a painter.
The Italian man drinks tea.
The Norwegian man lives in the first house from the left. (number_norw = 1)
The person living in the green house drinks coffee.
The green house is immediately right of the white one. (number_green = number_white + 1)
The clerk loves cats.
The salesman lives in the yellow house.
Milk is the favourite drink in the center house. (number_milk = 3)
The Norwegian's house is adjacent to the blue one. (number_norw = number_blue ± 1)
The cook likes juice.
The man living in the house next to the doctor's loves foxes.
The man who loves horses lives next door to the salesman.
The assignment is to find out who likes zebras.
So I set forth asserting:
% Number (the number of the house, 1 being the leftmost of the block, 5 the rightmost)
number(1..5).
% Color
color(red;green;white;yellow;blue).
% Nationality
nationality(english;spanish;japanese;italian;norwegian).
% Animal
animal(dog;cat;fox;horse;zebra).
% Job
job(painter;clerk;salesman;cook;doctor).
% Beverage
beverage(tea;coffee;milk;juice;coke).
% House
house(X, C, N, A, J, B) :-
number(X),
color(C),
nationality(N),
animal(A),
job(J),
beverage(B).
Now I'm stuck on asserting the constraints; how do I go about coding assertions 1. through 14.? I just need to understand the proper syntax, so if someone could please set me on the right track with one or two examples I can figure out the rest.
Thanks.
N.B. Notice I could have inferred, from 5. and 11., that the second house is the blue one because 11. number_blue = number_norw ± 1, 5. number_norw = 1, and 0 is not in the range of possible numbers, but I don't want to manually add it to the constraints because I expect clingo to figure it out itself.
One way to add the constraint for the first assertation:
% 1. The English man lives in the red house.
% S: english --> red house <==> red house OR not english
% not S: not (red house OR not english) <==> not red house AND english
% ie. it is not so, that the english man doesn't live in the red house
:- not 1 { house(X, red, english, A, J, B) :
number(X) : animal(A) : job(J) : beverage(B) }.
and as another example the seventh assertation:
% 7. The green house is immediately right of the white one.
% (number_green = number_white + 1)
:- house(NG, green, _, _, _, _), house(NW, white, _, _, _, _), NG!=NW+1.
This will however lead to long solving times and large memory requirements (gigabytes), because the grounded program (output of gringo) is massive. You can see this with gringo -t yourcode.asp. This is because the "do not care" variables _ (and X, A, J, B in the constraint for the first assertation above). Each rule will be written in at least 5*5*5*5 ways.
M. Gebser adviced me that the predicates (relations) should be kept short. The problem with this encoding of the instance is that house/6 is so long. One way to combat this would be to encode it in the following style:
house(1..5).
elem(color, red;green;white;yellow;blue).
elem(nationality, english;spanish;japanese;italian;norwegian).
...
and start from there. Now the arity of elem is only 2. When the instance is defined this way, the program becomes simpler eg. the constraints for the assertations do not need aggregates (the 1{ ... }N syntax).
:- not chosen(H, nationality, english), chosen(H, color, red).
M. Gebser also suggested that the solver (clasp) might benefit form the rule being written in the other way too:
:- not chosen(H, nationality, english), chosen(H, color, red).
:- chosen(H, nationality, english), not chosen(H, color, red).
You also need some additional restrictions, like that two different elements of the same type shouldn't be mapped to one house.
For nicer output, you can make a relation that gives the output like house/6 did.
Note that I used gringo3 and clasp2, which are not the newest versions. If you have the new clingo, there might be modifications that are needed.

Two different databases, sth which are wanted are mixed. I could not get over it. PROLOG

this is really hard question. I have an exam. And questions will be like that. They are really hard. These are my database:
director (martinscorsese, american, 1, 51).
director (hayaomiyazaki, japanese, 1, 23).
director (stevenspielberg, american, 3, 49).
director (georgelucas, american, 0, 19).
director (christophernolan, american, 0, 10).
watched(departed, [george, jane, eric]).
watched(theaviator, [jane,eric]).
watched(swrevengeofthesith, [paul,eric]).
watched(transformers, [paul, george, jane]).
I want to implement the predicate audiance(A,N,O,L1) that returns the list of all movies (L1) not yet seen by anyone in A, which has been directed by a director of Nationality N who won at least O oscars. The list L must not contain any duplicates.
audiance([paul],american,1,X). returns X=[ departed, theaviator ]
audiance([paul,george],N,0,X). returns N=american X= [theaviator]
audiance(X,american,0,[swrevengeofthesith]). returns X=[jane,george]
audiance([paul,george,jane],N,0,X). returns false
plz help me :))
i could just post code but i dont think it would help to pass the exam
you should divide the problem into smaller and easier sub-problems.
1) a predicate not_seen(Movie,People) that returns true only if nobody in the list People have seen the Movie
2) a predicate director_nationality(Movie, Nationality) that returns true if the director of the Movie has the given nationality
3) a predicate director_oscars(Director, Num_Oscars) that returns true if the director has won at least Num_Oscars oscars
then you have to combine all these in one predicate which you can call movie_requirements(Movie).
finally, to find all the movies you can use findall/3
to ensure that there wont be any doublicates you could use sort/2 that will remove any duplicates or use bagof/3 instead of findall/3
check member/2 and the other built-in predicates for lists