Find all k-length subsets efficiently in Elixir - combinations

I'm trying to find all k-length subsets of a list in Elixir. Doing this in Python would be easy, but this is a purely functional language and I'm lost.
Input and output are lists right now, but they could be converted to MapSet or similar if needed. Order of output is not important.
choose([1,2,3], 0) = [[]]
choose([1,2,3], 1) = [[1], [2], [3]]
choose([1,2,3], 2) = [[1,2], [1,3], [2,3]]
choose([1,2,3], 3) = [[1,2,3]]
choose([1,2,3], 4) undefined

Related

Prolog generator stuck infinitely trying THE SAME OBJECT over and over?

I am really stuck on a problem in Prolog. I am trying to make a generator "gen_lists_of_pairs(V, L)", which, given a list of natural numbers V, generates all possible lists containing two-element lists, such that their elements are unique and every element is in the form [A, B] where A and B are members of V and A < B. However, the generator seems to get stuck in an infinite loop trying the same thing over and over. I am new to prolog and I have had generators that are stuck attempting infinite possibilities, but I cannot fathom why in the world prolog gets stuck here..
This is my code:
ascending([_]).
ascending([A, B|L]) :- A < B, ascending([B|L]).
gen_list_of_pairs(_, []).
gen_list_of_pairs(V, [[X,Y]|L]) :-
gen_list_of_pairs(V, L),
member(X, V),
member(Y, V),
ascending([X, Y]),
not((member([X, Y], L))).
And this is the debug trace when calling "gen_list_of_pairs([1], X).":
Call:gen_list_of_pairs([1], _7086)
Exit:gen_list_of_pairs([1], [])
X = []
Redo:gen_list_of_pairs([1], _7086)
Call:gen_list_of_pairs([1], _7902)
Exit:gen_list_of_pairs([1], [])
Call:lists:member(_7906, [1])
Exit:lists:member(1, [1])
Call:lists:member(_7912, [1])
Exit:lists:member(1, [1])
Call:ascending([1, 1])
Call:1<1
Fail:1<1
Fail:ascending([1, 1])
Redo:gen_list_of_pairs([1], _7902)
Call:gen_list_of_pairs([1], _7920)
Exit:gen_list_of_pairs([1], [])
Call:lists:member(_7924, [1])
Exit:lists:member(1, [1])
Call:lists:member(_7930, [1])
Exit:lists:member(1, [1])
Call:ascending([1, 1])
Call:1<1
Fail:1<1
Fail:ascending([1, 1])
Redo:gen_list_of_pairs([1], _7920)
...
As you can see, after outputting "X = []", prolog gets stuck in an infinite loop, trying the pair [1,1] over and over and over, even though as far as my scarce knowledge goes, it should either attempt something else or stop the query after failing an attempt... I cannot whatsoever figure this out and am growing increasingly frustrated. Any help would be greatly appreciated...
There is too much recursion in there. Especially as you are recursing "on the left"
gen_list_of_pairs(V, [[X,Y]|L]) :-
gen_list_of_pairs(V, L), ...
With the second argument uninstantiated, this goes off to infinity, no matter what comes afterwards:
gen_list_of_pairs(V, [[X,Y]|L]) :-
gen_list_of_pairs(V, L),false.
Then:
?- gen_list_of_pairs([1,2,3],X).
ERROR: Stack limit (1.0Gb) exceeded
... because there is no stopping criterium. We just pile on [X,Y] to an ever-lengthening list.
It's better to start afresh.
In fact, the task of appending to the "Bag of Solution" is being taken care of by bagof/3 and setof/3.
We just need to generate new pairs, backtrackably, from V:
gimme_another_pair(V,[X,Y]) :-
member(X,V),
member(Y,V),
X < Y.
Then
?- gimme_another_pair([1,2,3],P).
P = [1, 2] ;
P = [1, 3] ;
P = [2, 3] ;
false.
And so:
gen_list_of_pairs(V, Result) :- setof(P,gimme_another_pair(V,P),Result).
And so:
?- gen_list_of_pairs([1,2,3],X).
X = [[1, 2], [1, 3], [2, 3]].

adding two lists together

I am stuck on a problem involving adding two lists together.
For example, if list1 was [1,2,3,4] and list2 was [2,4] I would have to return [3,5,3,4]. Or if list1=[0] and list2=[1] I would return [1]
def addsum(list1,list2):
new_list = []
list1[0]+list2[0] = new_list[0]
and so on. This was my first approach but I'm getting a lot of errors. I'm new to lists so I can't use index or lambda functions. I am only allowed to use len(). Would appreciate the help.
You may want to check out 2 python concepts: list comprehension (http://www.secnetix.de/olli/Python/list_comprehensions.hawk) and condensed form of if-else (https://stackoverflow.com/a/2802748/1045285).
l1 = [1, 2, 4, 5]
l2 = [2, 4]
min_len = min(len(l1), len(l2))
rem = l1[min_len:] if len(l1) > len(l2) else l2[min_len:]
res = [e1 + e2 for e1, e2 in zip(l1[:min_len], l2[:min_len])] + rem

Intersection of two nested lists in Python

I've a problem with the nested lists. I want to compute the lenght of the intersection of two nested lists with the python language. My lists are composed as follows:
list1 = [[1,2], [2,3], [3,4]]
list2 = [[1,2], [6,7], [4,5]]
output_list = [[1,2]]
How can i compute the intersection of the two lists?
I think there are two reasonable approaches to solving this issue.
If you don't have very many items in your top level lists, you can simply check if each sub-list in one of them is present in the other:
intersection = [inner_list for inner in list1 if inner_list in list2]
The in operator will test for equality, so different list objects with the same contents be found as expected. This is not very efficient however, since a list membership test has to iterate over all of the sublists. In other words, its performance is O(len(list1)*len(list2)). If your lists are long however, it may take more time than you want it to.
A more asymptotically efficient alternative approach is to convert the inner lists to tuples and turn the top level lists into sets. You don't actually need to write any loops yourself for this, as map and the set type's & operator will take care of it all for you:
intersection_set = set(map(tuple, list1)) & set(map(tuple, list2))
If you need your result to be a list of lists, you can of course, convert the set of tuples back into a list of lists:
intersection_list = list(map(list, intersection_set))
What about using sets in python?
>>> set1={(1,2),(2,3),(3,4)}
>>> set2={(1,2),(6,7),(4,5)}
>>> set1 & set2
set([(1, 2)])
>>> len(set1 & set2)
1
import json
list1 = [[1,2], [2,3], [3,4]]
list2 = [[1,2], [6,7], [4,5]]
list1_str = map(json.dumps, list1)
list2_str = map(json.dumps, list2)
output_set_str = set(list1_str) & set(list2_str)
output_list = map(json.loads, output_set_str)
print output_list

Does SML supports the nested list?

the Nested List can exist in Scheme, but is it legal to use nested-list in SML? or we can only use simple list in SML?
and if legal,
1) how to check wether the two input list have the same list structure. algorithm the atoms in the list are not equal.
2) Whatever the deep of the input list, how to delete all the atoms in the nested-list that equals to the input value: a. should use the original list and not create a new list.
There's no problem in having nested lists in Standard ML. For an example:
val foo = [ [1, 2, 3], [4, 5], [6] ]
is an example of an int list list, i.e., a list of lists of integers.
As for your additional questions.
1
If by same structure you mean whether the sublists contain the same number of elements, i.e, you want
val bar = [ [34, 4, 6], [2, 78], [22] ]
val baz = [ [1], [4, 6, 2], [3, 6] ]
val cmp_foo_bar = structureEq (foo, bar) (* gives true, since the lengths of the sublists match up *)
val cmp_foo_baz = structureEq (foo, baz) (* gives false, since they don't *)
Then you can simply make a recursive function on the lists, that compares the length of each sublist in turn.
Note, if the lists are nested more than once, you'll need a function for each level. (i.e., one for 'a list lists, one for 'a list list lists, etc.
2
You cannot make a function that "however deep the input list" does something to the elements in the list. The type system will not let you do this. This is similar to how you cannot make the following list:
val illegal_list = [ [1, 2], [ [1, 4], [2, 3] ] ]
This is due to a list only being allowed to contain one type of elements, so if you have an 'a list list, each element in the list must be an 'a list. You cannot have 'as directly.
You'll have to settle on how nested the lists are, and make a function specific to that depth.
There is no problem with nesting lists in SML, e.g. [[1, 2], [3, 4]] works just fine.
However, I suspect you actually mean something more general, namely the ability to nest "lists" in heterogeneous ways: [[1, [3]], 2]. This is not legal as such in SML. However, this is because such a thing is not really a list, it is a tree.
You can define trees easily as well, but you need a more general type definition than the one for list:
datatype 'a tree = L of 'a | T of 'a tree list
Then T[T[L 1, T[L 3]], L 2] is a representation of the "list" above. A function for computing the depth (or height) of such a tree looks like
fun depth (L _) = 0
| depth (T ts) = 1 + max (List.map depth ts)
where max needs to be defined in the obvious manner.

I want to split a list into a tupple of odd and even elements

Hi all im new to programming and im doing a problem for learning and enjoyment. Im a bit stuck at this point.. The problem is from Introduction to Programming using Sml 5.9
I want to split a list of [x1, x2, x3, ... ,xn] = ([x1, x3,....], [x2, x4,...])
This is what I have made so far:
fun split [] = []
| split (x1::x2::x3::x4::xs) = ([x1, x3], [x2, x4])::split xs
val test1split = split [1, 1, 2, 3];
From this I get:
[([1, 2], [1, 3])].... (I want a tuple with splitting list and not this obviously)
If there are more than 4 elements then the function doesn't work. Maybe I need a helper function to sort even and odd elements in a list first? I hope someone can help me with tracking my mind in the correct direction, until then I keep trying.
fun split [] = ([], [])
| split [x] = ([x], [])
| split (x1::x2::xs) =
let
val (ys, zs) = split xs
in
((x1::ys), (x2::zs))
end;
val test1split = split [1, 1, 2, 3, 5, 6] = ([1, 2, 5], [1, 3, 6])
val test2split = split [8, 7, 6, 5, 4, 3] = ([8, 6, 4], [7, 5, 3])
val test3split = split [8, 7] = ([8], [7])
val test4split = split [8] = ([8], [])
Solved it... Not completely sure how lol, need alot more practice to master it. Couldn't have done it without the pointers... Thx alot for the help Nick Barnes.
I'll try not to give too much away, but here are some tips:
You need two base cases - one for [], one for [x].
Your general case only needs to deal with two elements, not four (putting one in the first list, and one in the second)
At the moment, you've got split returning a list, rather than a tuple. The result of your first base case should be ([],[]).
In the general case, the recursive split xs will return a tuple (ys,zs). You need to extract these values, and build the resulting tuple in terms of ys, zs, x1 and x2.
(Edit) A couple of points on your revised solution:
You only need to deal with two elements at a time - the general case should be split x1::x2::xs
split [x,y] is handled by the general case - no need for another base case.
You're missing the recursive call! Elements are ending up in both lists because you're putting xs directly into both halves of your output - you need to split it first. Start with
let (ys, zs) = split xs in ...