Groovy 2D array combinations - arrays

I have a 2D array which looks like [[1, 2, 3], [10, 11]]. I want to get the next combinations: [[1, 2, 3, 10], [1, 2, 3, 11]]. The idea is to take all values from left array and combine it with each value from right array. I've tried different Groovy out of the box methods like combinations(), permutations() to get the expected result, but without any success. Please, help.

Why not simply:
def a = [[1, 2, 3], [10, 11]]
def res = a[ 1 ].collect{ a[ 0 ] + it }
assert res == [[1, 2, 3, 10], [1, 2, 3, 11]]

If one can cheat... Nesting the first list into another list can let us use .combinations() still:
def a = [[[1, 2, 3]], [10, 11]] //a[0] changed to [a[0]]
a.combinations().collect{it.flatten()} //[[1, 2, 3, 10], [1, 2, 3, 11]]
Now, if you can't store the values like that, you can still still make the change part of your code. All this assumes that the list is just a pair.
([a[0]] + a[1..<(a.size())]).combinations().collect{it.flatten()} //same result
I believe there are less unorthodox ways of doing it, but that's a quick and dirty solution.

Related

Append List of array to an array and repeat this in kotlin

I can't seem to find a right solution. Trying to add a list of array to another array. With my Python background it is easily done but not in Kotlin.
val extra = arrayOf(7,7,7)
fun containerArray() {
val even = arrayOf(2, 4, 6)
val odd = arrayOf(1, 3, 5)
val arr1 = arrayOf(even, odd)
val arr2 = arrayOf(*arr1, extra)
print(arr2.contentDeepToString())
}
fun main() {
for (i in 1..3) {
containerArray()
}
}
When executing above code I receive...
[[2, 4, 6], [1, 3, 5], [7, 7, 7]][[2, 4, 6], [1, 3, 5], [7,7,7]][...
What I want to achieve is this ....
[ [2, 4, 6], [1, 3, 5], [7, 7, 7], [7, 7, 7], [7, 7, 7]]
To add a thing to an array of things, and produce a new array, use plusElement:
val arr2 = arr1.plusElement(extra)
This not only works for arrays, but also works for any Iterables, i.e. Lists, Sets etc.
Do you get why you're getting that result? arrayOf(items) creates a new array wrapping those items, so arrayOf(even, odd) is an array that contains two arrays. Then you create another array, containing that array-of-arrays and another single array. You're nesting them as you go
Sweeper's answer is probably what you want, but there are a lot of ways to combine collections, flatten sequences etc. Like one thing you can do is use the *operator (the "spread operator") to "unpack" your arrays, so you get the items instead:
// unpack arr1 from an array of arrays, into just those arrays
// equivalent to arrayOf([2, 4, 6], [1, 3, 5], extra)
val arr2 = arrayOf(*arr1, extra)
print(arr2.contentDeepToString())
>> [[2, 4, 6], [1, 3, 5], [7, 7, 7]]
There's also flatMap, flatten etc - the best option depends on what you're doing!
Also when you say you want this:
[2, 4, 6], [1, 3, 5], [7, 7, 7]
that's just a bunch of values, not contained in anything, so we're assuming you want this:
[[2, 4, 6], [1, 3, 5], [7, 7, 7]]
where they're held in an array (or it could be a list). You could use the spread operator to unpack that into a bunch of values, but all you can do with that is pass it as a variable number of arguments to a function (which is what's happening in arrayOf)
I assume you want to get the following array:
[[2, 4, 6], [1, 3, 5], [7, 7, 7]]
There is an overridden + (plus) operator for Arrays in Kotlin, you can use it for adding arrays:
val arr2 = arr1 + extra
Resulting array arr2 will contain all elements of the original array arr1 and then all elements of the array extra.
ADDITIONALLY:
You can add another array to arr2:
val anotherArray = arrayOf(5, 5, 5)
val arr3 = arr2 + anotherArray
// result: [[2, 4, 6], [1, 3, 5], [7, 7, 7], [5, 5, 5]]
If you want to use the same array arr2 to store elements, you can create it with var modifier:
var arr2 = arr1 + extra
arr2 += arrayOf(5, 5, 5)
There are different ways of what you are trying to achieve using a loop, for example:
val even = arrayOf(2, 4, 6)
val odd = arrayOf(1, 3, 5)
val extra = arrayOf(7,7,7)
var arr1 = arrayOf(even, odd)
for (i in 1..3) {
arr1 += extra
}
arr1 will contain next elements: [[2, 4, 6], [1, 3, 5], [7, 7, 7], [7, 7, 7], [7, 7, 7]]

get array index from sort in Ruby

I have an array
array_a1 = [9,43,3,6,7,0]
which I'm trying to get the sort indices out of, i.e. the answer should be
array_ordered = [6, 3, 4, 5, 1, 2]
I want to do this as a function, so that
def order (array)
will return array_ordered
I have tried implementing advice from Find the index by current sort order of an array in ruby but I don't see how I can do what they did for an array :(
if there are identical values in the array, e.g.
array_a1 = [9,43,3,6,7,7]
then the result should look like:
array_ordered = [3, 4, 5, 6, 1, 2]
(all indices should be 0-based, but these are 1-based)
You can do it this way:
[9,43,3,6,7,0].
each_with_index.to_a. # [[9, 0], [43, 1], [3, 2], [6, 3], [7, 4], [0, 5]]
sort_by(&:first). # [[0, 5], [3, 2], [6, 3], [7, 4], [9, 0], [43, 1]]
map(&:last)
#=> [5, 2, 3, 4, 0, 1]
First you add index to each element, then you sort by the element and finally you pick just indices.
Note, that array are zero-indexed in Ruby, so the results is less by one comparing to your spec.
You should be able to just map over the sorted array and lookup the index of that number in the original array.
arr = [9,43,3,6,7,0]
arr.sort.map { |n| arr.index(n) } #=> [5, 2, 3, 4, 0, 1]
Or if you really want it 1 indexed, instead of zero indexed, for some reason:
arr.sort.map { |n| arr.index(n) + 1 } #=> [6, 3, 4, 5, 1, 2]
array_a1 = [9,43,3,6,7,0]
array_a1.each_index.sort_by { |i| array_a1[i] }
#=> [5, 2, 3, 4, 0, 1]
If array_a1 may contain duplicates and ties are to be broken by the indices of the elements (the element with the smaller index first), you may modify the calculation as follows.
[9,43,3,6,7,7].each_index.sort_by { |i| [array_a1[i], i] }
#=> [2, 3, 4, 5, 0, 1]
Enumerable#sort_by compares two elements with the spaceship operator, <=>. Here, as pairs of arrays are being compared, it is the method Array#<=> that is used. See especially the third paragraph of that doc.

Finding the first combination of two integers in an array whose latter element appears the earliest and sum matches a given value

I have array and sum_of_two:
array = [10, 5, 1, 9, 7, 8, 2, 4, 6, 9, 3, 2, 1, 4, 8, 7, 5]
sum_of_two = 10
I'm trying to find the combination of two integers in array whose latter element of the two appears the earliest among those of such combinations whose sum equals sum_of_two. For example, both [5, 5] and [1, 9] are candidates for such combinations, but 9 of [1, 9] (which appears later than 1 in array) appears earlier than the second 5 of [5, 5] (which is the last element in array). So I would like to return [1, 9].
I tried using combination and find:
array.combination(2).find{|x,y| x + y == sum_of_two} #=> [5, 5]
However, it returns a combination of the first integer in the array, 5 , and another integer further along the array, also 5.
If I use find_all instead of find, I get all combinations of two integers that add up to sum_of_two:
array.combination(2).find_all{|x,y| x + y == sum_of_two}
#=> [[5, 5], [1, 9], [1, 9], [9, 1], [7, 3], [8, 2], [8, 2], [2, 8], [4, 6], [6, 4], [9, 1], [3, 7], [2, 8]]
But then I'm not sure how to get the first one.
I would use Set (which would be a bit more efficient than using Array#include?) and do something like this:
array = [10, 5, 1, 9, 7, 8, 2, 4, 6, 9, 3, 2, 1, 4, 8, 7, 5]
sum_of_two = 10
require 'set'
array.each_with_object(Set.new) do |element, set|
if set.include?(sum_of_two - element)
break [sum_of_two - element, element]
else
set << element
end
end
#=> [1, 9]
x = array.find.with_index{|e, i| array.first(i).include?(sum_of_two - e)}
[sum_of_two - x, x] # => [1, 9]
Array#combination(n) does not give the elements in the order you want, so you must build the pairs yourself. It's easy if you begin from the second index. A O(n) lazy implementation, and let's call the input xs:
pairs = (1...xs.size).lazy.flat_map { |j| (0...j).lazy.map { |i| [xs[i], xs[j]] } }
first_matching_pair = pairs.detect { |i, j| i + j == 10 }
#=> [1, 9]

Combine arrays in Ruby

I have two arrays as in the listing given below.
a = [1, 2, 3, 4, 5]
b = [1.360, 0.085, -1.190, -0.340, 3.698]
I need to merge the values at each index so that I get a structure resembling Resultant Array.
Resultant Array = [[1, 1.360], [2, 0.085], [3, -1.190], [4, -0.340], [5, 3.698]]
How do I go about doing it?
You can use Array#zip
a.zip(b)
# => [[1, 1.36], [2, 0.085], [3, -1.19], [4, -0.34], [5, 3.698]]
a = [1, 2, 3, 4, 5]
b = [1.360, 0.085, -1.190, -0.340, 3.698]
You can also try an alternative:
[a,b].transpose
Note: Use this when length of your array is same
You can do:
a.zip(b) #=> [[1,1.360],[2,0.085],[3,-1.190],[4,-0.340],[5,3.698]]
I didn't try it.
Source: apidoc.com

How to transpose an array in Python 3?

I've been scanning the forums and haven't found an answer yet that I can apply to my situation. I need to be able to take an n by n array and transpose it in Python-3. The example given is that I have this list input into the function:
[[4, 2, 1], ["a", "a", "a"], [-1, -2, -3]] and it needs to be transposed to read:
[[4, 'a', -1], [2, 'a', -2], [1, 'a', -3]] So basically reading vertically instead of horizontally.
I CANNOT use things like zip or numpy, I have to make my own function.
Been rattling my brain at this for two nights and it's a huge headache. If anyone could help and then provide an explanation so I can learn it, I'd be grateful.
Edit:
I should add for reference sake that the argument variable is M. The function we're supposed to write is trans(M):
A one-liner:
def trans(M):
return [[M[j][i] for j in range(len(M))] for i in range(len(M[0]))]
result:
>>> M = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> trans(M)
[[1, 4, 7], [2, 5, 8], [3, 6, 9]
# or for a non-square matrix:
>>> N = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
>>> trans(N)
[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]
Additional Note: If you look up the tutorial on list comprehension, one of the examples is in fact transposition of a matrix array.
A variant that should work for matrices with irregular row lengths:
m=[[3, 2, 1],
[0, 1],
[2, 1, 0]]
m_T = [ [row[c] for row in m if c < len(row)] for c in range(0, max([len(row) for row in m])) ]
Here is an in place solution that works for square matrices:
def trans(M):
n = len(M)
for i in range(n - 1):
for j in range(i + 1, n):
M[i][j], M[j][i] = M[j][i], M[i][j]
Example Usage:
def print_matrix(M):
for row in M:
for ele in row:
print(ele, end='\t')
print()
M = [[4, 2, 1], ["a", "a", "a"], [-1, -2, -3]]
print('Original Matrix:')
print_matrix(M)
trans(M)
print('Transposed Matrix:')
print_matrix(M)
Output:
Original Matrix:
4 2 1
a a a
-1 -2 -3
Transposed Matrix:
4 a -1
2 a -2
1 a -3
y=([1,2], [3,4], [5,6])
transpose=[[row[i] for row in y] for i in range(len(y[0]))]
the output is
[[1, 3, 5], [2, 4, 6]]
You can also use the function in numpy to transpose - if you need the answer as a list it is straightforward to convert back using tolist:
from numpy import transpose
M = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transpose(M).tolist()
the output is
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Haven't timed it (no time!) but I strongly suspect this will be a lot faster than iterators for large arrays, especially if you don't need to convert back to a list.

Resources