Get the element's order map of an array - arrays

For example:
if input is {2, 8, 5, 6, 10},
the output will be {1, 4, 2, 3, 5} .
Since 2 in the minimum in the source array, it's order is 1. 10 is maximum in the array, so it's order is the length of input array.
It's easy to sort the input array first and then find the index of each element. But I want to know if there is a more optimized way.
It doesn't matter whether the order is zero-based or one-based.

Replace each element by a pair: (element, index). {2,8,5,6,10} becomes {(2,1),(8,2),(5,3),(6,4),(10,5)}. Let this array be A.
Sort A. You now have {(2,1),(5,3),(6,4),(8,2),(10,5)}
For each i from 1 to length(A) do B[A[i].second_element] <- i. In your case:
B[1] <- 1
B[3] <- 2
B[4] <- 3
B[2] <- 4
B[5] <- 5
Now B={1,4,2,3,5}. PROFIT!!!

Related

How to understand the index of np.array

I am learning python numpy.array and am confused about how the index works. Let's see I have the following 3x4 2D array:
A = np.array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9,10,11,12]])
If I want to extract the 1 from this array, I need to input the index of that number, which is A[0,0]
Out of curiosity I also tried the following
B = A[[0,0]]
C = A[[0],[0]]
B turns out to be a 2x4 2D array:
array([[1, 2, 3, 4],
[1, 2, 3, 4]])
C turns out to be a 1D array of 1 element:
array([1])
I am wondering how indexing of B and C works and why I obtain those arrays?
In B, you are only giving one index for a 2 dimensional array which is [0,0]. So it will return the element in the first dimension of the index given (0 and 0 here).
So, for the first index (which is 0) it will return the first element in the first dimension which is [1,2,3,4] and it will go for the next index given which is again 0, so it will print two [1,2,3,4] as you have got.
Next in the C, you have given 2 indices for a 2 dimensional array which are [0] and [0]. So it will go through the first dimension for the index 0 which is [1,2,3,4] and in that element it will return the 0th position which is [1] as you have got.
For better understanding, let's see another case A[[0,1],2].
Here, we have given 2 indices for a 2 dimensional array which are [0,1] and 2. So, we get the elements which are in the index [0,2] and next with [1,2].Th output will be [3,7].
The thing is it will iterate through all possible combinations of indices given and return those values in those indices.

Divide array into equal sized subarrays

we are given an array of size n (n is even), we have to divide it into two equal-sized subarrays array1 and array2, sized n/2 each such that product of all the numbers of array1 equals to the product of all the numbers in array2.
Given array:
arr = [2, 4, 5, 12, 15, 18]
solution:
array2 = [4, 5, 18]
array1 = [2, 12, 15]
Explanation:
product of all elements in array1 is 360
product of all elements in array2 is 360.
This problem might be soved using dynamic programming. You need to get subset of size n/2 with product equal to p = sqrt(overall_product). Note that there is no solution when overall_product is not exact square.
Recursion might look like
solution(p, n/2, arr) = choose valid solution from
solution(p / arr[i], n/2-1, arr without arr[i])
return true for arguments (1,0,...)
use memoization or table to solve problem with merely large n values.

selecting 2D sub-slice of a 2D-slice using ranges in go

I'm getting a surprising result when selecting a 2D sub-slice of a slice.
Consider the following 2D int array
a := [][]int{
{0, 1, 2, 3},
{1, 2, 3, 4},
{2, 3, 4, 5},
{3, 4, 5, 6},
}
To select the top left 3x3 2D slice using ranges I would use
b := a[0:2][0:2]
I would expect the result to be
[[0 1 2] [1 2 3] [2 3 4]]
however the second index range doesn't seem to have any effect, and returns the following instead:
[[0 1 2 3] [1 2 3 4] [2 3 4 5]]
What am I missing? Can you simply not select a sub-slice like this where the dimension > 1 ?
You can't do what you want in a single step. Slices and arrays are not 2-dimensional, they are just composed to form a multi-dimensional object. See How is two dimensional array's memory representation
So with a slice expression, you just get a slice that will hold a subset of the "full" rows, and its type will be the same: [][]int. If you slice it again, you just slicing the slice of rows again.
Also note that the higher index in a slice expression is exclusive, so a[0:2] will only have 2 rows, so you should use a[0:3] or simply a[:3] instead.
To get what you want, you have to slice the rows individually like this:
b := a[0:3]
for i := range b {
b[i] = b[i][0:3]
}
fmt.Println(b)
This will output (try it on the Go Playground):
[[0 1 2] [1 2 3] [2 3 4]]
Or shorter:
b := a[:3]
for i, bi := range b {
b[i] = bi[:3]
}

GoLang: How to delete an element from a 2D slice?

I've recently been messing around with Go and I wanted to see how it would be to delete an element from a two-dimensional slice.
For deleting an element from a one-dimensional slice, I can successfully use:
data = append(data[:i], data[i+1:]...)
However, with a two-dimensional slice, using:
data = append(data[i][:j], data[i][j+1:]...)
throws the error:
cannot use append(data[i][:j], data[i][j+1:]...) (type []string) as type [][]string in assignment
Would tackling this require a different approach?
A 2D slice in Go is nothing more than a slice of slices. So if you want to remove an element from this 2D slice, effectively you still only have to remove an element from a slice (which is an element of another slice).
There is nothing more involved. Only thing you have to look out is that when you remove an element from the row-slice, the result will only be the "new" value of the row (an element) of the "outer" slice, and not the 2D slice itself. So you have to assign the result to an element of the outer slice, to the row whose element you just removed:
// Remove element at the ith row and jth column:
s[i] = append(s[i][:j], s[i][j+1:]...)
Note that this is identical to the simple "removal from slice" if we substitute s[i] with a (not surprisingly, because s[i] denotes the "row-slice" whose jth element we're removing):
a = append(a[:j], a[j+1:]...)
See this complete example:
s := [][]int{
{0, 1, 2, 3},
{4, 5, 6, 7},
{8, 9, 10, 11},
}
fmt.Println(s)
// Delete element s[1][2] (which is 6)
i, j := 1, 2
s[i] = append(s[i][:j], s[i][j+1:]...)
fmt.Println(s)
Output (try it on the Go Playground):
[[0 1 2 3] [4 5 6 7] [8 9 10 11]]
[[0 1 2 3] [4 5 7] [8 9 10 11]]
Here is one of the possible approaches Go Playground.
b := [][]int{
[]int{1, 2, 3, 4},
[]int{5, 6, 7, 8},
[]int{9, 0, -1, -2},
[]int{-3, -4, -5, -6},
}
print2D(b)
i, j := 2, 2
tmp := append(b[i][:j], b[i][j+1:]...)
c := append(b[:i], tmp)
c = append(c, b[i+1:]...)
print2D(c)
Basically I am extracting the i-th row, remove the element from it append(b[i][:j], b[i][j+1:]...) and then put this row between the rows.
If someone would tell how to append many elements, it would look even nicer.

Array sorting using presorted ranking

I'm building a decision tree algorithm. The sorting is very expensive in this algorithm because for every split I need to sort each column. So at the beginning - even before tree construction I'm presorting variables - I'm creating a matrix so for each column in the matrix I save its ranking. Then when I want to sort the variable in some split I don't actually sort it but use the presorted ranking array. The problem is that I don't know how to do it in a space efficient manner.
A naive solution of this is below. This is only for 1 variabe (v) and 1 split (split_ind).
import numpy as np
v = np.array([60,70,50,10,20,0,90,80,30,40])
sortperm = v.argsort() #1 sortperm = array([5, 3, 4, 8, 9, 2, 0, 1, 7, 6])
rankperm = sortperm.argsort() #2 rankperm = array([6, 7, 5, 1, 2, 0, 9, 8, 3, 4])
split_ind = np.array([3,6,4,8,9]) # this is my split (random)
# split v and sortperm
v_split = v[split_ind] # v_split = array([10, 90, 20, 30, 40])
rankperm_split = rankperm[split_ind] # rankperm_split = array([1, 9, 2, 3, 4])
vsorted_dummy = np.ones(10)*-1 #3 allocate "empty" array[N]
vsorted_dummy[rankperm_split] = v_split
vsorted = vsorted_dummy[vsorted_dummy!=-1] # vsorted = array([ 10., 20., 30., 40., 90.])
Basically I have 2 questions:
Is double sorting necessary to create ranking array? (#1 and #2)
In the line #3 I'm allocating array[N]. This is very inefficent in terms of space because even if split size n << N I have to allocate whole array. The problem here is how to calculate rankperm_split. In the example original rankperm_split = [1,9,2,3,4] while it should be really [1,5,2,3,4]. This problem can be reformulated so that I want to create a "dense" integer array that has maximum gap of 1 and it keeps the ranking of the array intact.
UPDATE
I think that second point is the key here. This problem can be redefined as
A[N] - array of size N
B[N] - array of size N
I want to transform array A to array B so that:
Ranking of the elements stays the same (for each pair i,j if A[i] < A[j] then B[i] < B[j]
Array B has only elements from 1 to N where each element is unique.
A few examples of this transformation:
[3,4,5] => [1,2,3]
[30,40,50] => [1,2,3]
[30,50,40] => [1,3,2]
[3,4,50] => [1,2,3]
A naive implementation (with sorting) can be defined like this (in Python)
def remap(a):
a_ = sorted(a)
b = [a_.index(e)+1 for e in a]
return b

Resources