Scan list in prolog - list

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.)

Related

Find sum of number in multiple sets using exactly one number of each set

Background
Hi, I'm trying to solve a programming problem and I'm stuck on the following problem:
Assume you have multiple lists of numbers. All are sorted in decreasing order.
You now have to take exactly one number from each list to make the biggest possible sum.
So far so easy, to solve this you could just take the first number of each list and you're done.
But now, I need the second-largest sum while still using exactly one number from each list.
To achieve this, I would take the first element in each list but for the list which has the least difference between the first and second number the second number will be used.
This is still pretty doable.
The Problem
But I need an Iterator over every possible sum using exactly one number of each list sorted in decreasing order.
For performance reasons, it isn't possible to just compute every sum and then sort it. The algorithm must already provide the sums in decreasing order. If there are multiple combinations for a sum then the sum must be returned multiple times.
Additional Requirements
The Iterator should be lazy (only calculate the next sum when required).
The Lists are already lazy, which means you should require as few values as possible to calculate the fitting sum.
Example
For the Lists:
List 1: [5, 2, 1]
List 2: [10, 2]
List 3: [6, 1]
The Iterator then should return:
[5, 10, 6] = 21
[2, 10, 6] = 18
[1, 10, 6] = 17
[5, 10, 1] = 16
[5, 2, 6] = 13
[2, 10, 1] = 13
[1, 10, 1] = 12
[2, 2, 6] = 10
[1, 2, 6] = 9
[5, 2, 1] = 8
[2, 2, 1] = 5
[1, 2, 1] = 4
Comment
I don't need code as an answer to my question (you're still welcome to provide it if it helps to explain). What I'm looking for are ideas to solve this, or solutions that I can implement myself.
Thanks in advance!
First of all, Thanks to wlui155 for the help.
For Anyone interested, I coded a BFS algorithm that acts as follows:
Definitions:
Entry: Struct containing indices of used numbers and sum
BSet: Ordered set which can only contain unique Entries
Algorithm:
Pop Entry with biggest sum from BSet
Create a clone for each list
Advance in each clone a different index by one
Put new entries in BSet
Print current Entry
Goto 1.
Now you only have to ensure that no entry appears again after you've popped it. This can be ensured with a separate set containing all combinations for the current sum. Once the current sum gets smaller this set can be cleared.
If you have ideas to improve this, you're welcome to tell me.

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 member/2 predicate

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.

Python 3 list with range and other individual numbers

I need to make a list of numbers. These numbers represent binary masks. The first 100 or so masks are all included in this range. In the next group of masks only certain masks are included. I need a list similar to the following.
[1,2,3,5,6,7,8,9,10,30,34,48,53,62]
Can I do something like [range(1,10),30,34,48,53,62]
or do I need to create my list using range(1,10) and then append the next list to it?
Thanks
Python 3 actually allow you to build a list literal prepending an * to any iterable objects - which are in turn expanded in place:
>>> [1,2, *range(10), *range(2)]
[1, 2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1]
If you need this n older Pythons, or if you'd prefer to keep readability for people not too proeficient in Python who might have to walk through your code, an option is just to concatenate your different list fragments using the + operator:
a = list(range(1,10)) + [ 30,34,48,53,62]
Looks like I had to use the list(range(1,10)+[47,34,57]
solution

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.