-2

I am writing this piece of code which goes through a nested array and enters the xor value of the index row times the index of the column. The normal loop works but I want to improve the efficiency of the loop so there won't be heap problems when I try to run it multiple times on higher numbers. here is the regular loop code that works-

long[][] ar= new long[(int)m][(int) n];
long m=8,n=5;
        long k =1,newp=100;
        long sum=0,sum1=0;
        for(long i=0; i< ar.length;i++){
          for(long j=0;j<ar[0].length;j++){//time received
             ar[(int) i][(int) j]= i ^ j;
             sum+=ar[(int) i][(int) j];

here is my attempt at the more efficient loop-

long m=8,n=5;
        long[][] ar= new long[(int)m][(int) n];
        long sum1=0;
        for(long i: ar){
          for(long j[0]:ar){//time received
             ar[j][i]= (i ^ j);
             sum+=ar[i][j];
}
}

the nested loop seems to work, but the array doesn't seem to receive the variables as well as the integer/long type sum. help would be appreciated. Also, how should I change the xor calculation so that it will be correct-i ^ j stack trace:

java.lang.OutOfMemoryError: Java heap space
    at Immortal.elderAge(Immortal.java:6)
    at ImmortalTest.example(ImmortalTest.java:19)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
    at org.junit.vintage.engine.execution.RunnerExecutor.execute(RunnerExecutor.java:40)
    at org.junit.vintage.engine.VintageTestEngine$$Lambda$212/0x00000008400d9c40.accept(Unknown Source)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
    at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
    at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
Gil Caplan
  • 64
  • 8
  • 1
    1. The second code snippet does not compile -- how do you expect to apply XOR to long value `j` and to the array `i`? how array `i` is supposed to be cast to `int` and used as index? 2. In the first code snippet `m` and `n` are declared _after_ using in array declaration; also it is not needed to use `long` for `m, n, i, j` because array lengths and indexes are `int` – Nowhere Man Nov 08 '20 at 14:39
  • As Alex says, the code doesn't even compile. Also an array index can't be a long, just an int, as you can see by your own need for a cast. Why are you using longs for the index variables? Use the original method instead of for-each. – swpalmer Nov 08 '20 at 14:51
  • ok. how do I fix the code, nested code because the original one has heap errors for when large numbers are used, which is why I have long instead of an integer. so how do I change the loop correctly? – Gil Caplan Nov 08 '20 at 15:03
  • @GilCaplan, if you apply XOR to `int` operands it seems to be redundant to store the result in 2D array of `long`. However, even with `int` range if you try to use `Integer.MAX_VALUE` for both `m` and `n` it is doubtful that your machine has RAM of ~2^64 bytes. How big are your _large_ numbers? – Nowhere Man Nov 08 '20 at 15:45
  • Could you please show us the entire stack trace? – NomadMaker Nov 08 '20 at 16:11
  • @GilCaplan, if you need just to calculate the sum of XOR'ed indexes, perhaps you do not need the array at all? That would definitely save a lot of memory and prevent issues with insufficient heap space. – Nowhere Man Nov 08 '20 at 16:34
  • i need to also access the numbers of each spot in the array as a part of the question. ill add stack trace – Gil Caplan Nov 08 '20 at 16:53

1 Answers1

1

It is possible to optimize slightly population of the 2D array taking into account that XOR is a commutative operation, that is x ^ y == y ^ x.

Thus for the "square" part of the array (while i and j are below N = Math.min(m, n)), a "triangle" part should be considered excluding the main diagonal which will be populated with 0 (because x ^ x == 0). So instead of N2 operations it will take N * (N - 1) / 2 operations.

For the remaining part (over min) the XOR results should be calculated as before.

int min;
int max;
boolean moreRows;

if (m > n) {
    min = n;
    max = m;
    moreRows = true;
} else {
    min = m;
    moreRows = false;
    max = n;
}
int sum = 0;
int[][] ar2 = new int[m][n];
// square part
for (int i = 0; i < min; i++) {
    for (int j = 0; j < i; j++) {
        int t = i ^ j;
        ar2[i][j] = ar2[j][i] = t;
        sum += 2 * t;
    }
}
for (int i = min; i < max; i++) {
    for (int j = 0; j < min; j++) {
        int t = i ^ j;
        sum += t;
        if (moreRows) {
            ar2[i][j] = t;
        } else {
            ar2[j][i] = t;
        }
    }
}
for (int[] row: ar2) {
    System.out.println(Arrays.toString(row));
}

System.out.println("sum: " + sum);

Output for m = 5, n = 8:

[0, 1, 2, 3, 4, 5, 6, 7]
[1, 0, 3, 2, 5, 4, 7, 6]
[2, 3, 0, 1, 6, 7, 4, 5]
[3, 2, 1, 0, 7, 6, 5, 4]
[4, 5, 6, 7, 0, 1, 2, 3]
sum: 140
Nowhere Man
  • 19,170
  • 9
  • 17
  • 42
  • hey, I'm not 100% sure how to do this- let's say I want to take the next level, i want to take of a given k(lets say k=1), it takes of every index in our array the index and does xor - k, but only if that number is bigger or equal to k- so if the index equals 0 then nothing happens(in the example where k=1). let me know if you can help. thanks – Gil Caplan Nov 11 '20 at 09:22
  • It seems in this case another parameter `k` is introduced and the value written to array is calculated like this: `int xor = i ^ j; ar2[i][j] = ar2[j][i] = xor - (xor >= k ? k : 0);` using ternary operator. – Nowhere Man Nov 11 '20 at 11:11
  • ```(xor >= k ? k : 0) ```, could you explain what this piece of code does please. I tried putting it in the code but I didn't see that it does any difference, will this line work with any variable value of k? thanks – Gil Caplan Nov 11 '20 at 13:08
  • `bool_operand ? true_arg : false_arg` is [ternary operator](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html): a short form of `if-else` statement which can be used in expressions. For `k = 4` and the fix in both parts, the `sum` becomes 60. – Nowhere Man Nov 11 '20 at 13:42