tags:

views:

506

answers:

2
+2  Q: 

Uva's 3n+1 problem

I'm solving Uva's 3n+1 problem and I don't get why the judge is rejecting my answer. The time limit hasn't been exceeded and the all test cases I've tried have run correctly so far.

   import java.io.*;



public class NewClass{

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException {

        int maxCounter= 0; 
        int input; 

        int lowerBound; 
        int upperBound; 
        int counter;
        int numberOfCycles;
        int maxCycles= 0;
        int lowerInt;
        BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
        String line = consoleInput.readLine();
        String [] splitted =  line.split(" ");

        lowerBound = Integer.parseInt(splitted[0]);
        upperBound = Integer.parseInt(splitted[1]);


        int [] recentlyused =  new int[1000001];



if (lowerBound > upperBound )
{
    int h = upperBound;
    upperBound = lowerBound;
    lowerBound = h;

}
lowerInt = lowerBound;
        while (lowerBound <= upperBound)
        {
            counter = lowerBound;
            numberOfCycles = 0;


            if (recentlyused[counter] == 0)
            {
                while ( counter != 1 )
                {


                        if (recentlyused[counter] != 0)
                        {

                        numberOfCycles = recentlyused[counter] + numberOfCycles;
                        counter = 1;
                        }
                        else
                        {
                            if (counter % 2 == 0)
                            {
                            counter = counter /2;
                            }
                            else
                            {
                            counter = 3*counter + 1;
                            }
                            numberOfCycles++;
                        }

                }
            }
            else
            {

            numberOfCycles = recentlyused[counter] + numberOfCycles;
            counter = 1;
            }

            recentlyused[lowerBound] = numberOfCycles;



            if (numberOfCycles > maxCycles)
            {
            maxCycles = numberOfCycles;
            }

            lowerBound++;
        }
        System.out.println(lowerInt +" "+ upperBound+ " "+ (maxCycles+1));

    }


}
+2  A: 

Are you making sure to accept the entire input? It looks like your program terminates after reading only one line, and then processing one line. You need to be able to accept the entire sample input at once.

AlbertoPL
yes, I'm sure it's reading the whole input.
omgzor
I just tested it and I couldn't type in more than a single line... how are you inputting into the program?
AlbertoPL
damn... you're right. I thought I was working on a previous version.
omgzor
well, I did the correction, but the judge is still rejecting the answer.
omgzor
A: 

If I understand correctly you are using a memoizing approach. You create a table where you store full results for all the elements you have already calculated so that you do not need to re-calculate results that you already know (calculated before).

The approach itself is not wrong, but there are a couple of things you must take into account. First, the input consists of a list of pairs, you are only processing the first pair. Then, you must take care of your memoizing table limits. You are assuming that all numbers you will hit fall in the range [1...1000001), but that is not true. For the input number 999999 (first odd number below the upper limit) the first operation will turn it into 3*n+1, which is way beyond the upper limit of the memoization table.

Some other things you may want to consider are halving the memoization table and only memorize odd numbers, since you can implement the divide by two operation almost free with bit operations (and checking for even-ness is also just one bit operation).

David Rodríguez - dribeas
I noticed that as well, there is potentially a lot of wasted table space.
AlbertoPL
well, the page on algorithmist says:To get the problem in good time you must create an array with size 1000000 then using recursion with memoization trying to not computing any value more than one will be good for 0.200 sec
omgzor
http://www.algorithmist.com/index.php/UVa_100
omgzor
Yes of course, but say the range is from 100 - 200, you start storing those values at array index 100, which isnt the best. Also, it's possible your solution isn't fast enough, because when you hit certain values of counter, you're not remember recently hit values of counter, thus wasting time. When the counter is the same number as it was in a previous loop, you should know the answer at that point.
AlbertoPL
I am not discussing the general solution, but rather your implementation of it. You are not being careful on the indices you pass to the memorization array (if the input is big enough: 10^6 - 1) you will hit positions beyond the end of the array triggering an ArrayOutOfBounds (I think that is the name, did not code Java for long) exception and the code will break. Also note that you are not really doing what the proposed algorithm states: you only memorize the elements in the input range. This means that you will repeat calculations.
David Rodríguez - dribeas
Say the range is [2,7], first you calculate the sequence for 2, that starts with [2, 7 (which is 3*2 + 1) ... ], the value for 7 is not being cached in the results array, when you later hit the 7 you will recalculate it. That is the reason while the suggested algorithm uses recursion, as it is the easiest way of remembering the solutions to all intermediate results.
David Rodríguez - dribeas
So there are at least 2 things you must do to get your code up and running: beware of array limits and memorize _all_ intermediate results.
David Rodríguez - dribeas
Two comments above, the example numbers are wrong, it should not be [2,7], but rather [3, 10]. Once the numbers are corrected, the rest of the comment stands true.
David Rodríguez - dribeas