0

I'm trying to solve this riddle in java, about an old man who lives because his cult who gives the old man some of their life, this specific code should work to the rules which are given but one of the checks in the testing is an error.

public class hello {
    /** set true to enable debug */
    static boolean debug = true;

    static long old(int n, int m, int k, int newp) {
            int max;
            int min;
        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[(int)m][(int)n];
    // square part
    for (int i = 0; i < min; i++) {
        for (int j = 0; j < i; j++) {
           int t = i ^ j;
            ar2[i][j] = t - (t >= k ? k : 0);;
            sum += 2 * t- (t >= k ? k : 0);;
        }
    }
    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 - (t >= k ? k : 0);
            } else {
                ar2[j][i] = t;
            }
        }
    }
        //retrun time
            while(newp<sum && newp>0) {
                sum=sum-newp;//wrap it up
            }
            return sum;
    }
  }

here is the assert equals test which contains multiple examples:

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

public class HelloTest {

    @Test
    public void example() {
        assertEquals(5, Hello.olde(8, 5, 1, 100));
        assertEquals(224, Hello.old(8, 8, 0, 100007));
        assertEquals(11925, Hello.old(25, 31, 0, 100007));
        assertEquals(4323, Hello.old(5, 45, 3, 1000007));
        assertEquals(1586,Hello.old(31, 39, 7, 2345));
        assertEquals(808451, Hello.old(545, 435, 342, 1000007));
        // You need to run this test very quickly before attempting the actual tests :)
        assertEquals(5456283, Hello.old(28827050410L, 35165045587L, 7109602, 13719506));
    }

}

i get the following errors which looks like a long to int-

./src/test/java/HelloTest.java:19: error: incompatible types: possible lossy conversion from long to int
        assertEquals(5456283, hello.old(28827050410L, 35165045587L, 7109602, 13719506));
                                                ^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error

some more errors from harder examples-

        assertEquals(5456283, Hello.old(28827050410L, 35165045587L, 7109602, 13719506));
                                                ^
./src/test/java/HelloTest.java:39: error: incompatible types: possible lossy conversion from long to int
            long expected = Hello.old(m, n, l, t), actual = Hello.old(m, n, l, t);

debug some errors in one of the assert equals and harder examples, I can't really think what can be changed, I'm sure it's something small so help would be appreciated-Note: t will never be bigger than 2^32 - 1(from the instructions of the question) thanks

Gil Caplan
  • 64
  • 8
  • 2
    "i want to keep it on type long because there are tests with high numbers which will exceed the integer amount" - how do you expect those to work then? You can't create an array with more than 2^31 - 1 elements in Java. – Jon Skeet Nov 11 '20 at 15:21
  • (Hint: if the tests are meant to work with numbers outside the range of valid array lengths, you probably don't want to use arrays for that.) – Jon Skeet Nov 11 '20 at 15:22
  • nono, I don't need to add to the amount of spots in the array. – Gil Caplan Nov 11 '20 at 15:22
  • Note: t will never be bigger than 2^32 - 1 - in the instructions of the question – Gil Caplan Nov 11 '20 at 15:23
  • 2
    If `t` as well as `n` and `m` can never be larger than 2^32-1 then why do you require them to be `long` values? – Thomas Nov 11 '20 at 15:28
  • yes, didn't think of that! thanks. changed up the question a bit. – Gil Caplan Nov 11 '20 at 15:43
  • Well this goes back to arrays not being the best approach here. You'd be trying to create an `int[35165045587][28827050410]`. That's 1e21 elements. That's about 3687835639 *terrabytes*. Unless your machine has rather a lot more memory than I expect it does, you need to rethink your approach. – Jon Skeet Nov 11 '20 at 15:59
  • Understood, so since the array isn’t good for the space, what would be a suitable function/... that I can use instead of an array ? – Gil Caplan Nov 11 '20 at 16:10
  • That's an entirely different question, and one that isn't really suitable for Stack Overflow - and even if it *were*, it would require knowing what the actual problem is. (Currently all we have is a lot of very dense code and a description of the problem which is just that it's "about an old man who lives because his cult who gives the old man some of their life") – Jon Skeet Nov 11 '20 at 16:26
  • ok. no worries. thanks for the help – Gil Caplan Nov 11 '20 at 16:44
  • Hi, I am using the code which Alex helped with down below. I changed everything too long and using sum as the only variable which stores data, this works but when I converted everything to long(because on large tests sum can exceed 2^32-1 therefore I changed to long). how can I improve performance / efficiency? – Gil Caplan Nov 12 '20 at 04:33

2 Answers2

1

According to my knowledge, you cant take more than int in the size of an array but if you don't want to change your long everywhere, you can probably add cast.

long m = 434;
    int[] obj = new int[(int) m];

Attempting to access beyond the maximum value allowed through an iterator associated with the array would likely result in one of OutOfMemoryException, IndexOutOfBoundsException or a NoSuchElementException depending on implementation.

This is a very impractical use of memory. If one was to want such a data structure, one should investigate less RAM intensive approaches such as databases, sparse arrays, and the like.

Vyom Yadav
  • 145
  • 13
1
  1. The last test will NOT run on a single machine as long values cannot be used as array length and indexes. This has already been explained in the answer/comments to your previous question.

However, it can be deducted from the task that you do not need to store intermediate data in the array at all, you should just calculate the total.

And even if array is not used it is very likely to take a long time to complete the nested loop with 28_827_050_410 * 35_165_045_587L / 2 iterations. If you had a processor with performance of 100 GFlop/s it should be able to count that in over 160 years.

  1. The calculation of t and sum is incorrect.

It should be:

int t = i ^ j;
if (t >= k) {
    t -= k;
}
sum += 2 * t; // or sum += t in the second part.
  1. The last loop seems to be replaceable with simple return sum % newp;

Update:

Function old may be refactored as follows (to get rid of the arrays), though it is still a "naive" solution which would not pass the last test.

static int old(int n, int m, int k, int newp) {
    int max;
    int min;

    if (m > n) {
        min = n;
        max = m;
    } else {
        min = m;
        max = n;
    }
    int sum = 0;
    // square part
    for (int i = 0; i < min; i++) {
        for (int j = 0; j < i; j++) {
            int t = i ^ j;
            if (t >= k) {
                t -= k;
                sum += 2 * t;
            }            
        }
    }
    for (int i = min; i < max; i++) {
        for (int j = 0; j < min; j++) {
            int t = i ^ j;
            if (t >= k) {
                t -= k;
                sum += t;
            }
        }
    }
    return sum % newp;
}

Output for the 6 tests:

OK! 5
OK! 224
OK! 11925
OK! 4323
OK! 1586
OK! 808451
Nowhere Man
  • 19,170
  • 9
  • 17
  • 42
  • awesome, thanks for the help. so I should keep the nested loop but the only variable storing information should be sum to keep the performance and memory to a minimum right which changes throughout the loop right? – Gil Caplan Nov 11 '20 at 16:43
  • thanks a lot. appreciate your time. i tried and implemented what you said using only sum for storing value. i got this error when checking- ``` assertEquals(5456283, Hello.old(28827050410L, 35165045587L, 7109602, 13719506)); ``` – Gil Caplan Nov 11 '20 at 17:02
  • here is whats given- ```old(int n, int m, int k, int newp) ``` – Gil Caplan Nov 11 '20 at 17:03
  • If this riddle is somewhere on the internet, please post a link to it. – Nowhere Man Nov 11 '20 at 17:12
  • https://www.codewars.com/kata/59568be9cc15b57637000054/train/java . here thanks – Gil Caplan Nov 11 '20 at 17:13
  • @GilCaplan, I updated the answer, simpler tests now pass (`xor` values below k are ignored), but this does not help pass the last performance test. I guess that due to the `newp` parameter and use of modulo operation `%` the biggest part of the `xor` terms should be simply ignored – Nowhere Man Nov 11 '20 at 20:20
  • ok. thanks. perhaps the while instead of the ```%``` will work better – Gil Caplan Nov 11 '20 at 20:27
  • do you think that i need to change the angle of how I'm answering the question? – Gil Caplan Nov 11 '20 at 20:30
  • I think the issue might be because the sum on that last test adds up over 2^32-1 therefore it can't be an integer anymore- how do you think I can convert the sum to a long variable or something else so that I don't get this error? – Gil Caplan Nov 11 '20 at 20:45
  • i tried converting everything to long type but the code timed out – Gil Caplan Nov 11 '20 at 20:50