How to print variable value from a question? - prolog

I´m making a one bit addition:
sumbit(CIN,A,B,CO,R):- ...
?- sumbit(0
,1
,1
,CO
,R)
,write(CIN),nl
,write(A),nl
,write("+"),nl
,write(B),nl
,write("--"),nl
,write(CO),write(R),nl.
What I want to do is to print the variable values of CIN,A,B,CO and R.
It should come out something like this:
0
1
+
1
--
10
Instead it comes out as this:
_40
_73
+
_149
--
10
Yes.
Also is there a way to not print the "Yes"?
I´m using strawberry prolog if it helps.
Thank you in advance

One way to achieve that without altering your predicate definition is to tweak the query, like so:
?- [CIN, A, B] = [0, 1, 1]
,sumbit(CIN
,A
,B
,CO
,R)
,write(CIN),nl
,write(A),nl
,write("+"),nl
,write(B),nl
,write("--"),nl
,write(CO),write(R),nl.
Now all variables are instantiated, either by the call itself, or prior to the call.
When a variable is not instantiated, there's no value to print, so its "name" is printed instead. But since non-used name has no meaning in itself, it can be freely renamed by the system to anything. In SWI Prolog:
1 ?- write(A).
_G1338
true.
The renaming is usually done, as part of the Prolog problem solving process, to ensure that any two separate invocations of the same predicate do not interfere with each other.
So where SWI Prolog uses names like _G1338, the Prolog implementation you're using evidently uses names with the numbers only, after the underscore, like _40.

I found an answer by putting the write() inside the sumbit(...) predicate:
sumbit(CIN,A,B,CO,R):-
xor_(A,B,R1)
,and(A,B,R2)
,xor_(R1,CIN,R)
,and(R1,CIN,R4)
,or(R2,R4,CO)
,write(CIN),nl
,write(A),nl
,write("+"),nl
,write(B),nl
,write("--"),nl
,write(R),nl.
There are still some unanswered questions though:
is there a way to not print the "Yes"?
what was the _number that came out before?

Related

Edit Prolog program to output the result of a computation

I've found something about this in other questions, but mine is a bit different.
Given a string, I have to output another string with no adjacent duplicates.
E.g., given [a,a,b,b,c,d,a], my output will be [a,b,c,d,a].
Now, I've wrote the following recursive program to check if a certain given string has adjacent duplicates:
notequal(A,[]).
notequal(A,[X|S]) :- not(A=X).
noadj([]):-!.
noadj([A|S]) :- notequal(A,S), noadj(S).
How would I modify it in order to output what I described? I've tried multiple times but I'm new to prolog and I can't seem to get into its logic.
Of course, I'll need another variable, which would contain an element if notequal is true for that element.
So my idea is to iterate through the list and only add a certain term to the result if it passes the "notequal" test.
I'll edit this: I finally managed to do something like that by adding
noadjlist([X|S],[X|LS]) :- notequal(X,S), noadjlist(S,LS).
noadjlist([X|S],LS) :- noadjlist(S,LS).
noadjlist([],LS):-!.
However, my results are like:
?- noadjlist([1,2,2,3],LS).
LS = [1, 2, 3|_19316] .
why do I get that uninstantiated variable at the end?
noadjlist([],LS):-!.
should be
noadjlist([],[]):-!.

How do i count words in prolog?

I try to count words in a string in prolog. Like "No, I am definitely not a pie!"
To give me the number 7 and next example "w0w such t3xt... to give number 5.
I had thougt about subtract that are a library function and only get back white-characters. But the problem then is No way will give back 5 and not two words.
I thought about
filter([],L).
filter([X,Y|XS],[Y|XS]):- X = ' ',Y = ' ',L = [Y|XS], filter([Y|XS],L).
filter([X|XS],L):- filter(Xs,L).
That will remove white spaces and get back No way but it dosent work anbody have a tip.
Strings in Prolog are lists of character codes not of atoms, what explains why tests like X=' ' fail. See what is the result of executing
write("ab cd"), nl.
in your Prolog system.
You have errors in your 3 clauses:
What to do you expect the first clause to return in the last argument?
L is, as any other variable in a Prolog program, a variable that is local to the clause it appears in, never a global variable.
The second clause unifies L with a list and you use it as second argument of the recursive call: do you expect the recursive call to change the value of L? This will never be the case: in Prolog there is no assignment of variables, changes are made by building terms and unifying them with new variables.
What happens to X in your third clause???

Prolog Relational Tracking without Lists

I am trying to get a predicate to relate from 1 fact to another fact and to keep going until a specified stopping point.
For example,
let's say I am doing a logistics record where I want to know who got a package from who, and where did they get it from until the end.
Prolog Code
mailRoom(m).
gotFrom(annie,brock).
gotFrom(brock,cara).
gotFrom(cara,daniel).
gotFrom(daniel,m).
gotFrom(X,Y) :- gotFrom(Y,_).
So what I am trying to do with the predicate gotFrom is for it to recursively go down the list from what ever point you start (ex: gotFrom(brock,Who)) and get to the end which is specified by m, which is the mail room.
Unfortunately when I run this predicate, it reads out,
Who = annie.
Who = brock.
Who = cara.
etc.etc....
I tried stepping through the whole thing but Im not sure where it goes from brock to annie, to cara and all the way down till it cycles through trues for infinity. I have a feeling that it has something to do with the wildcard in the function (_), but Im not sure how else I could express that part of the function in order for the predicate to search for the next fact in the program instead of skipping to the end.
I tried using a backcut (!) in my program but it gives me the same error.
Any help is greatly appreciated. I don't want code I just want to know what I am doing wrong so I can learn how to do it right.
Thanks.
I'm afraid this rule is meaningless:
gotFrom(X,Y) :- gotFrom(Y,_).
There is nothing here to constrain X or Y to any particular values. Also, the presence of singleton variable X and the anonymous variable _ means that basically anything will work. Try it:
?- gotFrom([1,2,3], dogbert).
true ;
true ;
What I think you're trying to establish here is some kind of transitive property. In that case, what you want is probably more like this:
gotFrom(X,Z) :- gotFrom(X, Y), gotFrom(Y, Z).
This produces an interesting result:
?- gotFrom(brock, Who).
Who = cara ;
Who = daniel ;
Who = m ;
ERROR: Out of local stack
The reason for the problem may not be immediately obvious. It's that there is unchecked recursion happening twice in that rule. We recursively unify gotFrom/2 and then we recursively unify it again. It would be better to break this into two predicates so that one of them can be used non-recursively.
got_directly_from(annie,brock).
got_directly_from(brock,cara).
got_directly_from(cara,daniel).
got_directly_from(daniel,m).
gotFrom(X,Y) :- got_directly_from(X, Y).
gotFrom(X,Z) :- got_directly_from(X, Y), gotFrom(Y, Z).
This gives us the desired behavior:
?- gotFrom(brock, Who).
Who = cara ;
Who = daniel ;
Who = m ;
false.
Notice this one is resilient to my attack of meaningless data:
?- gotFrom([1,2,3], dogbert).
false.
Some general advice:
Never ignore singleton variable warnings. They are almost always a bug.
Never introduce a cut when you don't understand what's going on. The cut should be used only where you understand the behavior first and you understand how the cut will affect it. Ideally, you should try to restrict yourself to green cuts—cuts that only affect performance and have no observable effects. If you don't understand what Prolog is up to, adding a red cut is just going to make your problems more complex.

Prolog anonymous variable

Here is what I have understood about Prolog variables.
A single underscore stands for anonymous variable, which is like a new variable each time it occurs.
A variable name starting with underscore like _W is not an anonymous variable. Or, the variable names generated inside Prolog, like _G189, is not considered anonymous:
?- append([1,2],X,Y).
X = _G189
Y = [1, 2|_G189]
Could you please help me understand?
By the way, I got the above example from some tutorials, but when I run it in SWI-Prolog version 6, I get the following:
?- append([1,2],X,Y).
Y = [1, 2|X].
Thanking you.
Variables
The anonymous variable _ is the only variable where different occurrences represent different variables. Other variables that start with _ are not anonymous. Different occurrences refer to the same variable (within the same scope). However, many Prologs like SWI will warn you should a variable not starting with an underscore occur only once:
?- [user].
a(V).
Warning: user://1:9:
Singleton variables: [V]
You have to rename that variable to _V to avoid that warning. This is a help for programmers to better spot typos in variable names. There are some more such restrictions in many systems.
a(_V,_V).
Warning: user://1:12:
Singleton-marked variables appearing more than once: [_V]
Again, this is only a warning. If you want that a variable starting with _ should occur twice (without warning), write __ instead. But better stick to more meaningful names without a starting _.
Answers
What you get from Prolog's top level loop are answers ; and in particular answer substitutions. They serve to represent solutions (that's what we are really interested in). There are several ways how answer substitutions may be represented. The tutorial you are using seems to refer to a very old version of SWI. I would say that this version is maybe 15 to 20 years old.
?- append([1,2],X,Y).
X = _G189
Y = [1, 2|_G189]
However, the answer given is not incorrect: A new auxiliary variable _G189 is introduced.
Newer versions of SWI and many other systems try to minimize the output, avoiding auxiliary variables. So
?- append([1,2],X,Y).
Y = [1, 2|X].
is just as fine. It is the answer of a "newer" version (also some 6 years old). Note that this answer tells you much more than the first one: Not only does it show you the answer substitution more compactly, but it also tells you that there is exactly this one answer (and no more). See the dot . at the end? This means: There is no more here to answer. Otherwise there would be a ; for the next answer.

Correct use of findall/3, especially the first template argument

i know there is a build-in function findall/3 in prolog,
and im trying to find the total numbers of hours(Thrs) and store them in a list, then sum the list up. but it doesnt work for me. here is my code:
totalLecHrs(LN,THrs) :-
lecturer(LN,LId),
findall(Thrs, lectureSegmentHrs(CC,LId,B,E,THrs),L),
sumList(L,Thrs).
could you tell me what's wrong with it? thanks a lot.
You need to use a "dummy" variable for Hours in the findall/3 subgoal. What you wrote uses THrs both as the return value for sumList/2 and as the variable to be listed in L by findall/3. Use X as the first argument of findall and in the corresponding subgoal lectureSegmentHrs/5 as the last argument.
It looks like the problem is that you're using the same variable (Thrs) twice for different things. However it's hard to tell as you've also used different capitalisation in different places. Change the findall line so that the initial variable has the same capitalisation in the lectureSegmentHrs call. Then use a different variable completely to get the final output value (ie the one that appears in sumList and in the return slot of the entire predicate).
You need to use a different variable because Prolog does not support variable reassignment. In a logical language, the notion of reassigning a variable is inherently impossible. Something like the following may seem sensible...
...
X = 10,
X = 11,
...
But you have to remember that , in Prolog is the conjunction operator. You're effectively telling Prolog to find a solution to your problem where X is both 10 and 11 at the same time. So it's obviously going to tell you that that can't be done.
Instead you have to just make up new variable names as you go along. Sometimes this does get a bit annoying but it's just goes with the territory of a logical languages.

Resources