how to get user input prolog and store it - prolog

I'm trying to have the user input their birthday so I can tell them their zodiac sign. However, I'm having trouble getting their actual birthday and month. Could someone please help me? I've tried separating the reads into different functors, but I keep getting errors. The error I get when I combine both reads is "Syntax error: Operator priority clash." The error I get when I separate both reads is "ERROR: =:=/2: Arguments are not sufficiently instantiated."
Code when I combine the reads:
start :-
read_month,
read_month :-
write('Enter your birth month (month followed by a .): '),
nl,
read(X),
write('Enter your day of birth (followed by a .): '),
nl,
read(Y),
horoscope(X,Y).
Code when I separate the reads:
start :-
read_month,
read_day.
read_month :-
write('Enter your birth month (month followed by a .): '),
nl,
read(X).
read_day :-
write('Enter your day of birth (followed by a .): '),
nl,
read(Y),
horoscope(X,Y).

As a beginner, do not start like that. (And your first program is syntactically incorrect ; the first rule does not end with a period).
Instead, write a relation month_day_sign/3 which you can use directly at the toplevel, like so:
?- month_day_sign(7,24,Sign).
Sign = leo.
That's the way how you normally interact with Prolog. So you are exploiting the functionality of the toplevel shell.
Once you have mastered this, you may make some extra interface around. But don't go the other way!
By separating both "actions", the X is now disconnected from horoscope(X,Y)...

Related

Prolog predicate with multiple lists

I'm using swipl but working the adventure tuorial from Amzi!. The syntax difference is causing me a headache. After setting up the facts, I have these statements
list_things(Place) :-
location(X, Place),
tab(2),
write(X), nl,
false.
list_connections(Place) :-
connect(Place, X),
tab(2),
write(X), nl,
false.
look :-
here(Place),
write('You are in the '), write(Place), nl,
write("You can go to: "), nl,
list_connections(Place), nl,
write('You can see: '), nl,
list_things(Place).
When I run look., it only outputs the first list from list_connections. That is
?- look.
You are in the kitchen
You can go to:
office
cellar
dining room
false.
Now, I understand the false at the end of the function is terminating the look, but I don't know the correct syntax in swipl.
Now, I understand the false at the end of the function is terminating the look
The false at the end of list_connections(Place) forces it to backtrack and retry, writing all the connected places as it does so. Once it has got through them all and failed for the last time, I think there is supposed to be another rule for it:
list_connections(_).
I see it here in Amzi! chapter 5:
That rule is a "succeed for anything" rule which will allow look to carry on and then list_things can run. And there is a similar one for list_things.

Prolog Returning Elements Within Facts to The User

I have a Prolog knowledge base with some "symptom" facts called facts.pl. Here is an example of my KB:
symptom("Typhoid", "muscle_pain").
symptom("Typhoid", "bloating").
symptom("Meningitis", "headache").
symptom("Meningitis", "fever").
symptom("Meningitis", "stiff neck" ).
symptom("Measles", "cough").
symptom("Measles", "runny_nose").
I have written a short prolog program in another file called "diseaseSearch.pl". This program consults facts.pl and is supposed to allow the user to enter a disease name and prints the disease's corresponding symptoms to the screen.
My code:
:- write('loading disease database'), nl.
:- [facts].
:- write('disease database loaded'), nl, nl.
getsymptoms:-
write('> Enter a diseae name followed by a period.'), nl,
write('For Example: Measles'), nl,
write('Disease Name?:'),
read(Input), nl,
symptom(Input,Output),
write(Output).
If I enter "Measles." the output should be "cough" and "runny_nose". However, with the code above no matter which disease I enter it always returns the result from the first fact which is "muscle_pain". SWI output found here
I found a similar method from an online tutorial, I am trying to learn the basics of Prolog input and output right now. Am I on the right track? Some tips to solve this problem would be greatly appreciated!
I guess you are entering Measles without " " and prolog takes it as a variables. Either you should enter it with "". If you enter Measles then it's a variables but if you enter "Measles" then it's a term.
If you want to enter without annotations then you need to make a database in which you have all terms(means that they start with small letter) then you don't need annotation.

Prolog Beginner - macbook

Current college student here and have to learn Prolog this semester. Wanted to mess around and get ahead and learn it before we actually get into any assignments and I am lost lol.
I am creating a project for a program where it is dedicated to movies
I have my movie.pl file with things such as:
%acted_in(person,movie).
acted_in(brad_pitt,babel).
acted_in(cate_blanchette,babel).
acted_in(sharlto_copley,district_9).
acted_in(david_james,district_9).
%directed(person,movie).
directed(alejandro_inarritu,babel).
directed(neill_blomkamp,district_9).
%released(movie,year).
released(babel,2006).
released(district_9,2009).
Those are just some of the ones I have in there. Now my teacher does have stuff up already since he recommended we went ahead and tried our own programs. He went ahead and gave us a makefile that is supposed to work with everything just needed to change the EXE=movie.
The part where I am lost is on the main.pl. Say I have multiple different questions to put in, how would I add them? Do I just add a writeln with a new question under the previous print_query_false?
%main.pl
:- [movie].
print_query_true(Q) :-
forall(Q, writeln(true:Q)).
print_query_false(Q) :-
forall(\+ Q, writeln(false:Q)).
main :-
nl
writeln( "1. Did Leonardo DiCaprio act in Babel?" ),
print_query_true(acted_in(leonardo_dicaprio,babel)),
print_query_false(acted_in(leonardo_dicaprio,babel)),
nl,
halt.
The last problem I have is when i try to run swipl it goes through and turns on the program. but when i type in [movie]. it just says true and doesn't show that is says compiled or anything of the sort.
The part where I am lost is on the main.pl. Say I have multiple different questions to put in, how would I add them? Do I just add a writeln with a new question under the previous print_query_false?
Yes, for example:
main :-
nl,
format( "1. Did Leonardo DiCaprio act in Babel?" ),
nl,
print_query_true(acted_in(leonardo_dicaprio,babel)),
print_query_false(acted_in(leonardo_dicaprio,babel)),
nl,
format( "2. Was babel released in 2006?" ),
nl,
print_query_true(released(babel, 2006)),
print_query_false(released(babel, 2006)),
nl,
format( "3. Did anyone act in both Click and The Aviator?" ),
nl,
print_query_true((acted_in(X, click), acted_in(X, the_aviator))),
print_query_false((acted_in(X, click), acted_in(X, the_aviator))),
nl,
format("4. Did sharlto_copley and david_james both act in district_9?"),
nl,
print_query_true((acted_in(sharlto_copley, district_9), acted_in(david_james, district_9))),
print_query_false((acted_in(sharlto_copley, district_9), acted_in(david_james, district_9))),
nl,
format("5. Was there any two movies released in 2006 and 2009?"),
nl,
print_query_true((released(X, 2006), released(Y, 2009))),
print_query_false((released(X, 2006), released(Y, 2009))),
nl,
format("6. What actors acted in babel or district 9?"),
nl,
print_query_true((acted_in(X, babel) ; acted_in(X, district_9))),
print_query_false((acted_in(X, babel) ; acted_in(X, district_9))),
nl,
format("6. What actors played in babel but not in district 9?"),
nl,
print_query_true((acted_in(X, babel), \+ acted_in(X, district_9))),
print_query_false((acted_in(X, babel), \+ acted_in(X, district_9))),
nl,
halt.
I changed writeln to format to get proper formatted strings in the output. Test run:
?- [main].
% movie compiled 0.00 sec, 9 clauses
% main compiled 0.00 sec, 15 clauses
true.
?- main.
1. Did Leonardo DiCaprio act in Babel?
false:acted_in(leonardo_dicaprio,babel)
2. Was babel released in 2006?
true:released(babel,2006)
3. Did anyone act in both Click and The Aviator?
false: (acted_in(_G1551,click),acted_in(_G1551,the_aviator))
4. Did sharlto_copley and david_james both act in district_9?
true: (acted_in(sharlto_copley,district_9),acted_in(david_james,district_9))
5. Was there any two movies released in 2006 and 2009?
true: (released(babel,2006),released(district_9,2009))
6. What actors acted in babel or district 9?
true: (acted_in(brad_pitt,babel);acted_in(brad_pitt,district_9))
true: (acted_in(cate_blanchette,babel);acted_in(cate_blanchette,district_9))
true: (acted_in(sharlto_copley,babel);acted_in(sharlto_copley,district_9))
true: (acted_in(david_james,babel);acted_in(david_james,district_9))
6. What actors played in babel but not in district 9?
true: (acted_in(brad_pitt,babel),\+acted_in(brad_pitt,district_9))
true: (acted_in(cate_blanchette,babel),\+acted_in(cate_blanchette,district_9))
SWI-Prolog have an awesome documentation so I advise you to check up the predicates used to understand them fully:
forall: forall/2.
nl: nl/0
writeln: writeln/1
halt halt/0
format format/1
Compilation: SWI-prolog compilation
The last problem I have is when i try to run swipl it goes through and turns on the program. but when i type in [movie]. it just says true and doesn't show that is says compiled or anything of the sort.
Make sure you are in the right directory where you have your source-files.
SWI-Prolog v6.6.4 output:
?- [movie].
% movie compiled 0.00 sec, 9 clauses
true.

Prolog read predicate cant read user key in in initialization?

I want to have a prolog program which can auto run once I compile finish and it should read input from user keyboard. However when i use
:- write('Your name is: '), nl, read(X).
there is not any effect on read(X), which it means that there us not any prompt for users to key in. Is there any solution for this problem? My prolog compiler is WIN-Prolog 5.0, thanks for your helo :)
maybe you need something like
:- initialization(main). % changed to be ISO compliant, was :- initialization main.
main :- write('Your name is: '), nl, read(X).
at least, ISO Prologs do it in this way....
Since read/1 is meant to parse Prolog (it's a full fledged parser), you must supply a Prolog term, and don't forget, as Joel76 suggested, to complete input with a dot: for instance:
Your name is:
|: 'Carlo'.

How to get both drive predicates working in prolog?

begin:-
go,
initialise. % drive predicate
begin:-
write('Sorry cannot help'),nl,nl.
go:-
write('Below is the list of the current toys available within the
store.'),nl,nl,nl,nl,
loop_through_list([car, football, action_men, train_tracks, lego, football, bikes, control_car, drees_up, doll, bear, furbies, craft, doll_house]).
loop_through_list([Head|Tail]) :-
write(Head),
write(' '),
loop_through_list(Tail).
initialise:-
nl,nl,nl,nl,
tab(40),write('******************************************'),nl,
tab(40),write('*** TOY GENERATING SYSTEM ***'),nl,
tab(40),write('******************************************'),nl,nl,
write('Please answer the following questions'),
write(' y (yes) or n (no).'),nl,nl, nl, nl.
The problem here is that the go:- and the initialise:- work separately when on their own, but not when put together. Is there a problem with all the nls?
The problem is that go/0 doesn't work corrently. While it prints the list, it fails at the end, meaning that the execution will stop afterwards. Therefore, when you run begin/0, initialize/0 will never run.
To fix it you need to add a base case for loop_through_list/0:
loop_through_list([]).
loop_through_list([Head|Tail]) :-
write(Head),
write(' '),
loop_through_list(Tail).
As a side note, "print_list" would be a more descriptive name for loop_through_list/0

Resources