This question contains a JavaScript example but it could possibly be relevant for other languages as well.
I got a 2d binary array (values are set to 1 and 0 only). I want to make an action which toggles all values, meaning turn all 0 to 1 and all 1 to 0.
Which is a better way to do it:
1)
for(var i = 0; i < rowsNum; i++)
{
for(var j = 0; j < colNum; j++)
{
if(arr[i][j] == 0)
{
arr[i][j] = 1;
}
else
{
arr[i][j] = 0;
}
}
}
or
2)
for(var i = 0; i < rowsNum; i++)
{
for(var j = 0; j < colNum; j++)
{
arr[i][j] = 1 - arr[i][j];
}
}
I would like to know if there's a generic method which is best for most cases. Also, specifically regarding JS, is there a better way to do it than these 2 methods?
I would go for the second way of doing it, or I would use the xor operation, like this:
for (var i = 0; i < rows; i++) {
for (var j = 0; j < cols; j++) {
arr[i][j] ^= 1;
}
}
The thing is, if statements translate into branching instructions which can be slow due to branch mispredictions. However, the performance gain in an example like this will barely show, and if it makes the code less readable, then it's not worth it. Always optimize last and if it's absolutely necessary.
Related
I'm new to C and learning it for a class right now. We are currently working on a little project and we are supposed to use pointer arithmetic to access arrays as opposed to the standard [] way.
For some reason, I can use it just fine on the first loop (see code) but when I use it in the second, it doesn't produce the same outcome as if I were to use the standard [] way.
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
int num = *(*array+i)+j;
//Irrelevant code
}
}
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
int num = array[j][i]; // Error comes if I do *(*array+j)+i;
//Irrelevant code
}
}
I don't know if I am missing something here but why would calling the array using pointer arithmetic be different between the 2 loops?
The equivalence between subscripts and pointer notation is:
a[i] == *(a + i)
You are using (*a + i) in place of the correct *(a + i).
I believe your first set of loops should read:
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
int spot = *(*(board+i)+j);
for (int k = j + 1; k < size; k++) {
if (spot == *(*(board + i) + k) && spot > 0) {
return 0;
}
}
}
}
However, since you've not provided an MCVE (Minimal, Complete, Verifiable Example
— or MRE or whatever name SO now uses)
or an
SSCCE (Short, Self-Contained, Correct Example
— the same idea by a different name), I can't easily test the code.
Also, now you know why it is better to use the explicit subscript notation; it is a lot harder to get it wrong.
This is my first post here.
An assignment of my online course in C asked me to remove each row in a real(non dynamically allocated, pointers are not used) whose average sum is greater than the average sum of the whole matrix. The rows should be "removed" by shifting the ones below it up by one position.
I have set up a matrix with the following code:
int matrix[100][100]
Now, my idea was to create a regular 1D array which stores the indexes of the rows to-be-removed.
This is how I did it:
k = 0;
for (i = 0; i < no_of_rows; i++) {
average_sum_of_row = 0;
for (j = 0; j < no_of_columns; j++) {
average_sum_of_row += matrix[i][j];
}
average_sum_of_row = average_sum_of_row / no_of_columns;
if (average_sum_of_row > average_sum_of_matrix) {
indexes_of_rows_to_remove[k] = i;
k++;
l++;
}
}
Which works just fine! I get an array whose elements are the indexes of the rows which need to be removed. However, while implementing my code into the following:
m = 0;
for (i = 0; i < V; i++) {
if (indexes_of_rows_to_remove[m] == i) {
for (k = i; k < no_of_rows - 1; k++) {
for (j = 0; j < no_of_columns; j++) {
matrix[k][j] = matrix[k + 1][j];
}
}
i--;
no_of_rows--;
}
m++;
}
It does not work. What I used is my existing code of removing a row by shifting the ones below it up and decreasing the number of rows by one, but this simply doesn't work and I don't know why.
I tried using a separate integer(m) to go through all elements of the array of indexes, but for some reason it does not work.
Thanks all!
You can use this algorithm, which skips the rows to be deleted:
k = 0
For i in number of rows:
If i not to be deleted:
matrix[k] = matrix[i] # copy the whole row here
k++
The algorithm you are trying to implement is complicated and very inefficient.
What I am trying to do (not very successful) is if my code detects a signal (if(matrix[i][j] ==1)) coming (1 or 0) for the next few steps I want my code to write in a new matrix: newmatrix[i][j]=10 and if not to continue with 0. Here is my code so far:
for (i = 0; i < rows; i++) {
j = 0;
do {
if (matrix[i][j] == 1) {
int m = j;
while (j < m + 3) {
newmatrix[i][j] = 10;
printf("newmatrix[%i][%i] and %f\n", i, j, newmatrix[i][j]);
j++;
continue;
}
}
if (matrix[i][j] == 0) {
newmatrix[i][j] = 0;
printf("newmatrix[%i][%i] and 0 is %f\n", i, j, newmatrix[i][j]);
j++;
continue;
}
j++;
} while (j < MAXTIME);
}
}
The problem is that if there is a signal near the end instead of stopping when to column count reaches the max number the code inserts new columns even though they are only 10:
Where is my mistake can someone point me to the right direction? Is there maybe a way to do this cleaner with goto statement?
Here is a simpler approach with a temporary variable:
for (i = 0; i < rows; i++) {
int spike = 0;
for (j = 0; j < MAXTIME; j++) {
if (matrix[i][j] == 1) {
spike = 3;
}
if (spike) {
newmatrix[i][j] = 10;
spike--;
} else {
newmatrix[i][j] = 0;
}
printf("newmatrix[%i][%i] is %f\n", i, j, newmatrix[i][j]);
}
}
Notes:
I am assuming that matrix[i][j] is either 0 or 1. If other values are possible and newmatrix[i][j] should stay unmodified for these cells, the code should be modified.
It is advisable to only modify a loop index in the for update clause. do / while loops are notoriously error prone, especially with nested loops that also modify the loop index as is the case in your code.
How do i execute an IF statment inside a double for loop, checking if an object in an array equals the selectedItem.label? Here is my try! (didn't work)
function klikkA(evt:Event):void{
for( var j:int = 0; j < 4; j++)
{
for (var k:int = 0; k < 8; k++)
{
if (listeA.selectedItem.label != myArray[j][k])
{
continue;
}
else if(listeA.selectedItem.label == myArray[j][k])
{
txtFlagg.text = myArray[j][k];
break;
}
}
}
}
The break statement alone will only break the inner loop.
As you can see in the documentation of break, you can specify a label
break [label]
It explains:
In nested loops, break only skips the rest of the immediate loop and does not break out of the entire series of nested loops. To break out of an entire series of nested loops, use label
There's additional documentation on the label keyword
It provides an example comparable to yours:
outerLoop: for (var i:int = 0; i < 10; i++) {
for (var j:int = 0; j < 10; j++) {
if ( (i == 8) && (j == 0)) {
break outerLoop;
}
trace(10 * i + j);
}
}
/*
1
2
...
79
*/
Since break can only jump out of single loop you need to either use flag or goto.
I'd use flag that outer loop(s) check as it generally more accepted practice:
var found = false;
for( var j:int = 0; !found && j < 4; j++)
{
for (var k:int = 0; k < 8; k++)
{
.... if(listeA.selectedItem.label == myArray[j][k])
{ ....
found = true;
break;
}
}
}
Which of these optimizations is better and in what situation? Why?
Intuitively, I am getting the feeling that loop tiling will in general
be a better optimization.
What about for the below example?
Assume a cache which can only store about 20 elements in it at any time.
Original Loop:
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 1000; j++)
{
a[i] += a[i]*b[j];
}
}
Loop Interchange:
for(int i = 0; i < 1000; i++)
{
for(int j = 0; j < 10; j++)
{
a[j] += a[j]*b[i];
}
}
Loop Tiling:
for(int k = 0; k < 1000; k += 20)
{
for(int i = 0; i < 10; i++)
{
for(int j = k; j < min(1000, k+20); j++)
{
a[i] += a[i]*b[j];
}
}
}
The first two cases you are exposing in your question are about the same. Things would really change in the following two cases:
CASE 1:
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 1000; j++)
{
b[i] += a[i]*a[j];
}
}
Here you are accessing the matrix "a" as follows: a[0]*a[0], a[0]*a1, a[0]*a[2],.... In most architectures, matrix structures are stored in memory like: a[0]*a[0], a1*a[0], a[2]*a[0] (first column of first row followed by second column of first raw,....). Imagine your cache only could store 5 elements and your matrix is 6x6. The first "pack" of elements that would be stored in cache would be a[0]*a[0] to a[4]*a[0]. Your first acces would cause no cache miss so a[0][0] is stored in cache but the second yes!! a0 is not stored in cache! Then the OS would bring to cache the pack of elements a0 to a4. Then you do the third acces: a[0]*a[2] wich is out of cache again. Another cache miss!
As you can colcude, case 1 is not a good solution for the problem. It causes lots of cache misses that we can avoid changing the code for the following:
CASE 2:
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 1000; j++)
{
b[i] += a[i]*a[j];
}
}
Here, as you can see, we are accessing the matrix as it's stored in memory. Consequently it's much better (faster) than case 1.
About the third code you posted about loop tiling, loop tiling and also loop unrolling are optimizations that in most cases the compiler does automaticaly. Here's a very interesting post in stackoverflow explaining these two techniques;
Hope it helps! (sorry about my english, I'm not a native speaker)