Splitting atoms with pipe symbols - prolog

I have a list of lists of this structure in GNU-Prolog:
[[1|5], [1|6], [2|6], [3|6]]
What might be the best way to extract the numbers in each sublist separately? I can't unify each term because of the pipe, unless there is something I am missing. Any help would be great; I'm very new to Prolog and haven't found much online for this issue

Then I tryed this in console (SWI).
Does this help?
?- [1|2]=..A.
A = ['[|]', 1, 2].
?- [1|2]='[|]'(A,B).
A = 1,
B = 2.
I mean matching like
[1|2]='[|]'(A,B).
will succeed.

Typically righthand side of the | operator should be a list(including empty list []).
You should write like :
[[1|[5]], [1|[6]], [2|[6]], [3|[6]]]
or simply
[[1,5],[1,6],[2,6],[3,6]]

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?

Array Univ var ([x,y]=..T) - prolog

I saw a question asking what does [a,b,c]=..L. return.
When testing this I saw that it returns: L = ['.', a, [b, c]].
I can't understand why this happens, I was unable to understand the nature of Univ from the documentation. Understanding this will help me understand Univ.
One way to learn more about terms is to use write_canonical/1 in a conforming Prolog system.
For example, with GNU Prolog, we obtain:
| ?- write_canonical([x,y]).
'.'(x,'.'(y,[]))
This shows:
the primary functor in this term is '.', with arity 2
the first argument is x
the second argument is '.'(y, []), which is the list [y]
This explains why (=..)/2 yields:
| ?- [x,y] =.. Ls.
Ls = ['.',x,[y]]
and also your other example.
This happends because representation of the list in prolog is a tree datastructure,like this.It's top node is a "dot" left side is Head then again a dot on right if tail is not empty and head on left hand side and "dot" on right handside. When you do this you are simply creating a predicate(well , not exact a predicate but it is sometimes needed as i show an example): suppose i write:
V=..[somefunctor,X,Y,Z]
Then it will automatically construct a predicate like this:
somefunctor(X,Y,Z).
Now Why do we need this? Supppose i call a predicate with these terms: predicate(somefunctor,term,term2,term3) and predicate or rule looks something like this: predicate(X,Y,Z,T) and i ask you that no matter what predicate is in X, you have to call this predicate with parameters Y,Z,T. May be you think you call that predicate by writing like this: X(Y,Z,T) but unfortunately it is not allowed in prolog, so here you can use V=..[X,Y,Z,T] where X should be placed as first argument because it's predicate name and as a result you get something like this: V = somefunctor(term,term2,term3) and this happends internally. In order to invoke this predicate you make use of call predicate:
call(V) where `call/1` is a metapredicate and `V=..` is a not logical predicate.

How do you save all possible solutions in SWI-Prolog?

I have this predicate that has about a thousand possibilities and I need all possibilities as an output. It is not possible to simply copy and paste all listed possibilities in SWI-Prolog on Windows since you can only scroll up so much.
My predicate looks like this:
?- question(X,Y,Z).
X = 'Fo',
Y = 'Ob',
Z = 'Ar' ;
X = 'Fo2',
etc...
I was wondering if there was a way to save the result in a file or something?
Use findall/3:
findall([X,Y,Z],question(X,Y,Z),R).
R shall be bound to the list of all [X,Y,Z] such that question(X,Y,Z) succeeds.
For more information see: Documentatin on Findall
You can use something like this:
main :-
tell('output.txt'),
(
question(X,Y,Z),
writeln([X, Y, Z]),
fail
;
told
).
Or you can run the query ( question(X,Y,Z), writeln([X, Y, Z]), fail ; true ). in Prolog and get all solutions at standard output (screen).
SWI-Prolog offers a way to save the interaction carried on the REPL (Read,Eval,Print,Loop) console: see the protocol builtins. This way variables names are retained. Beware, the output could be difficult to process, and long variables will be replaced by ellipsis (you can change this, see these answers).
Otherwise, forall/2 could be a viable alternative
?- open('a.txt',write,S), forall(member(X,[martin,carlo]), format(S,'~q~n',[X])), close(S).

Error in PROLOG code

I am new to prolog.
I want my code in PROLOG to produce the expected output given below. Can some one please tell me where I am going wrong.
The code is basically to remove duplicates and produce o/p in required format.
remove_dups([],_L2,_L2).
remove_dups([A|B],L2,L3) :-
functor(A,Pr,Ar),(member(level(Pr,Ar,1) ,L2) -> remove_dups(B,L2,L2); append([level(Pr,Ar,1)],L2,L3),remove_dups(B,L3,L3)).
expected output:
?- remove_dups([a,b,a],[],L).
L = [level(a,0,1),level(b,0,1)].
For starters I would have preferred to separate the two steps: removal of duplicates and presentation of the levels.
remove_dups([],[]).
remove_dups([X|Xs],Ys) :- member(X,Xs), !, remove_dups(Xs,Ys).
remove_dups([X|Xs],[X|Ys]) :- remove_dups(Xs,Ys).
levels([],[]).
levels([X|Xs],[level(N,A,1)|Ys]):- functor(X,N,A), levels(Xs,Ys).
go(L,R):- remove_dups(L,RL), levels(RL,R).
I have to admit that the constant 1 in the level tripples puzzles me. Are you sure that it should not be somehow more meaningful?
I have also assumed that the order of the list elements is of no importance: remove_dups removes all occurrences of a duplicated element except for the last one. If you would like to keep the first occurrence, remove_dups has to be modified.

Resources