Append new variables to IDL for loop array - arrays

If I have the following array:
x = double([1, 1, 1, 10, 1, 1, 50, 1, 1, 1 ])
I want to do the following:
Group the array into groups of 5 which will each be evaluated separately.
Identify the MAX value each of the groups of the array
Remove that MAX value and put it into another array.
Finally, I want to print the updated array x without the MAX values, and the new array containing the MAX values.
How can I do this? I am new to IDL and have had no formal training in coding.
I understand that I can write the code to group and find the max values this way:
FOR i = 1, (n_elements(x)-4) do begin
print, "MAX of array", MAX( MAX(x[i-1:1+3])
ENDFOR
However, how do I implement all of what I specified above? I know I have to create an empty array that will append the values found by the for loop, but I don't know how to do that.
Thanks

I changed your x to have unique elements to make sure I wasn't fooling myself. It this, the number of elements of x must be divisible by group_size:
x = double([1, 2, 3, 10, 4, 5, 50, 6, 7, 8])
group_size = 5
maxes = max(reform(x, group_size, n_elements(x) / group_size), ind, dimension=1)
all = bytarr(n_elements(x))
all[ind] = 1
x_without_maxes = x[where(all eq 0)]
print, maxes
print, x_without_maxes

Lists are good for this, because they allow you to pop out values at specific indices, rather than rewriting the whole array again. You might try something like the following. I've used a while loop here, rather than a for loop, because it makes it a little easier in this case.
x = List(1, 1, 1, 10, 1, 1, 50, 1, 1, 1)
maxValues = List()
pos = 4
while (pos le x.length) do begin
maxValues.add, max(x[pos-4:pos].toArray(), iMax)
x.Remove, iMax+pos-4
pos += 5-1
endwhile
print, "Max Values : ", maxValues.toArray()
print, "Remaining Values : ", x.toArray()
This allows you to do what you want I think. At the end, you have a List object (which can easily be converted to an array) with the max values for each group of 5, and another containing the remaining values.
Also, please tag this as idl-programming-language rather than idl. They are two different tags.

Related

Most computationally efficient way to batch alter values in each array of a 2d array, based on conditions for particular values by indices

Say that I have a batch of arrays, and I would like to alter them based on conditions of particular values located by indices.
For example, say that I would like to increase and decrease particular values if the difference between those values are less than two.
For a single 1D array it can be done like this
import numpy as np
single2 = np.array([8, 8, 9, 10])
if abs(single2[1]-single2[2])<2:
single2[1] = single2[1] - 1
single2[2] = single2[2] + 1
single2
array([ 8, 7, 10, 10])
But I do not know how to do it for batch of arrays. This is my initial attempt
import numpy as np
single1 = np.array([6, 0, 3, 7])
single2 = np.array([8, 8, 9, 10])
single3 = np.array([2, 15, 15, 20])
batch = np.array([
np.copy(single1),
np.copy(single2),
np.copy(single3),
])
if abs(batch[:,1]-batch[:,2])<2:
batch[:,1] = batch[:,1] - 1
batch[:,2] = batch[:,2] + 1
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Looking at np.any and np.all, they are used to create an array of booleans values, and I am not sure how they could be used in the code snippet above.
My second attempt uses np.where, using the method described here for comparing particular values of a batch of arrays by creating new versions of the arrays with values added to the front/back of the arrays.
https://stackoverflow.com/a/71297663/3259896
In the case of the example, I am comparing values that are right next to each other, so I created copies that shift the arrays forwards and backwards by 1. I also use only the particular slice of the array that I am comparing, since the other numbers would also be used in the comparison in np.where.
batch_ap = np.concatenate(
(batch[:, 1:2+1], np.repeat(-999, 3).reshape(3,1)),
axis=1
)
batch_pr = np.concatenate(
(np.repeat(-999, 3).reshape(3,1), batch[:, 1:2+1]),
axis=1
)
Finally, I do the comparisons, and adjust the values
batch[:, 1:2+1] = np.where(
abs(batch_ap[:,1:]-batch_ap[:,:-1])<2,
batch[:, 1:2+1]-1,
batch[:, 1:2+1]
)
batch[:, 1:2+1] = np.where(
abs(batch_pr[:,1:]-batch_pr[:,:-1])<2,
batch[:, 1:2+1]+1,
batch[:, 1:2+1]
)
print(batch)
[[ 6 0 3 7]
[ 8 7 10 10]
[ 2 14 16 20]]
Though I am not sure if this is the most computationally efficient nor programmatically elegant method for this task. Seems like a lot of operations and code for the task, but I do not have a strong enough mastery of numpy to be certain about this.
This works
mask = abs(batch[:,1]-batch[:,2])<2
batch[mask,1] -= 1
batch[mask,2] += 1

Defining pointers vs accessing values in an Array in Ruby

Let's say I'm passing the following array to a method:
input = [1,9,10,3,2,3,11,0,99,30,40,50]
I need to work with sets of 4 numbers from that array as follows:
OPCODE = input[0] # first of the 4 numbers
pos1_pointer = will always be opcode position + 1 position to the right
pos2_pointer = will always be opcode position + 2 positions to the right
output = will always be opcode position + 3 positions to the right
pos1 and pos2 numbers are actually pointers to the actual values (eg. pos1_pointer = 9 (one position from opcode), actual value 30 (position 9 in the array).
How do I define the pointer based on where the OPCODE is sitting?
I've tried:
pos1_pointer = input[input[opcode] + 1] # points to 40 which is wrong (because opcode = input[0] which is 1, and it sums 9 positions to that, position 10 being value 40)
pos1_pointer = input[opcode + 1] # is also wrong because it assigns a value of 2 to it (it sums 1 to the value of opcode which is 1)
Use Iterators Rather Than Indexing
In Ruby, if you want to work with subsets of an array, there's a method for that! Array#each_slice can be used to feed your slices directly into a method, or to deconstruct them further. For example:
input = [1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50]
input.each_slice(4) do |slice|
opcode, pos1, pos2, output = slice
pp slice
end
You could replace pp slice with a call to your method(s) of choice, passing in either the whole slice or the deconstructed values as positional or keyword arguments. Let Ruby manage the indexing so you can focus on more important things.
Why not try this. The first argument, arr, is the array. The second argument, i, is the index at which you want to start from.
The method bellow will take the array and the index and then return an array starting from the whichever index, in this case 0, and then return everything between index 0 and index 0+3.
Double dots x..y means go from range x up to y. Triple dot x...y means start from x and go up to BUT exclude y.
def four(arr, i)
return arr[i..i+3]
end
print four([1,9,10,3,2,3,11,0,99,30,40,50],0)
# input = [1,9,10,3,2,3,11,0,99,30,40,50]
# output = [1,9,10,3]

Find an algorithm to sort an array given its status after sorting

Let A be an array with n elements. A is not sorted, nonetheless, after sorting the array, the difference between any two adjacent elements would be either k1, k2 or k3.
It should be noted that k1, k2 and k3 are not given, and all of them are natural!
For example, given the array:
A = { 25, 7, 5, 9, 32, 23, 14, 21}
After sorting the array, we would get -
A = { 5, 7, 9, 14, 21, 23, 25, 32}
The difference between the first pair (5, 7) is 2; so k1=2, the difference between the third pair (9,14) is 5, so k2=5, whereas the difference between the fourth pair (14, 21) is 7, so k3=7. The difference between other adjacent pairs is also 2, 5 and 7.
The algorithm for sorting the array should be as best as possible (obviously below O(nlogn)).
I managed to answer a similar question where the difference between any two adjacent elements was either k, 2k or 3k, where k is real. But I couldn't find an appropriate algorithm following a similar method, by finding k, dividing by it and doing bucket sort.
By finding the minimum and second minimum we can find one of the k's. But k could be n2 — so finding the maximum does not help either... I am really lost!
Disclaimer: This question has been asked before, but no answer was given to the problem, and the question was not easy to understand.
Here is a O(n) that only doesn't look efficient.
The idea is simple. Given the minimum element and a list of values for k, you construct the biggest sorted set with the values of k that you already have found, find the smallest missing thing not in the set, and find a new value of k. If there are K values of k, this operation is O((1+K) * n).
Repeating this K times is therefore O((1+K)^2 * n).
In our case K is constant, so we get O(n).
Here it is in Python.
def special_sort (array):
# special cases first.
if 0 == len(array):
return array
elif 1 == len(array):
return array
elif 2 == len(array):
return [min(array), max(array)]
min_value = min(array)
values_of_k = []
leftovers = array
while len(leftovers):
values_of_k = sorted(values_of_k)
values = set(array)
sorted_array = [min_value]
values.remove(min_value)
found = True
while found:
found = False
for k in values_of_k:
if sorted_array[-1] + k in values:
found = True
sorted_array.append(sorted_array[-1] + k)
values.remove(sorted_array[-1])
break
leftovers = list(values)
if 0 == len(leftovers):
return sorted_array
else:
first_missing = min(leftovers)
# Find the first element of the array less than that.
i = -1
while i+1 < len(sorted_array) and sorted_array[i+1] < first_missing:
i = i+1
values_of_k.append(first_missing - sorted_array[i])
print(special_sort([25, 7, 5, 9, 32, 23, 14, 21]))

Swift For loop Enumeration in Sort differs

Im trying to manual sort on the below array.
The issue here is, the result varies while reading the item from the "for-loop enumuration" (noted as //(2)) verses reading it as a subscript (noted as //(1)). It could be a minor issue hiding behind my eye. Appreciate your time.
var mySortArray : Array<Int> = []
mySortArray = [1,5,3,3,21,11,2]
for (itemX,X) in mySortArray.enumerated() {
for (itemY,Y) in mySortArray.enumerated() {
// if mySortArray[itemX] < mySortArray[itemY] // (1)
if X < Y // (2)
{
//Swap the position of item in the array
mySortArray.swapAt(itemX, itemY)
}
}
}
print(mySortArray)
// Prints [1, 2, 3, 3, 5, 11, 21] ( for condition // (1))
// Prints [2, 1, 3, 5, 11, 3, 21] ( for condition // (2))
mySortArray = [1,5,3,3,21,11,2]
print("Actual Sort Order : \(mySortArray.sorted())")
// Prints Actual Sort Order : [1, 2, 3, 3, 5, 11, 21]
The problem here is that the function .enumerated() returns a new sequence and iterates that. Think of it as a new array.
So, you are working with 3 different arrays here.
You have an unsorted array that you want to fix. Lets call this the w ("working array") and then you have you array x and array y.
So, w is [1,5,3,3,21,11,2], x and y are effectively the same as w at the beginning.
Now you get your first two values that need to swap...
valueX is at index 1 of x (5). valueY is at index 2 of y (3).
And you swap them... in w.
So now w is [1,3,5,3,21,11,2] but x and y are unchanged.
So now you indexes are being thrown off. You are comparing items in x with items in y and then swapping them in we which is completely different.
You need to work with one array the whole time.
Of course... there is also the issue that your function is currently very slow. O(n^2) and there are much more efficient ways of sorting.
If you are doing this as an exercise in learning how to write sort algorithms then keep going. If not you should really be using the .sort() function.
Really what you want to be doing is not using .enumerated() at all. Just use ints to get (and swap) values in w.
i.e. something like
for indexX in 0..<w.count {
for indexY in indexX..<w.count {
// do some comparison stuff.
// do some swapping stuff.
}
}

Save integers into array given by first integer

I need to know, how to save integers from stdin into array, given by first integer in line... Ehm... hope you understand. I will give you an example.
On stdin I have:
0 : [ 1, 2, 3 ]
5 : [ 10, 11, 12, 13]
6 : [ 2, 4, 9 ]
0 : [ 4, 9, 8 ]
5 : [ 9, 6, 7 ]
5 : [ 1 ]
And I need save these integers to the arrays like this:
0={1, 2, 3, 4, 9, 8}
5={10, 11, 12, 13, 9, 6, 7, 1}
6={2, 4, 9}
I absolutely don't how to do it. There is a problem, that the number of arrays(in this case - 0, 5, 6 - so 3 arrays ) can be very high and I need to work effectively with memory...So I guess i will need something like malloc and free to solve this problem, or am I wrong? The names of arrays (0, 5, 6) can be changed. Number of integers in brackets has no maximum limit.
Thank you for any help.
I go with the assumption, this is homework, and I go with the assumption, this isn't your first homework to do, so I won't present you a solution but instead some tips that would help you to solve it yourself.
Given the input line
5 : [ 10, 11, 12, 13]
I will call "5" the "array name" and 10, 11, 12 and 13 the values to add.
You should implement some system to map array names to indices. A trivial approach would be like this:
.
size_t num_arrays;
size_t * array_names;
Here, in your example input, num_arrays will end up being 3 with array_names[3] = { 0, 5, 6}. If you find a new array name, realloc and add the new array name. Also you need the actual arrays for the values:
int * * array;
you need to realloc array for each new array name (like you realloc array_names). array[0] will represent array array_names[0] here array 0, array[1] will represent array array_names[1] here array 5 and array[2] will represent array array_names[2] here array 6.
To access an array, find it's index like so:
size_t index;
for (size_t index = 0; index < num_arrays && array_names[index] != search; ++index) ;
The second step is easy. Once you figured out, you need to use array[index] to add elemens, realloc that one (array[index] = realloc(array[index], new size)) and add elements there array[index][i+old_size] = new_value[i].
Obviously, you need to keep track of the number of elements in your separate arrays as well ;)
Hint: If searching for the array names take too long, you will have to replace that trivial mapping part by some more sophisticated data structure, like a hash map or a binary search tree. The rest of the concept may stay more or less the same.
Should you have problems to parse the input lines, I suggest, you open a new question specific on this parsing part.
In algorithmic terms, you need map (associative array) from ints to arrays. This is solved long ago in most higher level languages.
If you have to implement it manually, you have a few options:
simple "master" array where you store your 0, 5, 6, 1000000 and then map them to indices 0, 1, 2, 3 by doing search in for each time you have to access it (it's too time consuming when ;
hash table: write simple hash function to map 0, 5, 6, 1000000 (they're called keys) to values less than 1000, allocate array of 1000 elements and then make "master" array structures for each hash function result;
some kind of tree (e.g. red-black tree), may be a bit complex to implement manually.
Last two structures are part of programming classic and are well described in various articles and books.

Resources