Efficently move multiple items in array from oldlocation to new location - arrays

For example suppose we have:
a = [0,1,2,3,4];
And suppose we want to move the element 1 and 2 after 4 so a = [0,3,4,1,2]. What we want to move from and to is given by the following data:
oldLocation = [1,2] #move item a[1] and a[2]
newLocation = [3,4] #move to a[3] and a[4]
Now notice the newLocation is relative to the original array a. So I can't just move one by one from old to new location, since the array would be modified. I need some special handling.
Any thoughts? Currently I'm making copy of array a and copying everything but the moved model. Then inserting the moved model at the specified position. Then setting a to the newly adjust array.
Language doesnt really matter, but I'm using javascript.

int [] swap(int[] a, int[] oldl, int[] newl) {
int len = oldl.length; // or newl.length
for (int i = 0; i < len; i++) {
int oldi = oldl[i];
int newi = newl[i];
int temp = a[oldi]; // swap both
a[oldi] = a[newi];
a[newi] = temp;
}
return a;
}
Please try to put effort & solve easier stuffs by yourself.

Related

My .slice() method mutate the original array (TypeScript)

This is my first time writing a slice() method in TypeScript. I know that the slice() method should've return a copy of an array. Here is a bit snippet of the code
class ChapterOne {
// Gauss Jordan Elimination
// Notes: Only solve system of linear equation with one solution
static gaussJordanElim( linsys : number[][] ) {
const numOfEquation = linsys.length
const numOfUnknown = linsys[0].length - 1
if (numOfUnknown > numOfEquation) return 'This System of Linear Equation either have no solution or have infinite solutions'
// I slice it here.
const input = linsys.slice()
const length = input.length
// pointer = i, row to operate = j, column to operate = k
for (let i = 0; i < length; i += 1) {
if (input[i][i] === 0) return 'Mathematical Error! Cannot divide by zero'
for (let j = 0; j < length; j += 1) {
if (i !== j) {
const ratio = input[j][i] / input[i][i]
for (let k = 0; k < length + 1; k += 1) {
input[j][k] = input[j][k] - ratio * input[i][k]
}
}
}
}
// I Checked it here
console.log(input)
console.log(linsys)
const output = input.map((row, pointer) => row[length] / row[pointer])
return output
}
}
In short I made a copy of the original array, did alot of manipulation to the copied array, and didn't want to mutate the original array but when I console.log both the copied and original, the original also change. Is there any clear explanation for this?
The main goal is to copy the original array, change the copied one, and maintain the original one.
This is because .slice does a shallow copy and does not copy nested objects. Since you are using two dimensional array, this is expected.
Use:
const input = JSON.parse(JSON.stringify(linsys))
Shallow cloning does not copy nested objects. So if an object contains an object, your .slice will keep a reference to the original copy of that object rather than creating a copy. Hence, the value changes.
In case of a shallow copy-
Objects will reflect change in the original place from where they were shallowly copied because they are stored as references (to their address in the Heap).
Primitive data types will NOT reflect change in the original place because they are directly stored in the callstack (in Execution Contexts).
For example:
var a = [
[1, 2], // This still is referencing to the original reference
[5,7]
]

How can you initialize an entire array at once in GML?

I want to initialize an entire array at once but I can't find any examles of this being done anywhere.
I want to do something like this:
int a [][] = {{0,1,0},
{0,1,1},
{2,1,0}};
Unfortunately GML is not like many other languages in the sense that GML does not have single line array initialization. You can easily write a script to accomplish this, but the GML docs use this method to initialize arrays. The example they gave initializes a 10 record array (0-9) with zeros.
var i;
i = 9;
repeat(10)
{
array[i] = 0;
i -= 1;
}
If you want different values for every record then you have to manually type every position. This is the example the docs gave.
count = 3;
array[count] = "you?"
count -= 1;
array[count] = "are "
count -= 1;
array[count] = "How "
count -= 1;
array[count] = "Hello!"
count -= 1;
In regards to a script: Here is a simple one for 1D arrays. Used as var myArray = array(record 1, record 2, 3, 4, ...)
///array(*args);
var arr;
for (var i=0;i<argument_count;i+=1)
{
arr[i] = argument[i];
}
return arr;
If you are using a current version of GameMaker, there's array literal syntax in form of [...items] (documentation). So you can do
a = [[0,1,0],
[0,1,1],
[2,1,1]];
and that'll work fine.
The only thing to note that this'll produce an array of arrays (which is how arrays work in most languages) rather than GML-specific legacy 2d array, so you'd need to use a pair of [index] accessors rather than [index1, index2].

Reshaping an array from 1D to ND in C

I am having a lot of trouble trying to implement this on my own, so if anyone can point to, or describe an algorithm I'd be much obliged.
The problem statement
Given one dimensional flattened pointer int* i which would look something like this {1,2,3,4}, and given a list of dimensions in form of a list {2,2} reshape the 1D array to conform with specified dimensions. Overall after the procedure the array should look like {{1,2},{3,4}}.
I am basically asking if anyone knows the algorithm that is used in numpy.reshape.
A n-dimensional array in c is nothing more than syntactic sugar for computing the offset inside a simple array, they look the same in memory (one contiguous block). Therefore, there's really no point in "reshaping" it, as this little sample demonstrates:
#include <stdio.h>
int data[] = {1,2,3,4};
int main(void)
{
int *i = data;
for (int n = 0; n < 4; ++n)
{
printf("i[%d] = %d\n", n, i[n]);
}
int (*j)[2] = (void *)i;
for (int n1 = 0; n1 < 2; ++n1)
{
for (int n2 = 0; n2 < 2; ++n2)
{
printf("j[%d][%d] = %d\n", n1, n2, j[n1][n2]);
}
}
return 0;
}
output:
i[0] = 1
i[1] = 2
i[2] = 3
i[3] = 4
j[0][0] = 1
j[0][1] = 2
j[1][0] = 3
j[1][1] = 4
NumPy doesn't need an algorithm, because it stores data contiguously regardless of the shape. The "shape" property is the only difference between the input and the output of reshape(). The algorithms come into play when later accessing the array, such as when printing it. Then you need to follow the shape to know how many elements go in each row or other dimension.

Setting up Arrays in one line

Im trying to set up an array with six integer values and one string in one line. I know how to do this one line at a time but cant figure out how to set it up in GameMaker.
array[0] = 10;
array[1] = 1;
array[2] = 5;
array[3] = 12;
array[4] = 12;
array[5] = 3;
array[6] = spr_sprite;
But ideally id like to avoid having multiple lines of code if i can. So how do i set it up in one line?
You can use that extention from the Marketplace (script array_create). Or create it yourself:
/// array_create(value1, value2, ...)
var res;
var n = argument_count - 1;
while (n-- >= 0)
{
res[n] = argument[n];
}
return res;
Old verisons of GMS may use 16 arguments maximum, but some time ago this limit was removed and now you can use about 700 arguments (actually I don't remember exact value and I guess this may differ on different hardware).
On GMS2 you can initialize arrays using the syntax
var a = [1, 2, 3, 4];

In c: Can I copy a whole portion of an array at once, by refering to the pointer to the location of a slot in the array I want to copy from?

Hope my question is clear and relavent, new to Pointers... - Can I copy a whole portion of an array at once, by refering to the pointer to the location of the first slot in the array I want to begin copying from?
For example -
Given an array : A [ 1,2,3,4,5,7,8,3,2,5,1,0,9]
- I want to copy only the part of the array from the n'th slot on, into the beginning of the array B [0 0 0 ..... ] (B is of the same length of A).
Can I do it at once, using pointers instead of a loop? Something like - switching the pointer to the 1'st slot in B with the pointer to the n'th slot of A, and the n'th slot in B with the last one in A?
Thanks a lot on advance!
That's what memcpy is for.
memcpy(B, A + n, (N - n) * sizeof(A[0]));
where N is the number of elements in A. If A is really an array (not just a pointer to one), then N can be computed as sizeof(A) / sizeof(A[0]), so the call simplifies to
memcpy(B, A + n, sizeof(A) - n * sizeof(A[0]));
memcpy lives in <string.h>; its first argument is the destination of the copy, its second the source.
(I'm sorry, I don't really follow what kind of pointer trick you have in mind, so I can't comment on that.)
I think I understand what you're asking. You can use pointers to set up your second array, but here is the problem with doing it that way:
int [] primary = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int * secondary = primary + 5;
At this point, primary is { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }, and secondary is { 6, 7, 8, 9, 0 }, but the problem is they both point to the same array in memory. So instead of having two independent copies, if you edit any of the elements of 'secondary', they are edited in 'primary' also.
secondary[2] = 10;
for(int i = 0; i < 10; ++i)
cout << primary[i] << ' ';
This portion of code would now yield:
1 2 3 4 5 6 7 10 9 0
The correct way to do it would to either be setting up the new array, and looping through copying over the values, or using memcpy().
Edit:
//Rotate an array such that the index value is moved to the front of the array
null rotateArray( &int original[], int size, int index)
{
int * secondary = new int[size]; //dynamically allocated array
for(int i = 0; i < size; ++i)
{
secondary[i] = original[(i+index)%size];
}
original = secondary; //Move the original array's pointer to the new memory location
}
Some notes:
secondary[i] = original[(i+index)%size];
this is how I rotated the array. Say you had an original array of size 5, and you wanted the fourth element to be the new start (remember, elements are numbered 0-(size-1)):
i = 0;
secondary[0] = original[(0 + 3)%5]// = original[3]
i = 1;
secondary[1] = original[(1 + 3)%5]// = original[4]
i = 2;
secondary[2] = original[(2 + 3)%5]// = original[0]
...
The last part of the code:
original = secondary;
is a little bit questionable, as I don't remember whether or not c++ will try and clean up the used memory once the function is exited. A safer and 100% sure way to do it would be to loop through and copy the secondary array's elements into the original array:
for(int i = 0; i < size; ++i)
original[i] = secondary[i];

Resources