Prolog member/2 predicate - list

Why does prolog answer false to: member([5], [2, 5]).?
Is there a way to work around it?
Any help will be greatly appreciated.

Why does Prolog answer false to: member([5], [2, 5]).?
Let's ask Prolog why! Download library(diadem) into your working directory and:
?- use_module(diadem).
true.
?- member([5], [2,5]).? Expl.
Expl = member([_|_], [2, 5])
; ... .
Not only does it fail but also a generalization fails:instead of [5] that is a list with a single element 5, we have now simply at least one element - no matter which. So we can take the value for Expl as a query which still fails. Something in the remaining goal must thus be the culprit.
?- member([_|_], [2, 5]).
false.
Note also what was not generalized away: The two elements are still here! If they would be variables, the query would succeed! Generalize the query a bit:
?- member([5], [2, Any]).
Any = [5].
Now it succeeds!

As described in the SWI Prolog documentation for member/2:
member(?Elem, ?List )
True if Elem is a member of List.
The predicate is member. It is not subset or sublist or subsequence. It succeeds if the first argument is a member (that is, an element) of the list given in the second argument. The element [5] is not a member of the list [2, 5] since the element [5] isn't 2 and it isn't 5. However, [5] would be a member of the list [2, [5]], so member([5], [2, [5]]) would succeed.

It could be that you are looking for another predicate?
From the SWI Prolog documentation for subset/2:
subset( +SubSet, +Set )
True if all elements of SubSet belong to Set as well.
It works as expected:
Welcome to SWI-Prolog (threaded, 64 bits, version 7.5.5)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
?- subset([5], [2, 5]).
true.
?- subset([5, 3], [2, 3, 5, 7]).
true.
?- subset([5, 3], [2, 5]).
false.

Related

Need help in understand list slicing inside list comprehension,

I know that the following breaks up a list and put it into two lists depending on whether an index is even or odd. But not sure how [n::2] for n in [1,0] works.
[[1,2,3,4,5][n::2] for n in [1, 0] ]
[[2, 4], [1, 3, 5]]
Can you point me to post that explain and walk me through the logic behind it? Thank you.
The left part happens with each value of n. n indicates the starting position to take the 2nd element including the n'th one.
print([[1,2,3,4,5][n::2] for n in [1, 0] ] )
print([[1,2,3,4,5][1::2]]) # outputs [[2, 4]]
print([[1,2,3,4,5][0::2]]) # outputs [[1, 3, 5]]
print([[1,2,3,4,5][4::2]]) # outputs [[5]]

Prolog - return list of unique numbers in nested lists

Hi everyone I'm trying to learn Prolog on my own and I am stuck trying to create a function that takes a nested list and returns a list of only the unique numbers. So unique(L,T) means that T is a list of unique numbers extracted from L.
The format of the lists look like this where c is always followed by an int:
[a,[b,[c,5],[c,3]],[c,4]]
Example of what should return as true:
unique([b,[c,4],[c,3]], [4,3])
This is the code I have tried however it is just returning an empty list when i try to query it:
unique([],[]).
unique([X|XS],[X|L]) :-
integer(X),
unique(XS,L).
unique([X|XS],L) :-
\+integer(X),
unique(XS,L).
I have tried various other solutions as well and seem to keep getting an empty list as output or just 'false'. I would appreciate any sort of guidance on this!
This code does not take into account that the lists are nested; it should succeed on (for example):
unique([b,c,4,c,3],[4,3]).
You'll need a case where the head of the list is a list, recursively find the integers in that, and append what you find to what you find for the tail of the list.
Flatten the list, filter it to get the numbers, sort to make them unique:
?- L = [a,[b,[c,5],[c,3]],[c,4]], flatten(L, F), include(number, F, N), sort(N, Unique_numbers).
L = [a, [b, [c, 5], [c, 3]], [c, 4]],
F = [a, b, c, 5, c, 3, c, 4],
N = [5, 3, 4],
Unique_numbers = [3, 4, 5].
If you want to keep the original order you can't sort, but there are many answers on SO that show you how to do it.
If you don't want to use the library predicates, look up how they are defined (flatten/2 and include/2) and get inspiration for your own solution.

Prolog How to Declare a List to a Variable

In Prolog, I'm struggling to understand how to bind a list of lists to a variable. For instance, say I have the predicate makeList (which I don't know how to write), then I should be able to type:
makeList([[0, 0], [1, 0]]).
Now I want to refer to [[0, 0], [1, 0]] in another predicate with a variable, ListList, like:
predicateThatDoesSomething(ListList) :- write(ListList).
Expected Output:
[[0, 0], [1, 0]]
Obviously predicateThatDoesSomething() knows about the variable named ListList already. But how do I make the predicate makeList()? I want to be able to type makeList([[ANY, LIST, IN, HERE], [ANOTHER, LIST]]) and have that be ListList for example.
You have to write a predicate that merge the two list, thus this predicate must unify with something like:
makeList(List1, List2, [List1, List2]).
After defined this predicate in you knowled base, you can interrogate the prolog engine asking:
makeList([1,2],[2,4],D).
And you'll get: D = [[1, 2], [2, 4]]
To make the other predicate (defined in your KB)
predicateThatDoesSomething(ListList) :- write(ListList).
know the result (output parameter, the results of unification), you have to logically and the statements. So you have to ask:
makeList([1,2],[2,4],D) , predicateThatDoesSomething(D).

Scan list in prolog

I want to scan a list in Prolog.
In particular, I want to write a predicate scan_list (list), and I want to make it check to see if the current element is a positive integer and if so print it.
Thank's.
If this is homework, be assured that the only way to learn any programming language is to practice it and think about the assignments. However, here is a version that might be, what you want
scan_list([]).
scan_list([H|T]) :- H > 0,!, print(H),nl,scan_list(T).
scan_list([_|T]) :- scan_list(T).
It works like that:
?- scan_list([1,-2,7,9,0,-1,14]).
1
7
9
14
yes
In SWI-Prolog there is include/3, e.g. you can write
?- include(<(0), [1, -2, 7, 9, 0, -1, 14, 0.8], L).
L = [1, 7, 9, 14, 0.8].
(Warning: this particular code accepts more numbers than positive integers.)

Appending Nested Lists in Python

I have the following question for homework
Define a function append lists that
takes a list of lists and returns a
new list containing the sublist
values. For example, append lists([[1,
2], [3, 4], [5]]) should return the
list [1, 2, 3, 4, 5] and append
lists([[1, 2], [3], [[4, 5]]]) should
return the list [1, 2, 3, [4, 5]].
I've tried various ways of creating this function in order to append the list so it gives the desired output to no avail so I came here looking for some help. I've found a few other ways of going about this online, but they use extensive methods that we haven't even dabbled in as of yet in my CPSC 121 class. We're limited to the basics in what we've learned.
Any help would be much appreciated!
By now, it is likely that the assignment is gone, but here is a solution:
def append_lists(lists):
output = []
for l in lists:
for e in l:
output.append(e)
return output
This appends each element of each list to the output of the function, which eliminates exactly one level of nesting in the elements.