Why cant i get the answer to the zebra puzzle in prolog? - prolog
this is my code currently, I am trying to solve the zebra puzzle.
exists(A,(A,_,_,_,_)).
exists(A,(_,A,_,_,_)).
exists(A,(_,_,A,_,_)).
exists(A,(_,_,_,A,_)).
exists(A,(_,_,_,_,A)).
rightOf(A,B,(B,A,_,_,_)).
rightOf(A,B,(_,B,A,_,_)).
rightOf(A,B,(_,_,B,A,_)).
rightOf(A,B,(_,_,_,B,A)).
middleHouse(A,(_,_,A,_,_)).
firstHouse(A,(A,_,_,_,_)).
nextTo(A,B,(B,A,_,_,_)).
nextTo(A,B,(_,B,A,_,_)).
nextTo(A,B,(_,_,B,A,_)).
nextTo(A,B,(_,_,_,B,A)).
nextTo(A,B,(A,B,_,_,_)).
nextTo(A,B,(_,A,B,_,_)).
nextTo(A,B,(_,_,A,B,_)).
nextTo(A,B,(_,_,_,A,B)).
:- Houses = (house(N1,P1,S1,D1,C1),house(N2,P2,S2,D2,C2),house(N3,P3,S3,D3,C3),house(N4,P4,S4,D4,C4),house(N5,P5,S5,D5,C5)),
exists(house(english,_,_,_,red),Houses),
exists(house(spainish,dog,_,_,_),Houses),
exists(house(_,_,_,coffee,green),Houses),
exists(house(ukrainian,_,_,tea,_),Houses),
rightOf(house(_,_,_,_,green),house(_,_,_,_,ivory),Houses),
exists(house(_,dog,oldgold,_,_),Houses),
exists(house(_,_,kools,_,yellow),Houses),
middleHouse(house(_,_,_,milk,_),Houses),
firstHouse(house(norwegian,_,_,_,_),Houses),
nextTo(house(_,_,chesterfields,_,_),house(_,fox,_,_,_),Houses),
nextTo(house(_,_,kools,_,_),house(_,horse,_,_,_),Houses),
exists(house(_,_,luckystike,orangejuice,_),Houses),
exists(house(japanise,_,parliments,_,_),Houses),
nextTo(house(norwegian,_,_,_,_),house(_,_,_,_,blue),Houses),
exists(house(WaterDrinker,_,_,water,_),Houses),
exists(house(ZebraOwner,zebra,_,_,_),Houses).
I have typed this up and saved it as zebra.pl, this I open it and enter [zebra] into SWI-prolog, it returns a warning message about the singleton use of N1,P1,C1 etc.. and returns true, then i ask it to print water drinker using print(WaterDrinker) and it returns _G317 and true,
why is it doing this and not returning the answer which could be norwegian, it does the same if i ask it return any variable like C3 or ZebraOwner
The main problem is that you cannot write a goal like :- Houses = ... in the middle of your program. Rather, you should write something like
solution(WaterDrinker, ZebraOwner) :-
Houses = ...
and then after the program has been loaded type
solution(W, Z).
at the -? prompt to compute the solution.
You also don't specify that all the values should be distinct. If you do that you will use the variables a second time and the warning will go away.
If you really need a variable only once you can prepend it with an underscore to make the warning go away. Or you can just use an underscore, like you already did many times.
Related
Return values from database - Prolog
Good morning, I'm learning prolog. But I already searched, but I didn't find a solution, it must be very simple, but I got stuck I created a database like the following data base([ movie(["Titanic"], [["Jack", "Dawson"] ,["Rose", "DeWitt", "Bukater"]], ["James","Cameron"] ), movie(["Hulk"], [["Bruce", "Banner"] ,["Betty", "Ross"]], ["Ang","Lee"] ) ]). This database contains the name of the film, the name of the main characters and then the director. The goal would be to create a function: Example find_movies_by_character("Bruce Banner") Need return Titanic I imagine something might be wrong, I'm open to new ideas
data base([ with that space in it, doesn't seem to be valid syntax in SWI Prolog. Wherever did you get that from? This database contains the name of the film, the name of the main characters and then the director. More specifically, the database contains a list containing movie terms, each containing a list containing the name of the film and (a list containing lists of parts of names of the main characters) and (a list containing parts of names of directors). From how complicated it is to write out, it will be at least that complicated to work with. If you can simplify it, it will get easier to work with: movie('Titanic', ['Jack Dawson', 'Rose DeWitt Bukater'], 'James Cameron'). movie('Hulk', ['Bruce Banner', 'Betty Ross'], 'Ang Lee'). find_movie_by_character(Character, MovieName) :- movie(MovieName, Characters, _), member(Character, Characters). e.g. ?- find_movie_by_character('Bruce Banner', X). X = 'Hulk'
A "display" that always displays in prolog
I have a predicate check(Data,Res) that checksDats according to some rules and returns Res (a function result on Data, assuming Data answers to several criteria). I have another function generate(N,Data) which generates a N-size Data. My main program begins with generating many 1-size Data, then if none answered the criteria, we go on to 2-size Data and so on until we reach a certain M upper limit. main(M):- next_number(N,M), generate(N,Data), check(Data,Res). However, the program runs for very long time. I wanted to make sure it does not get stuck. For this, I wanted to print the generated Data each time before its being checked. But adding display did not assist, because it only actually displayed if the entire statement was true. That's not what I want. I want to keep track of the progran using display, similarly to System.out.println in Java. Is there any other function that displays anyway? Or an idea how to use display in a way that will always display, regardless if the Data answered the criteria or not? I thought to do: (check(Data,Res) -> display(Data);display(Data)). But I am not sure. Any ideas?
Your long process is likely to be within check - or more precisely, that check fails for most data, causing the system to backtrack repeatedly. If you display a result in check, you'll have line upon line of tracing. Instead, you could add a write statement to generate, or even to your number generation: main(M):- next_number_and_tick(N,M), generate(N,Data), check(Data,Res). next_number_and_tick(N,M) :- next_number(N,M), write('Tick - now doing '), writeln(N). Upon backtracking, the program will signal the data size it is now working on, giving you an idea of the volume of work it is doing.
The problem in the way you use display is that the entire statement must be true for it to display. Your idea of using "if-then" is good but not accurate. If you want to use it, you should "trick" prolog the following way: new_check(Data,Res) :- (check(Data,Res) -> display('Victory!'),!; display('Failed Data: '), display(Data), nl, fail). This way, if the check fails, you will get a report on which Data failed, and if it succeeded everything stops (assuming you want only 1 solution. If you want more, remoce the ! predicate).
How to extend prolog driver and determine number of columns and rows by reading an eps file
Good day! I would like to ask for help in understanding Prolog code as well as learning how to extend its functionality. Based on my limited yet newbie knowledge of programming, the function of the first given code (is quite like a main file), everything originates from it and thus it is the first file that is run before calling any other function. main.pl printSequences([]). printSequences([Sequence|Sequences]):- writeln(Sequence), printSequences(Sequences). loadHelpers:- ['helpers'], ['part01'], ['part02'], ['part03'], ['part04']. part01:- readExtremePegSolitaireFile('test04.eps',_,Game), printGame(Game), columnsAndRows(Game). part02:- readExtremePegSolitaireFile('part01test01.eps',_,Game), printGame(Game), openSpaces(Game). part03:- readExtremePegSolitaireFile('test04.single.eps',_,Game), printGame(Game), setof(Moves,fewestMoves(Game,Moves),AllMoves), writeln(moves), printSequences(AllMoves). part04:- readExtremePegSolitaireFile('test04.eps',_,Game), printGame(Game), noIslands(Game). I don't think I have any problems understanding the first given code above, but my problem is mostly with this second given code and how to go about manipulating other files. I can't seem to understand the prefix part (is this the definition of a list of lists?) Also am I correct that most of the other functions are declared in this helper file to make the code more organized? helpers.pl :- module( helpers, [ readExtremePegSolitaireFile/3 , printGame/1 ] ). prefix([H],[]). prefix([H|T],[H|PreT]):- prefix(T,PreT). readExtremePegSolitaireFile(File,Moves,Game):- open(File,read,Input), read(Input,Moves), readGame(Input,Temp), prefix(Temp,Game), close(Input). readGame(Input,[]):- at_end_of_stream(Input), !. readGame(Input,[Row|Rows]):- \+ at_end_of_stream(Input), read(Input,Row), readGame(Input,Rows). printGame(Game):- writeln(game), printRows(Game). printRows([]). printRows([Row|Rows]):- writeln(Row), printRows(Rows). Last is a peg solitaire board that is given with the first line being the list of moves performed and the following lines are the board declarations (1,2,3,4 - players, x - peg, and '-' as empty spaces) test04.eps [r,d,u,r,l,l,l,d,l,u,r,r]. [2,-,x,x,x,x,x]. [x,x,-,x,-,x,x]. [x,3,x,-,x,-,x]. [x,-,4,x,x,x,x]. [x,x,-,x,x,-,x]. [x,x,x,1,-,x,x]. [x,x,x,x,x,x,x]. I would like to know how one would be able to calculate the number of columns and rows via a query columnsAndRows(Game). My first plan of action was to use something like this: (Which would be able to calculate the length of the rows by counting each element in the list however, it seems to have calculated all the elements in the list. 2 things that I noticed was: It didn't stop at the end of the row Apparently it didn't print the entire board, it was missing the last line of the board! columnsAndRows(Game) :- flatten(Game, FlatList), length(FlatList,FlatListSize), writeln(FlatListSize). ?- [a04tests]. ?- loadHelpers. ?- part01. game [2,-,x,x,x,x,x] [x,x,-,x,-,x,x] [x,3,x,-,x,-,x] [x,-,4,x,x,x,x] [x,x,-,x,x,-,x] [x,x,x,1,-,x,x] 42 true I'm honestly really lost and I'd appreciate any guidance as to where to begin, or even a process flow for this program. Many thanks!
SWI-Prolog: how to insert a new clause to a database
I'm sorry, this has probably been asked before but I can't find a good answer. I'm writing a Prolog assignment, in which we must write a database with insert, delete, etc. I'm currently stuck on the insert part. I'm trying to use tell, listing and told for this, but the results are often unpredictable, deleting random parts of the file. Here's the full code of my database, banco.pl: :- dynamic progenitor/2. progenitor(maria,joao). progenitor(jose,joao). progenitor(maria,ana). progenitor(jose,ana). insere(X,Y) :- dynamic progenitor/2, assert(progenitor(X,Y)). tell('banco.pl'), listing(progenitor), told. I then run the following on SWI-Prolog: insere(luiz,luiza). And get the following result on banco.pl: :- dynamic progenitor/2. progenitor(maria, joao). progenitor(jose, joao). progenitor(maria, ana). progenitor(jose, ana). Note that the clause I tried to insert isn't even in the file, and the lines defining commit and insere are missing. How would I do this correctly?
tell starts writing to the beginning of the file. so you're overwriting everything else that was in the file. you have these options: put your progenitor predicate (and just that) in another file. use append/1 to write to the end of the file with portray_clause. this only helps for insert, but you stated that you want delete too. read the other clauses into a list and reprint them, then use listing/1 : (text for formatting) read_all_other_clauses(All_Other_Clauses):- see('yourfilename.pl'), read_all_other_clauses_(All_Other_Clauses,[]), seen. read_all_other_clauses_(Other,Acc0):- (read(Clause) -> (Clause = progenitor(_,_) -> % omit those clauses, because they'll be printed with listing/1 read_all_other_clauses_(Other,Acc0); read_all_other_clauses_(Other,[Clause|Acc0])); Other = Acc0). % read failed, we're done operation(Insert, X,Y):- (call,(Insert) -> assert(progenitor(X,y)); retract(progenitor(X,y))), read_all_other_clauses(Others), tell('yourfilename.pl'), % After the reading! maplist(portray_clause,Others), %Maplist is a SWI built-in, easy to rewrite, if you don't have it. listing(progenitor/2), told. insert(X,Y):- operation(true,X,Y). delete(X,Y):- operation(fail,X,Y). Note that you could use the read_all_other_clauses for your delete only, if you change the line with the omit comment. Then you could use the solution proposed in #2 for your insere
Prolog - call a rule with fact
TL;DR: Need help calling a rule with a fact I´ve started out with Prolog, coming from C and got stuff working... until they evidently got broken. I´m writing a small car-paint program for myself as I´m learning this new language I'm trying to call a rule with a fact (is this possible?), what I want to do is use one fact "cars" and another fact "paint" to make one big list consisting of all the cars in all the different paints. I'm having trouble making the code work as I want...have a look I´ve got the facts: cars([ferrari, bmw, ford, jaguar]). paints([red, white, blue, yellow]). /*Now I wanted to loop through each car, eachtime printing out the different paint combinations of that car: */ start:- loop_cars(cars(C)). /*starts loop_cars with all the cars e.g [ferrari...]*/ /*but it false here, even if C = [ferrari...]*/ loop_cars([]). loop_cars([Ca|Rest]):- loop_paints(Ca,paints(P)), /*The car is sent off for a paint job,...*/ loop_cars(Rest). /*...(cont from above) same false here as before*/ loop_paints(_,[]). loop_paints(Ca,[Pa|Rest]):- /*This works*/ write([Ca,Pa]), /*Writes it like "[ferrari, white] [ferrari, blue] ..."*/ loop_paints(Ca,Rest). So I guess I need help solving two problems: How do i pass the contents of the facts cars and paints to the two loops? A "garage" to put all the combinations in. Garage being a big list consisting of small 2-items-lists (the car and paint).
You can do it like this: start :- cars(C), loop_cars(C). First, “assign” (I think it's called “unify” in Prolog terminology) the list of cars to the variable C and then call loop_cars for this list. Similarly with paints. If you want to store the result in a variable, you have to add an “output” parametr to your predicates: loop_paints(_,[],[]). loop_paints(Ca,[Pa|Rest],[Res|ResRest]):- Res = [Ca,Pa], loop_paints(Ca,Rest,ResRest).