Related
I have facts like that :
student(stud01, 'Programming 1', 90).
student(stud01, 'Math 1', 78).
student(stud01, 'Statistics 1', 94).
student(stud01, 'Electronics 1', 81).
student(stud01, 'Management', 66).
student(stud01, 'English', 83).
i want to build a predict that take the student id and and put all its grade in list
and after that take the max grade
i try this :
stuGrade(ID,List):-
stuGrade([],ID,List).
stuGrade(TmpList,ID,List):-
student(ID,Course,Grade),
not(mem([ID],TmpList)), !,
append_List([Grade],TmpList,NewTmpList),
stuGrade(List,ID,NewTmpList).
stuGrade(List,ID,List).
maxStudentGrade(ID,Max):-
stuGrade(ID,L),
max(L,Max).
but the problem that after using ?-trace. i see that the output list containing only the first grade (90) how can i slove this problem
Suppose that you begin with ?- stuGrade(stu01, List).
Then you will get the first student entry at least. And you say there is some issue after that.
So, a simple way to check is to test by using the first part of the query, such that,
?- ID = stu01, TmpList = [],
student(ID,Course,Grade),
not(mem([ID],TmpList)), !.
When you find its result is false, stop and check the last predicate.
Using break points
trace/0 and nodebug/0 are nice tools.
You may want to check issues by like the following,
stuGrade(TmpList, ID, List) :-
student(ID, Course, Grade),
trace, % <------------------ Put a break point here.
not(mem([ID], TmpList)),
nodebug, % <----------------- Here, stop tracing.
!,
append_List([Grade], TmpList, NewTmpList),
stuGrade(List, ID, NewTmpList).
Good luck.
And you code...
stuGrade(ID,List):- stuGrade([],ID,List).
stuGrade(TmpList, ID, List):-
student(ID, Course, Grade),
not(mem([ID], TmpList)),
!,
append_List([Grade], TmpList, NewTmpList),
stuGrade(List, ID, NewTmpList).
stuGrade(List,ID,List).
Not bad. But, consider the first clause of stuGrade/3.
When you get a Grade, it's prepended to TmpList and you get NewTmpList. But at the next line, the newly built list is put as the third argument, as you know that it's for the final returned List.
It cannot be that. The first parameter of stuGrade/3, TmpList, is the accumulating parameter. Then NewTmpList might be placed as the first argument of the recursive query, such that stuGrade(NewTmpList, ID, List).
i'am new in Prolog ,
i tried to write 5 lists and get the intersection between them ,
how i can achieve that, ** lists will be defined in file so it's not input from the user .
i see many resources they implement it with two lists and its work fine if i make list as query from user ...
but when i try to pre-defined lists in file it's not work.
simple description of part of my project to more clarify...
menus will display and user will select one from each of the season , weather condition , occasion...
lists will be about what clothes are appropriate
so for example user select "winter" season, "rainy" weather condition and "wedding"occasion
lists for each of them
rainy([take_umbrella, jacket,coat]).
winter([jacket,sweater,coat,take_umbrella]).
wedding ([take_umbrella,dress,jacket,coat]).
so the result form intersection will be take_umbrella ,jacket,coat
i hope my idea is clear, and thank you in advance:)
I try to predefined lists in file and it's work. Y your lists in file it's not work? I do not know. I fix your errors because your paste is not error free then it's work.
?- winter(Winter),
rainy(Rainy),
wedding(Wedding),
intersection(Winter, Rainy, Winter_and_Rainy),
intersection(Winter_and_Rainy, Wedding, Winter_and_Rainy_and_Wedding).
Winter = [jacket, sweater, coat, take_umbrella],
Rainy = [take_umbrella, jacket, coat],
Wedding = [take_umbrella, dress, jacket, coat],
Winter_and_Rainy = Winter_and_Rainy_and_Wedding, Winter_and_Rainy_and_Wedding = [jacket, coat, take_umbrella].
But if it's not know how many list maybe you make list and reduce.
?- % make some lists L1, L2, ..., Ln,
foldl(intersection, [L1, L2, ..., Ln-1], Ln, Intersection).
When is winter on a rainy wedding you reduce like:
?- winter(Winter), rainy(Rainy), wedding(Wedding),
foldl(intersection, [Winter, Rainy], Wedding, Intersection).
Winter = [jacket, sweater, coat, take_umbrella],
Rainy = Intersection, Intersection = [take_umbrella, jacket, coat],
Wedding = [take_umbrella, dress, jacket, coat].
You see order of element is change but is it problem? For me no problem.
I have predicates of students and sports they do, and I want to find out which students do a particular sport. I have this sofar, but i can only get results if I enter exact sports in a list , and my find predicate works only to find a sport in a list. I don't know how to put it together to use to find students that do 1 sport:
student('Quinton Tarentino', male, 12).
student('Tom Hanks', male, 9).
student('Ed Harris', male, 11).
does_sport('Quinton Tarentino', [soccer, hockey, cricket]).
does_sport('Tom Hanks', []).
does_sport('Ed Harris', [hockey, swimming]).
sports([soccer, hockey, swimming, cricket, netball]).
find(X) :- sports(L), member(X, L).
I tried things like:
?- does_sport(X, find(soccer, L)).
This just returns false. I know I need to link my sports list to the does_sports predicate but not sure how.
Any advice appreciated :)
To find out which students do a particular sport, you could define a predicate like so:
student_sport(St,Sp) :-
does_sport(St,L), % L is a list of sports student St does
member(Sp,L). % Sp is a member of list L
Then you can query for e.g. soccer, as you seem to intend in your question, like so:
?- student_sport(St,soccer).
St = 'Quintin Tarentino' ? ;
no
Hockey on the other hand yields two results:
?- student_sport(St,hockey).
St = 'Quintin Tarentino' ? ;
St = 'Ed Harris' ? ;
no
If you want to have a list of students doing hockey instead, you can use findall/3 like so:
?- findall(St,student_sport(St,hockey),L).
L = ['Quintin Tarentino','Ed Harris']
Or alternatively setof/3 to get a sorted list (without duplicates, in case you happened to have facts that contain any):
?- setof(St,student_sport(St,hockey),L).
L = ['Ed Harris','Quintin Tarentino']
Note that in some Prologs you might have to explicitly include a library to use member/2, e.g. in Yap: :- use_module(library(lists))., while others autoload it, e.g. SWI.
EDIT:
Concerning the issues you raised in your comment, let's maybe start with your observation that student_sport/2 produces the answers one at a time. That is intentional, as suggested by the predicate name that contains the word student in singular: It describes a relation between a student and a particular sport that very student practices. That's why I added the example queries with findall/3 and setof/3, to show ways how you can collect solutions in a list. You can easily define a predicate students_sport/2 that describes a relation between a particular sport and a list of all students who practice it:
students_sport(L,Sp) :-
setof(St,student_sport(St,Sp),L).
Concerning the sports-austere, you can choose an atom to denote that case, say none and then add an according rule to student_sport/2 like so:
student_sport(St,none) :- % <- rule for the sports-austere
does_sport(St,[]). % <- succeeds if the student does no sport
student_sport(St,Sp) :-
does_sport(St,L),
member(Sp,L).
This yields the following results:
?- student_sport(St,none).
St = 'Tom Hanks' ? ;
no
?- students_sport(St,none).
St = ['Tom Hanks']
?- students_sport(St,hockey).
St = ['Ed Harris','Quintin Tarentino']
?- students_sport(St,Sp).
Sp = cricket,
St = ['Quintin Tarentino'] ? ;
Sp = hockey,
St = ['Ed Harris','Quintin Tarentino'] ? ;
Sp = none,
St = ['Tom Hanks'] ? ;
Sp = soccer,
St = ['Quintin Tarentino'] ? ;
Sp = swimming,
St = ['Ed Harris']
And finally, concerning your assumption of your code being exactly as I wrote it: There is a similarity in structure, namely your predicate find/1 having a first goal (sports/1) involving a list and subsequently using member/2 to check for membership in that list. The second rule (or single rule before the edit) of student_sport/2 is also having a first goal (but a different one: does_sport/2) involving a list and subsequently using member/2 to check for membership in that list. Here the similarities end. The version I provided is not using sports/1 at all but rather the list of sports associated with a particular student in does_sport/2. Note that find/1 does not describe any connection to students whatsoever. Furthermore your query ?- does_sport(X, find(soccer, L)). indicates that you seem to expect some sort of return value. You can regard predicates as functions returning true or false but that is usually not very helpful when programming Prolog. The argument find(soccer,L) is not being called as you seem to expect, but literally passed as an argument. And since your facts do not include something along the lines of
does_sport(*SomeStudentHere*, find(soccer,L)).
your query fails.
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.)
I have trouble sorting two related but separate lists of tuple lists. One list is made up of tuple lists representing a blog post. The other list is made up of tuple lists representing a comment post.
The problem is when you would like the same order based on blog id value. The lists for blog posts is sorted via the date value. So you cannot just sort numerically via blog id for both blog and comment post. And you cannot just sort the comment post via date value because the date values of blog and related comment post may be different.
I am not sure how to approach the problem - at least not in an elegant way.
Should I use lists:nth and consequently get each tuple list and position value? Then I would get the value of blog id, Then I would search in the list for comment posts for that id. Get the value of that tuple list. Associate the value of that tuple list in a new list with the appropriate nth position value.
Should I use the lists:sort function?
Any suggestions with code samples much appreciated.
Here are two sample lists of tuple lists that can be used as a basis :
[[{<<"blog_id">>,<<"a2">>},
{<<"postDate">>,<<"2010-12-4T6:10:12">>},
{<<"message">>,<<"la di da bo di do">>}],
[{<<"blog_id">>,<<"b8">>},
{<<"postDate">>,<<"2009-12-3T10:09:33">>},
{<<"message">>,<<"that is cool">>}],
[{<<"blog_id">>,<<"a9">>},
{<<"postDate">>,<<"2009-12-2T18:12:29">>},
{<<"message">>,<<"i like san francisco">>}]]
[[{<<"comment_id">>,<<"n6">>},
{<<"related_blog_id">>,<<"b8">>},
{<<"postDate">>,<<"2010-12-5T15:10:12">>},
{<<"message">>,<<"yup really neat">>}],
[{<<"comment_id">>,<<"y2">>},
{<<"related_blog_id">>,<<"a9">>},
{<<"postDate">>,<<"2009-12-6T10:09:33">>},
{<<"message">>,<<"yes but rent is expensive">>}],
[{<<"comment_id">>,<<"x4">>},
{<<"related_blog_id">>,<<"a2">>},
{<<"postDate">>,<<"2009-12-5T16:12:29">>},
{<<"message">>,<<"sounds like a hit">>}]]
And the desired output is the following with first list unchanged and second list reordered :
[[{<<"blog_id">>,<<"a2">>},
{<<"postDate">>,<<"2010-12-4T6:10:12">>},
{<<"message">>,<<"la di da bo di do">>}],
[{<<"blog_id">>,<<"b8">>},
{<<"postDate">>,<<"2009-12-3T10:09:33">>},
{<<"message">>,<<"that is cool">>}],
[{<<"blog_id">>,<<"a9">>},
{<<"postDate">>,<<"2009-12-2T18:12:29">>},
{<<"message">>,<<"i like san francisco">>}]]
[ [{<<"comment_id">>,<<"x4">>},
{<<"related_blog_id">>,<<"a2">>},
{<<"postDate">>,<<"2009-12-5T16:12:29">>},
{<<"message">>,<<"sounds like a hit">>}],
[{<<"comment_id">>,<<"n6">>},
{<<"related_blog_id">>,<<"b8">>},
{<<"postDate">>,<<"2010-12-5T15:10:12">>},
{<<"message">>,<<"yup really neat">>}],
[{<<"comment_id">>,<<"y2">>},
{<<"related_blog_id">>,<<"a9">>},
{<<"postDate">>,<<"2009-12-6T10:09:33">>},
{<<"message">>,<<"yes but rent is expensive">>}]]
Ok, new try then :)
We have:
-module(foo).
-compile(export_all).
Basic module exports to test the thing
blogs() ->
[[{<<"blog_id">>,<<"a2">>},
{<<"postDate">>,<<"2010-12-4T6:10:12">>},
{<<"message">>,<<"la di da bo di do">>}],
[{<<"blog_id">>,<<"b8">>},
{<<"postDate">>,<<"2009-12-3T10:09:33">>},
{<<"message">>,<<"that is cool">>}],
[{<<"blog_id">>,<<"a9">>},
{<<"postDate">>,<<"2009-12-2T18:12:29">>},
{<<"message">>,<<"i like san francisco">>}]].
Your definition of blogs.
comments() ->
[[{<<"comment_id">>,<<"n6">>},
{<<"related_blog_id">>,<<"b8">>},
{<<"postDate">>,<<"2010-12-5T15:10:12">>},
{<<"message">>,<<"yup really neat">>}],
[{<<"comment_id">>,<<"y2">>},
{<<"related_blog_id">>,<<"a9">>},
{<<"postDate">>,<<"2009-12-6T10:09:33">>},
{<<"message">>,<<"yes but rent is expensive">>}],
[{<<"comment_id">>,<<"x4">>},
{<<"related_blog_id">>,<<"a2">>},
{<<"postDate">>,<<"2009-12-5T16:12:29">>},
{<<"message">>,<<"sounds like a hit">>}]].
Your definition of comments.
sorted_comments() ->
[[{<<"comment_id">>,<<"x4">>},
{<<"related_blog_id">>,<<"a2">>},
{<<"postDate">>,<<"2009-12-5T16:12:29">>},
{<<"message">>,<<"sounds like a hit">>}],
[{<<"comment_id">>,<<"n6">>},
{<<"related_blog_id">>,<<"b8">>},
{<<"postDate">>,<<"2010-12-5T15:10:12">>},
{<<"message">>,<<"yup really neat">>}],
[{<<"comment_id">>,<<"y2">>},
{<<"related_blog_id">>,<<"a9">>},
{<<"postDate">>,<<"2009-12-6T10:09:33">>},
{<<"message">>,<<"yes but rent is expensive">>}]].
Your definition of being sorted.
sort(Blogs, Comments) ->
%% Create list of blog id's
Bs = [proplists:get_value(<<"blog_id">>, B) || B <- Blogs],
Fetch all the blog_id values from the Blogs.
%% Create the numbering
DB = dict:from_list([Item || Item <- lists:zip(Bs,
lists:seq(1, length(Bs)))]),
Number the order the blogs occur in. Stuff these into a dict for fast lookup later.
%% Sorter function:
F = fun(I, J) ->
II = proplists:get_value(<<"related_blog_id">>,
I),
JJ = proplists:get_value(<<"related_blog_id">>,
J),
dict:fetch(II, DB) =< dict:fetch(JJ, DB)
end,
This function compares two Comments, I, J to each other based on their related blog_id.
{Blogs, lists:sort(F, Comments)}.
Return what we want to return.
sort_test() ->
{blogs(), sorted_comments()} == sort(blogs(), comments()).
Tester function.
2> c(foo).
{ok,foo}
3> foo:sort_test().
true