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

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].

Related

Code is not executing the else condition in the inner most loop when matching array to array index by index?

var amazon = activeSpreadsheet.getSheetByName('Amazon');
var lastRow1 = amazon.getLastRow();
var array1 = amazon.getRange('A2:A' + lastRow1).getValues();
var source = activeSpreadsheet.getSheetByName('ProductDetails');
var lastRow2 = source.getLastRow();
var array2 = source.getRange('B2:B' + lastRow2).getValues();
n = 2;
x = 0; // match
z = 0; // non-match
for (var i = 0; i < array2.length; i++){
for (var j = 0; j < array1.length; j++){
if (array2[i] !== array1[j]){
z = z + 1;
}
else {
x = 9999
}
}
newsheet.getRange([n],[5]).setValue(z);
newsheet.getRange([n],[6]).setValue(x);
if (z > x) {
newsheet.getRange([n],[1]).setValue(array2[i]);
n == n++;
z = 0;
x = 0;
}
else if (z < x) {
z = 0;
x = 0;
}
}
My project is written in GAS (google app scripts) which is essentially, for all intents and purposes JS with variation in libraries.
Basically I am grabbing an element in the array2 and passing it through a loop to match to array1. For every time it does not match it adds 1, and when it matches (should only match once if it has any matches) it stores an arbitrary large number (larger than length of array1) and compares them.
As you can see I've written out to display these values and I always get z = 5183 (length of array1) and x = 0 (meaning no non-matches found). Therefore even if something exists in array 2 and 1 it will always write it to the cell.
What should happen is if there is a match, z= 5182 and x= 9999 (or arbitrary large number) and since 5182 < 9999 it doesn't do anything.
Is my scope wrong? Or am I not writing the If/Else correctly? Or is it something else?
Your code performs a strict comparison between the elements of two Arrays. That's fine, in general. However, for those specific Arrays those elements are also Arrays, which means strict (in)equality is checking to see if those are the exact same array object in memory. See this question for more information.
You probably wanted to do a value-based comparison, which means you need to compare the specific element of that inner array (i.e., index again). if (array2[i][0] !== array1[j][0]) {...} will check the 1st element of the inner array.
Looking at the instantiation of array1 and array2, we see that these are indeed 2D arrays from a single-column Ranges, so there will be only 1 element in each inner array. You can reduce the level of indexing necessary by flattening these arrays when you read them:
const array1 = sheet.getRange(...).getValues().map(function (row) { return row[0]; });
const array2 = ...;
I'm also not sure why you are passing in arrays to Sheet#getRange - you should pass in 1-4 arguments in manners consistent with the method signatures detailed in the Apps Script documentation.
Note that there are much better algorithms for checking if a value exists in a given array - you re-scan all of the 2nd array for every value of the first array. You should conduct thorough research into this topic before asking a new question on how to improve your algorithm.
Lastly, you should implement the best practice of using batch methods - you currently call setValue in a loop. Consider storing the results to write in an array, and then writing with Range#setValues once your loop has completed. There are many questions available for you to review on this topic.

How can i set all items of an array to 0 in GameMaker studio?

Simple. I Need Help Setting All The Values Of An array to 0 in GameMaker: Studio.
This is because i need to test if i have not modified the array by using
if array[id] != 0 {
//Enter code
}
Of course, there are several ways, choose the best depending on the circumstances.
If you haven't filled anything in the array yet, adding a new item to a certain index initializes all previous values with "0":
var array;
array[length-1] = 0; //everything upto length-1 is filled
If you did already create the array and wish to reset it you should loop over it:
for (var i = array_get_length_1d(array) - 1; i >= 0; --i) {
array[i] = 0;
}
If you do not care about the original memory locations, and you can create a complete new array, creating a new one in place of the old one can be slightly faster:
array = 0; //destroys the old array
array[length - 1] = 0; //recreates like in the first option

words processing (dynamic array of structs)

//runs through initial values and set them to null and zero;
for(int g =0;g<Arraysize;g++){Array1[g].word="NULL";Array1[g].usage=0;}
//struct
int Arraysize = 100;
struct HeavyWords{
string word;
int usage;
};
//runs through txt file and checks if word has already been stored, if it didn't,
it adds it as the next point in the struct, if it has, it adds to the usage int at that point in my array of structs
while (myfile >> Bookword)
{totalwords++;cout<<Bookword<<endl;
bool foundWord = false;
for(int q = 0;q<counter;q++)
{
if(Array1[q].word == Bookword)
{
Array1[q].usage++;
foundWord = true;
}
}
if(foundWord == false) {
Array1[counter].word = Bookword;
Array1[counter].usage = 1;
counter++;
//cout<<counter<<endl;
}
//double size of array when the counter reaches array size
if(counter==Arraysize)
{
HeavyWords * Array2;
Array2 = new HeavyWords[2*Arraysize];
for (int k= 0;k<Arraysize;k++)
{
Array2[k].word = Array1[k].word;
}
Arraysize = 2*Arraysize;
Arraydouble++;
HeavyWords* cursor = Array1;
Array1 = Array2;
delete [] cursor;
}
}
//I just started programming in C++ so im apologize if this code is an explosion of nonesence.
//here is my code,
//I have been racking my brain as to why it is not correctly storing the usage of each word, but when I run it, it gives me the incorrect amount of times certain words are used
//would really love if someone could tell me where my logic went wrong
Immediate problem - While copying Array1 to Array2 you are not copying the usage.
Solution - copy the usage. A statement such as Array2[k] = Array1[k] would do.
Suggestions:
You are also not breaking out in the first part of the code when you find a match in the Array1 for the word you are looking for. You code would needlessly continue to iterate over the entire array, when e.g. a match would have been found at say 10th index and you could have come out of the for loop.
You are re inventing the wheel. You need an expandable array; C++ STL has one readymade for you - it is called vector.
Also Array/Vector does NOT look to be right choice for what you are trying to do. On each word you are doing a linear search on the Array1. A map from C++ STL would neatly AND efficiently do what you are trying to do. Your code would also be much shorter. You can look up on how to code with maps. If you write some code, I can help further. Or wait; someone here would write out entire code for you :).

actionscript subtract specific items from array

how do I remove specific items from my array that is hundreds of items long?
-eg:
var myArray:Array = ["dog", "cat", "bear", "duck", "frog", etc..., etc...];
What do I do when I want to remove "duck" from this array? Please keep in mind, that the array is very long and we do not know WHERE the "duck" is, so we don't know it's index in the array.
I need to get that item somehow by it's name and remove it from the array.
myArray.splice(myArray.indexOf("duck"), 1);
This is a straight-forward way of doing it:
Non-stable version (does less copying).
for (var i:int, j:int = array.length - 1, temp:Object; i <= j;) {
temp = array[i];
if (temp == "duck") {
array[i] = array[j];
array[j] = temp;
j--;
} else {
i++;
}
}
array.length = i;
And the stable version (more copying, but the order of the original array is unchanged):
for (var i:int, j:int, temp:Object; i < array.length; i++) {
temp = array[i];
if (temp != "duck") {
array[j] = temp;
j++;
}
}
array.length = j;
However, if you could assure that values are unique, the algorithm would be different, since you wouldn't have to verify items after the one you've found.
The algorithm would be significantly different, if the array was sorted because you could use binary search to find the element to remove. In some very peculiar situations, like, for example, if you have a well-founded set (which is your array), the deletion would be even simpler, because the position of the item you are searching for could be determined in constant time. The later can be mitigated through the use of indices (put simple, you could have a hash-table that uses elements of the array as its keys and their offsets into array as values).
Again, you need to consider all those cases and what is practical with regard to your program.
As I've mentioned above, there may be benefits if you use a different data structure, or if you sort on insert, or if you index on insert.
Lastly, producing a copy with undesired items removed is different from destructively removing items from the same array.
If your array is very long, it is well worth optimizing it somehow.
some options:
1) use a dictionary; the string can be the key. This has the added benefit of not re-indexing your list when you add/remove elements.
//specify weak keys when you create the dictionary
var myDictionary:Dictionary = new Dictionary(true);
//when you want to delete an item:
myDictionary["duck"] = null;
2) sort your array and use a binary search. There's lots of info about binary search online. Here's one SO question on the topic.
One way is to just use a while loop in combination with the indexOf method of an Array as such :
var index:int;
while ((index = myArray.indexOf("duck")) >= 0)
{
myArray.splice(index,1);
}
You could wrap that in a function and accept Array and String parameters, and return the resulting array like this :
function removeSearchString(sourceArray:Array, searchString:String):Array
{
var index:int;
while ((index = sourceArray.indexOf(search)) >= 0)
{
sourceArray.splice(index,1);
}
return sourceArray;
}
then you'd use the function like this :
myArray = removeSearchString(myArray, "duck");

FOR loop in C for specified i values

I'm trying to make a FOR loop in c with specific i values for example i=2,6,8,12,16,20,22,26,34.. I just don't know how to specify increments as they are not equal. This code is not good for me.
for (i=2,i<=30,i++) {
}
Maybe with specified array of values in i and then run for loop with reference to that array?
Any help?
Your for-loop syntax needs to be fixed.
The first option is to use a custom function:
for (i=2; i <= 30; i = foo(i)) { ... }
where foo is a function which takes the current value of i and returns the next value. You will need to come up with a proper definition of foo yourself.
The other approach can be to put all these values in an array and use the array as indices:
int indices[ MAX_INDICES ] = { 2, 6, ... };
for (size_t j = 0; j < MAX_INDICES; ++j) {
/* instead of using 'j' use indices[ j ] now on */
}
The amount you want to add seems not to be allways the same. Because of that I would suggest to put the Values into an array and loop through it with an index.
pseudocode:
int vals[10];
// fill the values
vals[0] = 2;
vals[1] = 6;
vals[2] = 8;
...
for(int i = 0; i < 10; ++i)
{
// work
}
Correct, you want to put the indices in an array:
static const int indices[] = { 2,6,8,12,16,20,22,26,34 };
for (int i = 0; i != sizeof(indices) / sizeof(indices[0]); ++i) {
const int j = indices[i];
...
}
Is there any pattern for the values of i? If not, and the number of possible values you need is small enough, you would need to create an array and the iterate across the array, something like:
int myValue[9] = {2,6,8,12,16,20,22,26,34};
int i;
for(i=0; i < 9; i++)
{
printf("myValue[%d] = %d\n", i, myValue[i]);
}
For a step of 2 you can make it like this.
for (i=2,i<=30,i+=2) {
}
What are the exact constraints? Seems to increment by 4 most of the time but then there are variations.
Given that, it seems the best approach would be to put the values you need into an array and use them that way, or alternatively define a function that can generate these values and then access them that way (rather than indexing through your array of values).
Also, note the parts inside the for-loop are separated by ; not ,

Resources