0

So here is my code for the 3n+1 problem on UVa. It runs perfectly on my PC in Eclipse AFAIK, however, I keep getting a runtime error against the UVa judge. Unfortunately, the judge does not tell me what inputs it uses, nor provide any information beyond "RuntimeException" when it fails. This is the same structure as the ACM's ICPC, for the curious.

I am pretty sure that the recursion shall not overflow the stack as the maximum cycle length of all numbers from 1 to 1000000 is only 525. Also, the cache of 1000000 integers shall be only 4Mb large.

package Collatz;

import java.util.Arrays;
import java.util.Scanner;

class Main{
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int[] cache = buildCache(1000000);
        while (in.hasNextLine()) {
            Scanner line = new Scanner(in.nextLine());
            if (!line.hasNextInt()) continue;
            int a = line.nextInt();
            int b = line.nextInt();
            int c = a;
            int d = b;
            if (c > d) {
                int temp = c;
                c = d;
                d = temp;
            }
            int max = 0;
            for (int i = c - 1; i <= d - 1; i++) {
                max = Math.max(max, cache[i]);
            }
            System.out.format("%d %d %d\n", a, b, max);
            line.close();
        }
        in.close();
    }

    public static int[] buildCache(int n) {
        int[] cache = new int[n];
        Arrays.fill(cache, 0);
        cache[0] = 1;
        for (int i = 1; i < n; i++) {
            search(i + 1, cache);
        }
        return cache;
    }

    public static int search(long i, int[] cache) {
        int n = cache.length;
        if (i == 1) {
            return 1;
        } else if (i <= n && cache[(int)(i - 1)] > 0) {
            return cache[(int)(i - 1)];
        } else {
            long j = (i % 2 == 1) ? (3 * i + 1) : (i / 2);
            int result = search(j, cache) + 1;
            if (i <= n) {
                cache[(int)(i - 1)] = result;
            }
            return result;
        }
    }
}
dimo414
  • 47,227
  • 18
  • 148
  • 244
user690421
  • 422
  • 1
  • 5
  • 15
  • 4
    What runtime error are you getting? Can you post the stack trace? – thegrinner Jan 23 '14 at 21:59
  • 2
    FYI `Arrays.fill(cache, 0)` is unnecessary - elements of an `int[]` will default to `0`. – Paul Bellora Jan 23 '14 at 22:00
  • @thegrinner The problem is that UVa don't tell me what runtime error I am getting... On my PC there is no error though. Apparently I didn't try all corner cases or my understanding of the input format is wrong. Here is the question link: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=36 – user690421 Jan 23 '14 at 22:13
  • @PaulBellora Cool. I was thinking that since the array is "newed" to the heap, it might contain garbage. But it seems that you are right after googling. – user690421 Jan 23 '14 at 22:14
  • 1
    out of curiosity, what is UVa? (Other than the reason you need sunblock?) – JVMATL Jan 23 '14 at 22:26
  • @JVMATL: See http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=36 (found by Googling `uva 3n+1`; dunno why the OP assumed everyone would just automatically know what it was). – ruakh Jan 23 '14 at 22:34
  • @ruakh thanks for that - funny, even after I have looked at the link, I still don't know [exactly] what UVa is (what it stands for) but for the benefit of anybody else reading here: it's some sort of online server that posts a list of programming challenges and automatically grades/test responses. (looks like it's intended to help train people who want to participate in programming contests) Bonus points if anybody can figure out what UVa stands for by browsing their web site. :) – JVMATL Jan 23 '14 at 22:40
  • @JVMATL I guess UVA is the abbreviation of some university in Eastern Europe. Normally the Online Judge system of a university is named by the university name itself. And you are right, this is a collection of programming contest problems aimed to help those who are interested or are preparing for programming contest. I am looking at it just for fun. – user690421 Jan 23 '14 at 22:51
  • Amusingly, this (find the max cycle length for `n` 1-1,000,000) is almost exactly an interview question I pose regularly for interns. – dimo414 Jan 23 '14 at 23:33
  • 1
    One thing important here to note is that if this is a `StackOverflowError` the judge has made a major oversight. `StackOverflowError` extends `Error`, not `RuntimeException`. This is actually pretty important. Did the judge say exactly `RuntimeException` or did you infer that? If you could clarify this that would be great. – Radiodef Jan 23 '14 at 23:37
  • Basically if it's definitely `RuntimeException`, that narrows it down quite a bit. As far as I can see it must be an out of bounds exception or something with the Scanner (but `InputMismatchException` *should* be ruled out because the spec for the UVa problem says the input *will* be integers). But throw that out the window if the judge did not say `RuntimeException`. – Radiodef Jan 23 '14 at 23:51
  • @Radiodef Thank you very much for the answers. I also think it has something to do with Scanner or bound. It seems ppl rarely use Scanners in doing those algorithmic questions. But I found scanner really handy... Anyway, I think there is a similar problem on SPOJ and I gonna try that. – user690421 Jan 24 '14 at 00:19
  • The input to throw InputMismatchException is a line with something like `99 abc` because you only check hasNextInt for the first token. But, again, according to the spec that should not be a valid input. It would not make sense to reject the submission based on criteria outside the spec. – Radiodef Jan 24 '14 at 00:34

2 Answers2

1

OK. I finally found the problem. It is the package statement. The program is accepted after removing it... A bit mistake for me when copy-paste code from my IDE to submission form.. But there are some interesting discussions here and thank everyone!

user690421
  • 422
  • 1
  • 5
  • 15
0

The logic here will overflow the stack. It goes searching for the next number in the sequence before caching the result of the function on the current one.

    int result = search(j, cache) + 1;
    if (i <= n) {
        cache[(int)(i - 1)] = result;
    }
    return result;
clwhisk
  • 1,805
  • 1
  • 18
  • 17
  • 1
    Of course it has to compute the result before it can cache it. That would only overflow the stack if the sequence is too long to support the recursive solution. – ruakh Jan 23 '14 at 23:57