Get all list elements in prolog - list

I need to get all list element in out side of the list using prolog.
['1','2','3',a,b,c] to become X='1','2','3',a,b,c
I need the result X as shown above.
is it possibile to get the result?

This will literally display what you're asking for (I'm assuming you're interested in the result strictly for display purposes).
print_list(L) :-
write('X='),
print_list_aux(L), !.
print_list_aux([H1,H2|T]) :-
print(H1),
write(','),
print_list_aux([H2|T]).
print_list_aux([X]) :-
print(X),
nl.
print_list_aux([]) :- nl.
Example:
?- print_list(['1', '2', a, b]).
X='1','2',a,b
true.
?-
If you use write/1 instead of print/1, you eliminate the quotes on the numbers in the output, so it would be: X=1,2,a,b.

Related

problem with deleting list item in prolog

my code in prolog
:- dynamic kitchenfurniture/1.
kitchenfurniture([furniture(fridge,1), furniture(table,2), furniture(chair,1)]).
writel([H|T]) :- write(H), nl, writel(T).
whatkitchenfurniture :- kitchenfurniture(X), writel(X).
addkitchenfurniture(X) :- kitchenfurniture(Y), append(Y, [X], Z), retract(kitchenfurniture(Y)), assert(kitchenfurniture(Z)).
deletekitchenfurniture(X) :- kitchenfurniture(Y), delete(X, Y, Z), retract(kitchenfurniture(Y)), assert(kitchenfurniture(Z)).
when I enter the code in the console
it does not remove the item from the list
problem wth line code deletekitchenfurniture(furniture(fridge,1)).
It is difficult to understand what exactly you type into the console; why don't you show it?
It is probable that this is wrong:
?- deleteaddkitchenfurniture('furniture(fridge,1)').
The correct way to do it might be:
?- deleteaddkitchenfurniture(furniture(fridge,1)).
No single quotes there. If you put it in single quotes, it becomes an atom with some parentheses embedded in it. If you don't quote, it is a compound term, as in the original list you have in here:
kitchenfurniture([furniture(fridge,1), furniture(table,2), furniture(chair,1)]).

Prolog: expressing that two lists have at least two elements in common

I am trying to find out if two lists overlap. The predicate I want to write
takes two lists and returns true if the lists have at least two elements in common.
Sample queries with expected answer:
?- overlap([13,14,15], [17,18,13,19]).
false.
?- overlap([13,14,15], [14,17,13,18,16]).
true.
However, so far, I only got one element to work.
member(M, [M|_]).
member(M, [_|T]) :-
member(M, T).
overlap(X, Y) :-
member(M, X),
member(M, Y).
?- overlap([a,b,c,d], [1,2,c,d]).
How can I make sure it checks two elements, not just one?
Another approach, very close to your code, would be to make sure that the two members are not the same:
overlap(X, Y) :-
dif(A, B),
member(A, X), member(A, Y),
member(B, X), member(B, Y).
Since there is a comment asking for a more efficient way to do it, here is an altogether different approach, as in this answer to a very similar question.
overlap(N, X, Y) :-
sort(Xs, SX),
sort(Ys, SY),
append(SX, SY, All), length(All, Len_all),
sort(All, Sorted), length(Sorted, Len_sorted),
Len_sorted =< Len_all - 2.
In simple words, since sort also removes all duplicates, you can count the number of duplicates in a list by comparing the length before and after sorting. Once you write the predicate in this fashion, you will also notice that you can generalize it a bit, so that it has two arguments: a list of lists, and a non-negative integer which is the number of elements shared among all lists:
overlap_n(LL, N) :-
maplist(sort, LL, SLL), % sort all lists
append(SLL, All), length(All, Len_all),
sort(All, Sorted), length(Sorted, Len_sorted),
N is Len_all - Len_sorted.
You can now express your original question as:
?- overlap_n([X, Y], N), N >= 2.
If your Prolog has intersection/3, the shorter form could be:
overlap(X,Y) :- intersection(X,Y,[_,_|_]).
It will be inefficient for large, overlapping lists. Your approach is easily corrected and extended:
overlap(X,Y) :-
select(A,X,Rx), select(A,Y,Ry),
member(B,Rx), member(B,Ry).
I would add a cut at end to avoid multiple solutions...

How do I check if the first occurrence of a number equals to x?

I'm am trying to find a way to check if the first first a number in a nested list equals to x.
check(X,L), X= is a number and Y is a nested list.
check(2,[a,b[g,4],y,8]).
false
check(2,[a,b[g,2],y,8]).
true
It seems that recursion would do best. But I still do not understand how to approach it with recursion in Prolog.
I had this idea of flattening the nested list and then check if first element is a number and if it equals to X.
Can anyone help me?
Your idea must be refined. Some code is needed to match the first occurrence. I would 'cheat':
check(X,L) :- flatten(L,F), include(number,F,[X|_]).
It can be nicely done with simple recursion:
check(X,[X|_]) :- number(X).
check(X,[NL|_]) :- is_list(NL), check(X, NL).
check(X,[V|L]) :- not(number(V)), check(X, L).
UPDATE:
This fixes problem found by #CappelliC:
check(X,[X|_]) :- number(X).
check(X,[V|L]) :- not(number(V)), not(is_list(V)), check(X, L).
check(X,[NL|L]) :- is_list(NL), append(NL,L,BL), check(X, BL).
Results:
?- check(2,[a,b,[g,4],y,8]).
false.
?- check(2,[a,b,[g,2],y,8]).
true .

Prolog - copy a piece of list

I need to duplicate list in prolog.
I have list:
L = [a(string1,value1),a(string2,value2),a(string3,value3),a(string4,value4)].
Output will be: L = [string1, string2, string3, string4].
How can I do this?
I can copy whole list by code:
copy([],[]).
copy([H|L1],[H|L2]) :- copy(L1,L2).
I have tried something like:
copy2([],[]).
copy2([H|L1],[K|L2]) :- member(f(K,_),H), copy2(L1,L2).
But it does not work properly.
But I need only strings from my original list. Can anyone help?
pattern matching is used to decompose arguments: you can do
copy([],[]).
copy([a(H,_)|L1],[H|L2]) :- copy(L1,L2).
It is uncommon to use a structure a/2 for this purpose. More frequently, (-)/2 is used for this. Key-Value is called a (key-value) pair.
Also the name itself is not very self-revealing. This is no copy at all. Instead, start with a name for the first argument, and then a name for the second. Lets try: list_list/2. The name is a bit too general, so maybe apairs_keys/2.
?- apairs_keys([a(string1,value1),a(string2,value2)], [string1, string2]).
Here are some definitions for that:
apairs_keys([], []).
apairs_keys([a(K,_)|As], [K|Ks]) :-
apairs_keys(As, Ks).
Or, rather using maplist:
apair_key(a(K,_),K).
?- maplist(apair_key, As, Ks).
Or, using lambdas:
?- maplist(\a(K,_)^K^true, As, Ks).
Declarative debugging techniques
Maybe you also want to understand how you can quite rapidly localize the error in your original program. For this purpose, start with the problematic program and query:
copy2([],[]).
copy2([H|L1],[K|L2]) :-
member(f(K,_),H),
copy2(L1,L2).
?- copy2([a(string1,value1),a(string2,value2),a(string3,value3),a(string4,value4)], [string1, string2, string3, string4]).
false.
Now, generalize the query. That is, replace terms by fresh new variables:
?- copy2([a(string1,value1),a(string2,value2),a(string3,value3),a(string4,value4)], [A, B, C, D]).
false.
?- copy2([a(string1,value1),a(string2,value2),a(string3,value3),a(string4,value4)], L).
false.
?- copy2([a(string1,value1),B,C,D], L).
false.
?- copy2([a(string1,value1)|J], L).
false.
?- copy2([a(S,V)|J], L).
false.
?- copy2([A|J], L).
A = [f(_A,_B)|_C], L = [_A|_D]
; ... .
So we hit bottom... It seems Prolog does not like a term a/2 as first argument.
Now, add
:- op(950,fx, *).
*_.
to your program. It is kind of a simplistic debugger. And generalize the program:
copy2([],[]).
copy2([H|L1],[K|L2]) :-
member(f(K,_),H),
* copy2(L1,L2).
Member only succeeds with H being of the form [_|_]. But we expect it to be a(_,_).

How can I check if an element in the list is an empty list: []?

How can I check if an element in the list is an empty list: [] ?
I've got the following:
display_degrees([A,B,C,D]):- write(B).
display_degrees([A,B,C,D]):- B==[], nl,write('has no degree'), nl, !.
When I enter in something like:
display_degrees([1,[],3,4]).
I just get: [] instead of 'has no degree'. Is my syntax wrong? Can I not add a clause to this predicate like this?
You're getting this behavior because proof search stops when a goal has succeeded. When you type
display_degrees([1,[],3,4]).
the first rule unifies, and it writes B. Since it was a success, it stops. You can ask Prolog to keep searching, and then it will find the second clause. In swipl, I get
?- [foo].
?- display_degrees([1,[],3,4]).
[]
true r % I type 'r' there
has no degree
true.
If you're just learning Prolog, I suggest you avoid the cut operator ! for some time. Also, doing IO is not the most intuitive thing. I would try some exercises with defining things like natural numbers and recursive functions. E.g., plus:
plus(z, X, X).
plus(s(X), Y, s(Z)) :- plus(X, Y, Z).
The problem with what you have is that the more general rule will fire first. You could switch the order:
display_degrees([A,[],C,D]) :- nl, write('has no degree'), nl, !.
display_degrees([A,B,C,D]) :- write(B).
I could just as well have written for the first predicate:
display_degrees([A,B,C,D]) :- B == [], nl, write('has no degree'), nl, !.
But the "shortcut" I show initially is more idiomatic for a Prolog predicate like this.
I kept the cut since you know you deterministically want one choice. The first rule will match if and only if the second list element is [].
| ?- display_degrees([1,[],3,4]).
has no degree
yes
| ?- display_degrees([1,2,3,4]).
2
yes
| ?-