Scheme check if and bigger than - scheme

I've just gotten started with a scheme course, and I need to make the rules listed below. From what I can tell the syntax I've used seems to be correct, but for some reason both rules only return false. Is there anything I'm doing wrong?
% state(country, name).
state(unitedstates, arizona).
state(unitedstates, california).
state(unitedstates, newmexico).
state(unitedstates, texas).
state(unitedstates, louisiana).
state(unitedstates, oklahoma).
state(unitedstates, colorado).
state(unitedstates, utah).
state(unitedstates, nevada).
state(mexico, chihuahua).
state(mexico, sonora).
state(mexico, coahuila).
state(mexico, durango).
state(mexico, veracruz).
state(mexico, bajacalifornia).
%stateinfo(Name, Population, Area-sq-mi)
stateinfo(chihuahua, 3400000, 96000).
stateinfo(sonora, 2700000, 69000).
stateinfo(coahuila, 2700000, 58000).
stateinfo(california, 34000000, 163000).
stateinfo(texas, 21000000, 269000).
stateinfo(arizona, 5000000, 111990).
% isState/1 – The parameter is a state in any country
isState(name) :- state(_, name).
% biggerstate/2 – The first parameter is a state with a greater area than the second.
biggerstate(Name1, Name2) :-
stateinfo(Name1, _, Area-sq-mi1),
stateinfo(Name2, _, Area-sq-mi2),
Area-sq-mi2 < Area-sq-mi1.
I've taken another piece of code that works, and made sure the syntax of my rules matches, but it still gives only false.

Related

I wrote a prolog code for my family tree. What's the problem with this code?

/*facts*/
female(Sufia).
female(Bilkis).
female(Nasima).
female(Rabeya).
female(NWife).
female(Eva).
female(Rekha).
female(Shammi).
female(Shanta).
female(TWife).
female(NSWife).
female(Jui).
female(SHWife).
female(TSWife).
male(Anowar).
male(Shahidul).
male(Khazal).
male(Shafik).
male(Nahid).
male(Jahorul).
male(Naim).
male(Tanim).
male(Raiyan).
male(NSon).
male(JHusband).
male(Jubayer).
male(Shoddo).
male(TSon).
male(NSSon).
male(JSon).
male(SHSon).
male(TSSon).
parent(Anowar,Shahidul).
parent(Anowar,Nasima).
parent(Anowar,Shafik).
parent(Shahidul,Nahid).
parent(Shahidul,Eva).
parent(Nasima,Rekha).
parent(Nasima,Shammi).
parent(Nasima,Shanta).
parent(Shafik,Tanim).
parent(Shafik,Raiyan).
parent(Nahid,NSon).
parent(Rekha,Jui).
parent(Rekha,Jubayer).
parent(Shammi,Shoddo).
parent(Tanim,TSon).
parent(NSon,NSSon).
parent(Jui,JSon).
parent(Shoddo,SHSon).
parent(TSon,TSSon).
/*rules*/
mother(X,Y):-parent(X,Y),female(X).
father(X,Y):-parent(X,Y),male(X).
son(X,Y):-parent(X,Y),male(X).
daughter(X,Y) :- female(X),parent(X,Y).
sister(X,Y) :- female(Y),parent(Par,X),parent(Par,Y), X \= Y.
child(X, Y) :-parent(Y, X).
sibling(X,Y):-parent(Z,X),parent(Z,Y),X\=Y.
grandparent(X,Z):-parent(X,Y),parent(Y,Z).
firstCousin(X,Y):-grandparent(Z,X),grandparent(Z,Y),X\=Y.
secondCousin(X,Y):-grandparent(A,X),grandparent(B,Y),sibling(A,B),A\=B.
firstcousinOnceRemoved(X,Y):-child(X,Z),cousin(Z,Y).
firstcousinTwiceRemoved(X,Y):-grandparent(X,Z),cousin(Z,Y).
You need to quote every name, otherwise these symbols are variables, not atoms.
Otherwise, just lowercase the first letter. To illustrate this last option, using my pet project, here is the graph:
as obtained from this source
:- module(answer_so, [answer_so/0]).
:- use_module(genealogy).
answer_so :- genealogy(answer_so, 'Answer SO').
parent_child(P,C) :- parent(P,C).
female(sufia).
female(bilkis).
female(nasima).
female(rabeya).
female(nwife).
female(eva).
female(rekha).
female(shammi).
female(shanta).
female(twife).
female(nswife).
female(jui).
female(shwife).
female(tswife).
male(anowar).
male(shahidul).
male(khazal).
male(shafik).
male(nahid).
male(jahorul).
male(naim).
male(tanim).
male(raiyan).
male(nson).
male(jhusband).
male(jubayer).
male(shoddo).
male(tson).
male(nsson).
male(json).
male(shson).
male(tsson).
parent(anowar,shahidul).
parent(anowar,nasima).
parent(anowar,shafik).
parent(shahidul,nahid).
parent(shahidul,eva).
parent(nasima,rekha).
parent(nasima,shammi).
parent(nasima,shanta).
parent(shafik,tanim).
parent(shafik,raiyan).
parent(nahid,nson).
parent(rekha,jui).
parent(rekha,jubayer).
parent(shammi,shoddo).
parent(tanim,tson).
parent(nson,nsson).
parent(jui,json).
parent(shoddo,shson).
parent(tson,tsson).
Seems there are no marriages...

Prolog output message understanding

This is a really quick one, I don't know the correct way to google it!
Say we have an output such it gives:
X = [4|_1218]
what generally has to be changed to get the output just to say 4?
member1(Head, [Head|_]):-!.
member1(Item, [_|Tail]):-
member1(Item, Tail).
findnotin([Head|_], RuledOut, [Head|_]):-
not(member1(Head, RuledOut)).
Edit Completedish program:
find_not_in([], _, _).
find_not_in([Head|Candidates], RuleOut, [Head|Legal]):-
not(member1(Head, RuleOut)),
find_not_in(Candidates, RuleOut, Legal).
find_not_in([_|Candidates], RuleOut, Legal):-
find_not_in(Candidates, RuleOut, Legal).

SWI-prolog same generation

I have some facts and rules that I'm trying to use that when I pass a query it says if the two variables are of the same generation (either siblings or cousins).
%mother/father DB
mother(lisa, abe).
mother(lisa, sarah).
mother(nancy, john).
mother(mary, jill).
mother(sarah, susan).
mother(susan, jack).
mother(susan, phil).
father(tony, abe).
father(tony, sarah).
father(abe, john).
father(john, jill).
father(bill, susan).
father(rob, jack).
father(rob, phil).
father(jack, jim).
%Parent rule
parent(X,Y):-mother(X,Y).%Defines the parent rule
parent(X,Y):-father(X,Y).
%sibling rule true if X,Y share same parent
sibling(X,Y):-father(Z,X),father(Z,Y),
mother(M,X),mother(M,Y).
cousin(X,Y):-parent(P,X),parent(Q,Y),sibling(P,Q).
%returns true if X is an ancestor of Y
ancestor(X,Y):-parent(X,Y);parent(X,Z),ancestor(Z,Y).
same_generation(X,Y):-ancestor(Z,X),ancestor(A,Y),sibling(Z,A).
Unfortunately the problem I'm getting is that when I test the query for a child and parent ex.same_generation(Jack,Susan), I get true (that is incorrect)!
Any help would be great!
Here is the family tree:
enter image description here

Prolog - fail; true

I have some problem with my code here.
Let's say I have a knowledge base like this:
university('University of Cambridge', 1, 'United Kingdom', 90.3, 92.8, 89.4).
university('University of Oxford', 2, 'United Kingdom', 88.9, 94.8, 88.0).
university('ETH Zurich - Swiss Federal Institute of Technology', 3, 'Switzerland', 86.4, 94.4, 92.2).
university('University of Edinburgh', 4, 'United Kingdom', 83.7, 88.8, 83.6).
Then I call it out like this:
(Ignore the checkC(Country)/checkC(_))
checkC(Country):-
university(U, R, Country, _, _, _),nl,
write('University: '),write(U),nl,
write('Rank: '),write(R),nl,
write('Country: '),write(Country),nl,
fail; true, nl,
write('************'), nl,nl.
checkC(_):-
write('Country not found'),nl,nl.
My question is, why is it if the user inputs a random country name not within the knowledge base, the write('Country not found') won't come out, I found out that it has something to do with the fail; true.
Any help?
While the fail; true trick is nice for the command line, gathering multiple solutions is usually done via the predicates findall, bagof and setof.
I used format for readabilities sake.
checkC(X):-
findall( [U,R,X], university(U,R,X,_,_,_), List),
(List = [] ->
write('Country not found\n\n');
writeCountries(List)).
writeCountries([]).
writeCountries([X|R]):-
writeCountries(R),
format('University: ~w~nRank: ~w~nCountry: ~w~n~n',X).
If you are using swipl, maplist comes in handy:
checkC(X):-
findall( [U,R,X], university(U,R,X,_,_,_), List),
(List = [] ->
write('Country not found\n\n');
maplist(format('University: ~w~nRank: ~w~nCountry: ~w~n~n'),List)).
If you don't have format/2 look if you have writef/2 or printf/2.

Prolog Query Exercise - Beginner

I'm a begginer at Prolog and I need some help with this exercise, this is the knowledge base provided:
album(‘R. Stevie Moore’, ‘Manuscription’).
album(‘Lane Steinberg’, ‘Manuscription’).
album(‘R. Stevie Moore’, ‘The Yung & Moore Show’).
album(‘Yukio Yung’, ‘The Yung & Moore Show’).
album(‘Jessie Evans’, ‘Autonervous’).
album(‘Bettina Koster’, ‘Autonervous’).
album(‘Lucia Pamela’, ‘Walkin on the moon’).
album(‘Shooby Taylor’, ‘The Human Horn’).
album(‘Tiny Tim’, ‘God Bless Tiny Tim’).
album(‘The Legendary Stardust Cowboy’, ‘Rock-It to Stardom’).
vinil(‘Rock-It to Stardom’).
vinil(‘Walking on the Moon’).
cd( ‘God Bless Tiny Tim’).
cd(‘Walking on the Moon’).
cd(‘Autonervous’).
cd(‘Manuscription’).
cassette(‘The Human Horn’).
cassette(‘The Yung & Moore Show’).
mp3(‘Walkin on the Moon’).
I need to make a query that will return to me all the albums that were made by only one musician.
Thanks for your help :)
In the comments you have provided your code album(X,B),album(Y,C), B \= C. Actually, this is not too far away from a correct solution.
A correct solution could be:
one_musician_album(X) :-
album(A, X),
\+ (album(B, X), A \= B).
The meaning of the predicate is: an album X is a "one-musician album" if this album is authored by some musician A and it's not possible to find a different musician B authored the album X.
Test run:
?- one_musician_album(X).
X = 'Walkin on the moon' ;
X = 'The Human Horn' ;
X = 'God Bless Tiny Tim' ;
X = 'Rock-It to Stardom'.
To get all answers you have to type ';' after each answer.
Maybe this is not needed for you, but it's possible to get all answers in a list with findall:
?- findall(X, one_musician_album(X), Albums).
Albums = ['Walkin on the moon', 'The Human Horn', 'God Bless Tiny Tim', 'Rock-It to Stardom'].
Here is a generalization, based on 'all solutions' builtin bagof/3.
Note that
?- bagof(A, album(A,T), As).
T = 'Autonervous',
As = ['Jessie Evans', 'Bettina Koster'] ;
T = 'God Bless Tiny Tim',
As = ['Tiny Tim']
....
then, restricting the authors (As) to be a list of a single element, we get albums with a single author
?- bagof(A, album(A,T), [A]).
A = 'Tiny Tim',
T = 'God Bless Tiny Tim' ;
...
then, we could use findall/3, as in the good answer by Sergey, or, again, bagof/3, with explicit quantification:
?- bagof(T, A^bagof(A, album(A, T), [A]), Ts).
Ts = ['God Bless Tiny Tim', 'Rock-It to Stardom', 'The Human Horn', 'Walkin on the moon'].

Resources