dart generating all possible combinations list of lists - dart

I have a list of lists, similar to this:
a = [ [1,2,3], [4,5,6], [7,8,9,10]]
I'd like to create all possible combinations, like this:
[(1, 4, 7), (1, 4, 8), (1, 4, 9), (1, 4, 10), (1, 5, 7), (1, 5, 8), (1, 5, 9), (1, 5, 10), (1, 6, 7), (1, 6, 8), (1, 6, 9), (1, 6, 10), (2, 4, 7), (2, 4, 8), (2, 4, 9), (2, 4, 10), (2, 5, 7), (2, 5, 8), (2, 5, 9), (2, 5, 10), (2, 6, 7), (2, 6, 8), (2, 6, 9), (2, 6, 10), (3, 4, 7), (3, 4, 8), (3, 4, 9), (3, 4, 10), (3, 5, 7), (3, 5, 8), (3, 5, 9), (3, 5, 10), (3, 6, 7), (3, 6, 8), (3, 6, 9), (3, 6, 10)]
For python, there's a library that does exactly this.
Is there a similar solution for Dart?
If not, I'd appreciate a simple code that accomplish that

One approach could be:
Iterable<List<T>> allCombinations<T>(List<List<T>> sources) sync* {
if (sources.isEmpty || sources.any((l) => l.isEmpty)) {
yield [];
return;
}
var indices = List<int>.filled(sources.length, 0);
var next = 0;
while (true) {
yield [for (var i = 0; i < indices.length; i++) sources[i][indices[i]]];
while (true) {
var nextIndex = indices[next] + 1;
if (nextIndex < sources[next].length) {
indices[next] = nextIndex;
break;
}
next += 1;
if (next == sources.length) return;
}
indices.fillRange(0, next, 0);
next = 0;
}
}
This works by effectively treating the indices as a number in variable base based on the source list lengths, then incrementing it and creating the corresponding list.
Time complexity is still 𝒪(Πi(source[i].length) * source.length).

Could not find a package which does exactly what you want, but I guess your can do something like this if you want to introduce your own method:
void main() {
print(combinations([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9, 10]
]));
// ([1, 4, 7], [1, 4, 8], [1, 4, 9], [1, 4, 10], ..., [3, 6, 9], [3, 6, 10])
}
Iterable<List<T>> combinations<T>(
List<List<T>> lists, [
int index = 0,
List<T>? prefix,
]) sync* {
prefix ??= <T>[];
if (lists.length == index) {
yield prefix.toList();
} else {
for (final value in lists[index]) {
yield* combinations(lists, index + 1, prefix..add(value));
prefix.removeLast();
}
}
}
More efficient solution but also more risky to use since it does require the user of combinations to take care when consuming the output and make sure not to keep any instances of the inner Iterable:
void main() {
print(combinations([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9, 10]
]).map((e) => e.toList()));
// ([1, 4, 7], [1, 4, 8], [1, 4, 9], [1, 4, 10], ..., [3, 6, 9], [3, 6, 10])
}
Iterable<Iterable<T>> combinations<T>(
List<List<T>> lists, [
int index = 0,
List<T>? prefix,
]) sync* {
prefix ??= <T>[];
if (lists.length == index) {
yield prefix;
} else {
for (final value in lists[index]) {
yield* combinations(lists, index + 1, prefix..add(value));
prefix.removeLast();
}
}
}
The problem with this solution is the risk of misuse as the following example:
final listOfCombinations = combinations([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9, 10]
]).toList();
print(listOfCombinations);
// [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]
Which should instead be:
final listOfCombinations = combinations([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9, 10]
]).map((e) => e.toList()).toList();
print(listOfCombinations);
// [[1, 4, 7], [1, 4, 8], [1, 4, 9], [1, 4, 10], [1, 5, 7], [1, 5, 8], [1, 5, 9], [1, 5, 10], [1, 6, 7], [1, 6, 8], [1, 6, 9], [1, 6, 10], [2, 4, 7], [2, 4, 8], [2, 4, 9], [2, 4, 10], [2, 5, 7], [2, 5, 8], [2, 5, 9], [2, 5, 10], [2, 6, 7], [2, 6, 8], [2, 6, 9], [2, 6, 10], [3, 4, 7], [3, 4, 8], [3, 4, 9], [3, 4, 10], [3, 5, 7], [3, 5, 8], [3, 5, 9], [3, 5, 10], [3, 6, 7], [3, 6, 8], [3, 6, 9], [3, 6, 10]]
So, use the first suggested solution if you don't want the risk of this kind of issues. :)

check out this answer. working for the problem you are searching for:
https://stackoverflow.com/a/57883482/11789758

Related

Can I use cvxpy to split integer-2D-array to two arrays?

I have a problem that I wonder if I can solve using cvxpy:
The problem:
I have a two dimensional integers array and I want to split it to two array in a way that each row of the source array is either in the 1st or 2nd array.
The requirement from these arrays us that for each column, the sum of integers in array #1 will be as close as possible to twice the sum of integers in array #2.
Example:
Consider the input array:
[
[1, 2, 3, 4],
[4, 6, 2, 5],
[3, 9, 1, 2],
[8, 1, 0, 9],
[8, 4, 0, 5],
[9, 8, 0, 4]
]
The sums of its columns is [33, 30, 6, 29] so ideally we are looking for 2 arrays that the sums of their columns will be:
Array #1: [22, 20, 4, 19]
Array #2: [11, 10, 2, 10]
Off course this is not always possible but I looking for the best solution for this problem.
A possible solution for this specific example might be:
Array #1:
[
[1, 2, 3, 4],
[4, 6, 2, 5],
[8, 4, 0, 5],
[9, 8, 0, 4]
]
With column sums: [22, 20, 5, 18]
Array #2:
[
[3, 9, 1, 2],
[8, 1, 0, 9],
]
With column sums: [11, 10, 1, 11]
Any suggestions?
You can use a boolean vector variable to select rows. The only thing left to decide is how much to penalize errors. In this case I just used the norm of the difference vector.
import cvxpy as cp
import numpy as np
data = np.array([
[1, 2, 3, 4],
[4, 6, 2, 5],
[3, 9, 1, 2],
[8, 1, 0, 9],
[8, 4, 0, 5],
[9, 8, 0, 4]
])
x = cp.Variable(data.shape[0], boolean=True)
prob = cp.Problem(cp.Minimize(cp.norm((x - 2 * (1 - x)) * data)))
prob.solve()
A = np.round(x.value) # data
B = np.round(1 - x.value) # data
A and B are the sum of rows.
(array([21., 20., 4., 19.]), array([12., 10., 2., 10.]))

Ruby array to subarray with fall factor

Is there any inbuilt method available to split large array into smaller chunks with dynamic fall factor?
Eg: i=0
src_arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
if batch_size = 5 and fall_factor = 1, first chunk should be [1, 2, 3, 4, 5] and subsequent array chunks should start from start_index = i * (batch_size - fall_factor). ie, start_index will be 0, 4, 8, 12, and
result: [1, 2, 3, 4, 5]
[5, 6, 7, 8, 9]
[9, 10, 11, 12, 13]
[13, 14]
if fall_factor = 2 result should be as below
[1, 2, 3, 4, 5]
[4, 5, 6, 7, 8]
[7, 8, 9, 10, 11]
[10, 11, 12, 13, 14]
I know how to SOLVE this. My question is if any inbuilt method available like each_slice to get this done instead of reinventing.
For example you can use just #step method of Numeric
0.step(src_arr.size - fall_factor - 1, batch_size - fall_factor).map do |ind|
src_arr[ind, batch_size]
end
# fall_factor = 1
# => [[1, 2, 3, 4, 5], [5, 6, 7, 8, 9], [9, 10, 11, 12, 13], [13, 14]]
# fall_factor = 2
# => [[1, 2, 3, 4, 5], [4, 5, 6, 7, 8], [7, 8, 9, 10, 11], [10, 11, 12, 13, 14]]
Code
def doit(arr, batch_size, fall_factor)
arr[batch_size..-1].
each_slice(batch_size-fall_factor).
each_with_object([arr[0,batch_size]]) { |b,c| c << [*c.last[-fall_factor..-1], *b] }
end
Examples
arr = (1..14).to_a
#=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
doit(arr, 5, 1)
#=> [[1, 2, 3, 4, 5], [5, 6, 7, 8, 9], [9, 10, 11, 12, 13], [13, 14]]
doit(arr, 5, 2)
#=> [[1, 2, 3, 4, 5], [4, 5, 6, 7, 8], [7, 8, 9, 10, 11], [10, 11, 12, 13, 14]]
doit(arr, 5, 3)
#=> [[1, 2, 3, 4, 5], [3, 4, 5, 6, 7], [5, 6, 7, 8, 9], [7, 8, 9, 10, 11],
# [9, 10, 11, 12, 13], [11, 12, 13, 14]]
doit(arr, 5, 4)
#=> [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7], [4, 5, 6, 7, 8],
# [5, 6, 7, 8, 9], [6, 7, 8, 9, 10], [7, 8, 9, 10, 11], [8, 9, 10, 11, 12],
# [9, 10, 11, 12, 13], [10, 11, 12, 13, 14]]
Explanation
For arr above and:
batch_size = 5
fall_factor = 2
we have:
a = arr[batch_size..-1]
#=> arr[5..-1]
#=> [6, 7, 8, 9, 10, 11, 12, 13, 14]
b = a.each_slice(batch_size-fall_factor)
#=> a.each_slice(3)
#=> #<Enumerator: [6, 7, 8, 9, 10, 11, 12, 13, 14]:each_slice(3)>
We can see the elements of the enumerator b by converting it to an array:
b.to_a
#=> [[6, 7, 8], [9, 10, 11], [12, 13, 14]]
Continuing:
d = [arr[0,batch_size]]
#=> [[1, 2, 3, 4, 5]]
b.each_with_object(d) { |b,c| c << [*c.last[-fall_factor..-1], *b] }
#=> [[1, 2, 3, 4, 5], [4, 5, 6, 7, 8], [7, 8, 9, 10, 11], [10, 11, 12, 13, 14]]
To see how the last calculation is performed, let:
e = b.each_with_object(d)
#=> #<Enumerator: #<Enumerator: [6, 7, 8, 9, 10, 11, 12, 13, 14]:
# each_slice(3)>:each_with_object([[1, 2, 3, 4, 5]])>
e.to_a
#=> [[[6, 7, 8], [[1, 2, 3, 4, 5]]],
# [[9, 10, 11], [[1, 2, 3, 4, 5]]],
# [[12, 13, 14], [[1, 2, 3, 4, 5]]]]
We can use Enumerator#next to obtain each element of e that is passed to the block, set the block variables to each of those values and perform the block calculation. The first element is passed to the block:
b, c = e.next
#=> [[6, 7, 8], [[1, 2, 3, 4, 5]]]
b #=> [6, 7, 8]
c #=> [[1, 2, 3, 4, 5]]
The block calculation is therefore:
c << [*c.last[-fall_factor..-1], *b]
#=> c << [*[[1, 2, 3, 4, 5]].last[-2..-1], *[6, 7, 8]]
# c << [*[1, 2, 3, 4, 5][-2..-1], *[6, 7, 8]]
# c << [*[4, 5], *[6, 7, 8]]
# c << [4, 5, 6, 7, 8]
c #=> [[1, 2, 3, 4, 5], [4, 5, 6, 7, 8]]
The next element of e is now passed to the block:
b, c = e.next
#=> [[9, 10, 11], [[1, 2, 3, 4, 5], [4, 5, 6, 7, 8]]]
b #=> [9, 10, 11]
c #=> [[1, 2, 3, 4, 5], [4, 5, 6, 7, 8]]
The remaining calculations are performed similarly.
Based on logic shared by you, below is one possible implementation:
b = 5 # batch size
f = 2 # fall factor
indices = (0...src_arr.size).collect {|i| i * (b-f)}.reject {|i| i + f >= src_arr.size}
result = indices.each_with_object([]) do |i, obj|
obj << src_arr[i, b]
end
p result
#=> [[1, 2, 3, 4, 5], [4, 5, 6, 7, 8], [7, 8, 9, 10, 11], [10, 11, 12, 13, 14]]

How to sort map's values?

Can someone give me a hint? I want to sort a map's values by the length of the lists.
var chordtypes = {
"maj": [0, 4, 7],
"M7": [0, 4, 7, 11],
"m7": [0, 3, 7, 10],
"6": [0, 4, 7, 9],
"9": [0, 4, 7, 10, 14],
"sus2": [0, 2, 7],
"sus4": [0, 5, 7],
"omit3": [0, 7],
"#5": [0, 4, 8],
"+7b9#11": [0, 4, 8, 10, 13, 18],
"+9": [0, 4, 8, 10, 14]
};
A function that does sort a Map of List on their length.
import 'dart:collection';
/// sorts the ListMap (== A Map of List<V>) on the length
/// of the List values.
LinkedHashMap sortListMap(LinkedHashMap map) {
List mapKeys = map.keys.toList(growable : false);
mapKeys.sort((k1, k2) => map[k1].length - map[k2].length);
LinkedHashMap resMap = new LinkedHashMap();
mapKeys.forEach((k1) { resMap[k1] = map[k1] ; }) ;
return resMap;
}
result for :
var res = sortListMap(chordtypes);
print(res);
==>
{ omit3: [0, 7],
maj: [0, 4, 7],
sus2: [0, 2, 7],
sus4: [0, 5, 7],
#5: [0, 4, 8],
M7: [0, 4, 7, 11],
m7: [0, 3, 7, 10],
6: [0, 4, 7, 9],
9: [0, 4, 7, 10, 14],
+9: [0, 4, 8, 10, 14],
+7b9#11: [0, 4, 8, 10, 13, 18] }
Using DART language:
Let's say you want to sort a Map with integer key and value of type Foo:
class Foo {
int x; //it can be any type
}
So you can get the list of all the entries, sort them like a normal list and then rebuild the map:
Map<int, Foo> map = //fill map
var entries = map.entries.toList();
entries.sort((MapEntry<int, Foo> a, MapEntry<int, Foo> b) => a.value.x.compareTo(b.value.x));
map = Map<int, Foo>.fromEntries(entries);
Something like this could work for you:
Map chordtypes = {
"maj": [0, 4, 7],
"M7": [0, 4, 7, 11],
"m7": [0, 3, 7, 10],
"6": [0, 4, 7, 9],
"9": [0, 4, 7, 10, 14],
"sus2": [0, 2, 7],
"sus4": [0, 5, 7],
"omit3": [0, 7],
"#5": [0, 4, 8],
"+7b9#11": [0, 4, 8, 10, 13, 18],
"+9": [0, 4, 8, 10, 14]
};
List keys = chordtypes.keys.toList();
keys.sort((k1, k2) {
if(chordtypes[k1].length > chordtypes[k2].length)
return -1;
if(chordtypes[k1].length < chordtypes[k2].length)
return 1;
return 0;
});
keys.forEach((String k) {
print('$k ${chordtypes[k]}');
});
Building on #Leonardo Rignanese's answer. An extension function for a more functional approach:
extension MapExt<T, U> on Map<T, U> {
Map<T, U> sortedBy(Comparable value(U u)) {
final entries = this.entries.toList();
entries.sort((a, b) => value(a.value).compareTo(value(b.value)));
return Map<T, U>.fromEntries(entries);
}
}
General usage:
foos.sortedBy((it) => it.bar);
Usage for OP:
final sortedChordtypes = chordtypes.sortedBy((it) => it.length);
Gist here: https://gist.github.com/nmwilk/68ae0424e848b9f05a8239db6b708390

Ruby "bucketize" an array

Suppose I have the following array:
a = (1..10).to_a
Is there a single in-built ruby (or rails) function that is capable or splitting the array into exactly N roughly equal parts while maintaining the order?
I'm looking for something like this:
a.bucketize(3)
=> [[1,2,3,4],[5,6,7],[8,9,10]]
a.bucketize(5)
=> [[1,2],[3,4],[5,6],[7,8],[9,10]]
Hint: each_slice doesn't do this.
Also, I know I could write this function myself and open up the Array class or Enumerable module.
Thanks.
I'd do it like this:
ary = (1..10).to_a
ary.each_slice((ary.length.to_f/3).ceil).to_a
=> [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
ary.each_slice((ary.length.to_f/5).ceil).to_a
=> [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
It's not perfect, but it does come close:
ary = (1..9).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
ary.each_slice((ary.length.to_f/2).ceil).to_a
=> [[1, 2, 3, 4, 5], [6, 7, 8, 9]]
ary.each_slice((ary.length.to_f/3).ceil).to_a
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
ary.each_slice((ary.length.to_f/4).ceil).to_a
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
This kind of task is best tackled using a functional approach. Here's a tail-recursive functional implementation (except for the unavoidable << to accumulate efficiently on arrays):
class Array
def bucketize(n, index = 0, acc = [])
return acc if n <= 0 || size <= index
n0 = ((size - index).to_f / n).ceil
bucketize(n - 1, index + n0, acc << self[index, n0])
end
end
(1..9).to_a.bucketize(3)
#=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
(1..10).to_a.bucketize(3)
#=> [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
(1..11).to_a.bucketize(3)
#=> [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11]]
Here's what I ended up doing:
class Array
def bucketize(n)
return [] if (buckets = n.to_i) <= 0
j = length / buckets.to_f
result = each_with_index.chunk { |_, i| (i / j).floor }.map { |_, v| v.map(&:first) }
result << [] until result.length == buckets
result
end
end
Examples:
a = (1..10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a.bucketize(1)
=> [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]
a.bucketize(2)
=> [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
a.bucketize(3)
=> [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
a.bucketize(4)
=> [[1, 2, 3], [4, 5], [6, 7, 8], [9, 10]]
...
a.bucketize(9)
=> [[1, 2], [3], [4], [5], [6], [7], [8], [9], [10]]
...
a.bucketize(11)
=> [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], []]

ruby array iteration

I have four arrays(named array1,2,3,4) each with 8 objects and want to sort them into 8 empty arrays that will consist of 4 objects each, i.e place each object from array 1 into an empty array.
?? << array1.shift until array.empty?
I'm not sure how to iterate over the 8 empty arrays so that each of them recieves an object from array1
e.g
array1 = clubs1-8
array2 = spades1-8
array3 = hearts1-8
array4 = diamonds1-8
8 empty arrays or players, each player is dealt a card from array1,then 1 card from array2 etc.
Thanks for the answers but I wanted to add the objects iteratively so I could add conditions based on what objects had already been added to each array
e.g
distribute array1 among 8 empty arrays
distribute array2 among the 8 arrays but check before that no array contains the same card number (it can't have both the 2 of hearts and the 2 of diamonds)
Did you mean something like this?
require "matrix"
a1 = (0..7).to_a
a2 = (8..15).to_a
a3 = (16..23).to_a
a4 = (24..31).to_a
Matrix[a1, a2, a3, a4].transpose.to_a #=> [[0, 8, 16, 24], [1, 9, 17, 25], [2, 10, 18, 26], [3, 11, 19, 27], [4, 12, 20, 28], [5, 13, 21, 29], [6, 14, 22, 30], [7, 15, 23, 31]]
Added:
In fact it is even more trivial:
a1.zip(a2, a3, a4) #=> [[0, 8, 16, 24], [1, 9, 17, 25], [2, 10, 18, 26], [3, 11, 19, 27], [4, 12, 20, 28], [5, 13, 21, 29], [6, 14, 22, 30], [7, 15, 23, 31]]
Iteration is not the only way. Try this (assuming a1..a8 are your 8 empty arrays):
a1, a2, a3, a4, a5, a6, a7, a8 = array1.zip(array2, array3, array4)
irb(main):001:0> ar1 = [1,2,3,4,5,6,7,8]
=> [1, 2, 3, 4, 5, 6, 7, 8]
irb(main):002:0> ar2 = [2,3,4,1,2,3,2,1]
=> [2, 3, 4, 1, 2, 3, 2, 1]
irb(main):003:0> ar3 = [4,3,5,6,3,3,4,5]
=> [4, 3, 5, 6, 3, 3, 4, 5]
irb(main):004:0> ar4 = [5,2,5,6,7,2,2,5]
=> [5, 2, 5, 6, 7, 2, 2, 5]
irb(main):005:0> ar1.zip(ar2,ar3,ar4)
=> [[1, 2, 4, 5], [2, 3, 3, 2], [3, 4, 5, 5], [4, 1, 6, 6], [5, 2, 3, 7], [6, 3, 3, 2], [7, 2, 4, 2], [8, 1, 5, 5]]

Resources