How do i count words in prolog? - 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???

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 to print variable value from a question?

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?

Concatenate two atoms in prolog without using atom_concat

I want to write prolog that can essentially do what this is doing
atom_concat('3',' =',Answer).
Answer = '3 ='.
But I do not want to use the atom_concat function (or any built in predicates). I would also like the answer to have no quotation marks in it.
I have tried implementing a method that operates the same as the append method, which I have called merge.
merge([],Xs,Xs).
merge([X|Xs],Ys,[X|Zs]):-
merge(Xs,Ys,Zs).
But when I write this into my db.pl file I get false when running it.
?- [db].
true.
?- merge('3',' =',Answer).
false.
You can't mutate immutable values. You could use string_concat/3 to create a merger of two string atoms. By putting 'Variable' you are signalling Prolog that you want an ATOM called Variable. So numerical 3 and string atom '3' are not the same. What basically happens is you have two >immutables<, so a third has to be made that is an amalgamation of the other two.
atom_concat
string_concat
'merge' is also a deprecated method, just to clear up any confusion:
merge
The program you want:
The query
?- trace, (concat_strings(['Hello ','Hello ','Hello '],[world1,world2,world3],Output)).
The code
concat_strings([H1|T1],[H2|T2],[H3|T3]) :-
string_concat(H1, H2, H3),
concat_strings(T1,T2,T3).
concat_strings([],[],[]).
It takes the the first word of both lists, makes a new immutable atom from the 2 through string_concat and puts it in H3, which is then put onto the head of the list when the call ends. We have the end condition concat_strings([],[],[]) and the first 2 are the lists YOU pass, the third means T3 eventually unifies as T3 = [], which is also the atom to show Prolog the end of a list has been reached. Prolog then starts stepping back, adds [] as the tail and then adds the new atoms to the new list as it works its way back to your call.
OPINION:
My favorite resource for Prolog basics explained: http://www.learnprolognow.org/lpnpage.php?pageid=top
built_equality_structure(Id,Value,Id = Value).
If you call it with
?- built_equality_structure(a,3,X).
you will get the result
X = (a=3)
where the Prolog system only add parentheses for readability.

persian language processing prolog

This is my prolog code, which gave me the following error:
ERROR: Out of global stack
hasA(S,A):- name(S,L1),
compar(L1,A).
compar([H1,H2|T1],T1):- H1 == 1575, H2 == 1740.
neda(H,A):- hasA(H,Z1),
append(A,[1575,1740],A),
state(Z1,Z2),
append(A,Z2,A).
state([H|T],T):- H == 32.
state(A,A).
What is wrong? Can you help me with it?
Assuming that you call neda(H,A) with A being a free variable you end up calling append(A,[1575,1740],A) with A being a free variable as well. However, traditionally, append is implemented as
append([],Ys,Ys).
append([X|Xs],Ys,[X|Zs]) :- append(Xs,Ys,Zs).
Unification of append(A,[1575,1740],A) with append([],Ys,Ys) fails since it requires A to be [], on the one hand, and [1575,1740], on the other hand. Hence, Prolog tries to unify append(A,[1575,1740],A) with append([X|Xs],Ys,[X|Zs]) and succeeds with {A/[X|Xs], Ys/[1575,1740], Xs/Zs} which leads to the call append(Xs,[1575,1740],Xs) and the process repeats, i.e., Prolog enters an infinite recursion and ultimately runs out of stack.
If I guess your intention correctly, you first would like to append [1575,1740] to A and then to append Z2. This would mean that you need to introduce two new variables, say A1 and A2, to record the state of A after each appending step:
neda(H,A):- hasA(H,Z1),
append(A,[1575,1740],A1),
state(Z1,Z2),
append(A1,Z2,A2).
Beware, however, that with A being a free variable on backtracking this code will generate lists of increasing length; is this what you want?

Prolog replace element in a list with another list

*Hi, i am trying to replace an element from a list with another list and im stuck when turbo prolog gives me syntax error at the case where if C=A-> put in result list(L1) the list that replace the element.
domains
list=integer*
element=i(integer);l(list)
lista=element*
predicates
repl(list,integer,list,lista)
clauses
repl([],A,B,[]):-!.
repl([C|L],A,B,**[l(|L1])**:- C=A,repl(L,A,B,L1),!.
repl([C|L],A,B,[i(C)|L1]):- repl(L,A,B,L1),!.
Thanks for help, problem solved (using dasblinkenlight code)
Try this:
concat([],L,L).
concat([H|T],L,[H|Res]) :- concat(T,L,Res).
repl([],_,_,[]).
repl([Val|T],Val,Repl,Res) :- repl(T,Val,Repl,Temp), concat(Repl,Temp,Res).
repl([H|T],Val,Repl,[H|Res]) :- repl(T,Val,Repl,Res).
I do not know if it is going to work in Turbo Prolog, but it works fine in SWI, and it does not use any built-in predicates.
concat/3 pair of rules concatenates lists in positions 1 and 2 into a resultant list in position 3.
The first repl deals with the empty list coming in; it is identical to yours, except it replaces singleton variables with underscores (a highly recommended practice)
The second rule deals with the situation where the value Val being replaced is at the head of the list; it replaces the values in the tail, and concatenates the replacement list Repl with the result of the replacement Res.
The last rule deals with the situation when the head value does not match the Val. It recurses down one level, and prepends the head of the initial list to the head of the result of the replacement.
As a side note, the cut operator ! is rarely necessary. In case of this problem, you can definitely do without it.

Resources