How to reduce number of move operations in an array? - arrays

Say I have an array of numbers, e.g. [0, 1, 2, 3, 4, 5] and I want to end up with an array, e.g. [2, 1, 4, 0, 5, 3]. At my disposal, I have a single method that I can use:
move(fromIndex, toIndex)
Thus, to achieve my desired array, I could call the method a number of times:
move(2, 0); // [2, 0, 1, 3, 4, 5]
move(1, 2); // [2, 1, 0, 3, 4, 5] (swapped 2 with 0)
move(4, 2); // [2, 1, 4, 0, 3, 5]
move(3, 4); // [2, 1, 4, 3, 0, 5] (swapped 4 with 0)
move(4, 3); // [2, 1, 4, 0, 3, 5] (swapped 0 with 3)
move(5, 4); // [2, 1, 4, 0, 5, 3] (swapped 5 with 3)
Thus, I also have a list of move() operations to achieve my desired result. The list of move() operations can possibly be reduced in size by changing the order and the indexes, to end up with the same result.
Is there an algorithm that I can use on my list of move() operations to reduce the number of operations to a minimum?

We can create a graph with an element pointing towards the number it needs to be swapped with to get to the desired position. Hence we will get multiple graphs with possible cycles. In your particular case,we will get
2->0->3->5->4->2 (first and last elements denote a cycle)
This means that 2 wants to be swapped with 0 to get to the desired position. Similarly,0 wants to be swapped with 3 to get to the desired position. Notice that 1 does not want to be swapped.
Now, we can swap two adjacent elements of the graph to reduce the graph size by 1. Say we swap 3 and 5 so now the arr = [0,1,2,5,4,3]. Now 3 is in desired state so we can remove it from graph
2->0->5->4->2
We need to repeat this process (m-1) times to remove the graph completely. Here m represents the number of edges of the graph. We can have multiple disconnected graphs or graphs without cycles. We need to make sure that we are swapping elements from the same graph. The final answer would be the sum of all steps (that is m-1 for each component) of the graph.

Related

Is it possible to find all possible combinations of a fixed amount of integers that add up to a specific number?

It would need to find every combination of integers that the array could be, E.G. an array of length 4 and a number of 10:
[10, 0, 0, 0] [9, 1, 0, 0]
[8, 2, 0, 0]
...
[3, 2, 5, 0]
It would also need each combination to be specific in the way that [8, 2, 0, 0] and [0, 8, 2, 0] would exist as seperate combinations.
I have tried using for in range loops; 4 for in range loops inside eachother printing every possible combination and then checking if the total of the 4 integers of add up to the number, however this has an incredibly exponential execution time and I was wondering if there was any way to do it without checking every possible value of the 4 integers.
Example of what I've tried:
for a in range(10):
for b in range(10):
for c in range(10):
for d in range(10):
if (a+b+c+d == num):

How would you split a numpy array where the elements give the partition size?

For an numpy 1d array such as:
In [1]: A = np.array([2,5,1,3,9,0,7,4,1,2,0,11])
In [2]: A
Out[2]: array([2,5,1,3,9,0,7,4,1,2,0,11])
I need to split the array by using the values as a sub-array length.
For the example array:
The first index has a value of 2, so I need the first split to occur at index 0 + 2, so it would result in ([2,5,1]).
Skip to index 3 (since indices 0-2 were gobbled up in step 1).
The value at index 3 = 3, so the second split would occur at index 3 + 3, and result in ([3,9,0,7]).
Skip to index 7
The value at index 7 = 4, so the third and final split would occur at index 7 + 4, and result in ([4,1,2,0,11])
I'm using this simple array as an example, because I think it will help in my actual use case, which is reading data from binary files (either as bytes or unsigned shorts). I'm guessing that numpy will be the fastest way to do it, but I could also use struct/bytearray/lists or whatever would be best.
I hope this makes sense. I had a hard time trying to figure out how best to word the question.
Here is an approach using standard python lists and a while loop:
def custom_partition(arr):
partitions = []
i = 0
while i < len(arr):
pariton_size = arr[i]
next_i = i + pariton_size + 1
partitions.append(arr[i:next_i])
i = next_i
return partitions
a = [2, 5, 1, 3, 9, 0, 7, 4, 1, 2, 0, 11]
b = custom_partition(a)
print(b)
Output:
[[2, 5, 1], [3, 9, 0, 7], [4, 1, 2, 0, 11]]

How to find indexes of max n values in array

I have an array [0, 0, 10, 0, 3, 1]. I want to have the indexes of max three elements from this array, which would be: [2, 4, 5].
How do I do it without finding max element, delete it (make 0), then find next one, delete it and at last find third one? I can't sort this array, I need index from the current position.
a = [0, 0, 10, 0, 3, 1]
a.each_index.max_by(3){|i| a[i]} # => [2, 4, 5]
or
[0, 0, 10, 0, 3, 1].each_with_index.max(3).map(&:last) # => [2, 4, 5]
arr = [1, 3, 2, 4]
n = 2
p arr.each_with_index.sort.map(&:last).last(n).reverse
#=> [3,1]
How does it work ?
arr.each_with_index.sort
Will return an array of arrays. Each of the arrays is constructed as follows [value, index] and they are sorted based on value. In our example it would return [[1, 0], [2, 2], [3, 1], [4, 3]].
arr.map(&:last)
Will loop through all of those arrays and take the last value of the array (the index) and return an array of those indexes. In our example it will return [0, 2, 1, 3]. Now we have an array of indexes sorted in ascending order so the first value is the minimum and the last value is the maximum.
arr.last(n)
Returns an array containing last n values of an array. Since the array is in ascending order the max n values are the last n values.
arr.reverse
Reverts an array. It is optional. If you want to have the max in first position of your array and the Nth maximum value at the end then use reverse, else do not use it.

Accessing Values In Matrix (Haskell Newbie)

i am trying to do the equvilant of this in haskell bascially
for (int i = 0; i < city_Permutation_Route.length - 1; i++) {
route_Distance = route_Distance + city_Distance_Matrix[city_Permutation_Route[i]][city_Permutation_Route[i + 1]];
}
there i get the weight of each route, compare it against each of the others so that i print out the route with the lowest weighted route as follows
Route Weight = 453.4
Route = 0,1,2,3,4,5,6,7,8
i have functions to get the total route and all the other data but do not understand how to get values from the matrix
Question: How do i do this in haskell
i want to be able to get the values from my distance matrix using the permutation values as the index to it
Given a permutation, for example [3, 2, 7, 5, 4, 6, 0, 1] you can compute all of the legs by zipping it with its own tail.
zip [3, 2, 7, 5, 4, 6, 0, 1]
(tail [3, 2, 7, 5, 4, 6, 0, 1])
zip [3, 2, 7, 5, 4, 6, 0, 1]
[2, 7, 5, 4, 6, 0, 1]
[(3,2),(2,7),(7,5),(5,4),(4,6),(6,0),(0,1)]
These are the indexes into the distance matrix for the cost of traveling between two points. If we look these up in the city_Distance_Matrix using the list indexing function !! we get the cost for each leg
map (\(c0, c1) -> city_Distance_Matrix !! c0 !! c1)
[(3,2),(2,7),(7,5),(5,4),(4,6),(6,0),(0,1)]
[97.4, 71.6, 111.0,138.0,85.2 ,86.3 ,129.0]
If we total these, we get the total cost for traveling the legs of this permutation.
sum [97.4, 71.6, 111.0,138.0,85.2 ,86.3 ,129.0] = 718.5
Putting this all together, we can define a function that computes the total length of all the legs of a permutation of the cities. We can simplify the function by using zipWith which is a combination of zip and map.
totalLength :: [Int] -> Double
totalLength cities = sum $ zipWith (\c0 c1 -> city_Distance_Matrix !! c0 !! c1) cities (tail cities)
You should be able to use this to find the permutation whose totalLength is minimal.

Calculating repetitive permutations of an array

Let's say I have an array with 5 elements. How can I calculate all possible repetitive permutations of this array in C.
Edit: What I mean is creating all possible arrays by using that 5 number. So the positon matters.
Example:
array = [1,2,3,4,5]
[1,1,1,1,1]
[1,1,1,1,2]
[1,1,1,2,3]
.
.
A common way to generate combinations or permutations is to use recursion: enumerate each of the possibilities for the first element, and prepend those to each of the combinations or permutations for the same set reduced by one element. So, if we say that you're looking for the number of permutations of n things taken k at a time and we use the notation perms(n, k), you get:
perms(5,5) = {
[1, perms(5,4)]
[2, perms(5,4)]
[3, perms(5,4)]
[4, perms(5,4)]
[5, perms(5,4)]
}
Likewise, for perms(5,4) you get:
perms(5,4) = {
[1, perms(5,3)]
[2, perms(5,3)]
[3, perms(5,3)]
[4, perms(5,3)]
[5, perms(5,3)]
}
So part of perms(5,5) looks like:
[1, 1, perms(5,3)]
[1, 2, perms(5,3)]
[1, 3, perms(5,3)]
[1, 4, perms(5,3)]
[1, 5, perms(5,3)]
[2, 1, perms(5,3)]
[2, 2, perms(5,3)]
...
Defining perms(n, k) is easy. As for any recursive definition, you need two things: a base case and a recursion step. The base case is where k = 0: perms(n, 0) is an empty array, []. For the recursive step, you generate elements by prepending each of the possible values in your set to all of the elements of perms(n, k-1).
If I get your question correctly, you need to generate all 5 digit numbers with digits 1,2,3,4 and 5. So there is a simple solution - generate all numbers base five up to 44444 and then map the 0 to 1, 1 to 2 and so on. Add leading zeros where needed - so 10 becomes 00010 or [1,1,1,2,1].
NOTE: you don't actually have to generate the numbers themselves, you may just iterate the numbers up to 5**5(excluding) and for each of them find the corresponing sequence by getting it's digits base 5.
int increment(size_t *dst, size_t len, size_t base) {
if (len == 0) return 0;
if (dst[len-1] != base-1) {
++dst[len-1];
return 1;
} else {
dst[len-1] = 0;
return increment(dst, len-1, base);
}
}
Armed with this function you can iterate over all repetitive permutations of (0 ... 4) starting from {0, 0, 0, 0, 0}. The function will return 0 when it runs out of repetitive permutations.
Then for each repetitive permutation in turn, use the contents as indexes into your array so as to get a repetitive permutation of the array rather than of (0 ... 4).
In your given example, each position could be occupied by either 1, 2, 3, 4, 5. As there are 5 positions, the total number of possibilities = 5 * 5 * 5 * 5 * 5 = 5 ^ 5 = 3125. In general, it would be N ^ N. (where ^ is the exponentiation operator).
To generate these possibilities, in each of the positions, put the numbers 1, 2, 3, 4, 5, one by one, and increment starting from the last position, similar to a 5 digit counter.
Hence, start with 11111. Increment the last position to get 11112 ... until 11115.
Then wrap back to 1, and increment the next digit 11121 continue with 11122 ... 11125, etc. Repeat this till you reach the first position, and you would end at 55555.

Resources