OneRegister TopCoder long vs int
Autor: animeworld | Publicado: 2015-02-26T04:07:00-08:00



I build a solution for the problem OneRegister from TopCoder in Java.
It was giving the error:
java.lang.OutOfMemoryError: Java heap space

It took me a while to figure out that the problem was happening because I was using int instead of long!!!

Problem statement:
http://community.topcoder.com/stat?c=problem_statement&amp;pm=10992&amp;rd=14239&amp;rm=&amp;cr=10574855


package javaapplication1;

import java.util.LinkedList;

public class OneRegister {

    private final String NOT_POSSIBLE = ":-(";

    private String lexOrder(String s1, String s2) {
        char[] c1 = s1.toCharArray();
        char[] c2 = s2.toCharArray();
        for (int i = 0; i &lt; s1.length(); i++) {
            if (c1[i] == c2[i]) {
                continue;
            }
            if (c1[i] == '*') {
                return s1;
            }
            return s2;
        }
        throw new IllegalArgumentException("the two strings are equal");
    }

    class node {

        String p;
        int s; // &lt;&lt;&lt;&lt;&lt;!!!!! replace with long

        node(String program, int s) { // &lt;&lt;&lt;&lt;&lt;!!!!! replace with long
            p = program;
            this.s = s;
        }
    }

    public String getProgram(int s, int t) {
        if (s == t) {
            return "";
        }
        if (t == 0) {
            return "-";
        }
        if (t == 1) {
            return "/";
        }
        if (s &gt; t &amp;&amp; t % 2 != 0) {
            return ":-(";
        }

        LinkedList&lt;node&gt; list = new LinkedList&lt;&gt;();

        // +
        int sum = s + s; // &lt;&lt;&lt;&lt;&lt;!!!!! replace with long
        if (sum &lt;= t) list.add(new node("+", sum));

        // *
        int mul = s * s; // &lt;&lt;&lt;&lt;&lt;!!!!! replace with long
        if (mul &lt;= t &amp;&amp; mul != 1) list.add(new node("*", mul));

        // /
        list.add(new node("/", 1));

        String ans = NOT_POSSIBLE;
        while (!list.isEmpty()) {
            node n = list.poll();

            if (n.s == t) {
                if (ans.equals(NOT_POSSIBLE) || lexOrder(ans, n.p).equals(n.p)) {
                    ans = n.p;
                }
                continue;
            }

            if (!ans.equals(NOT_POSSIBLE) &amp;&amp; n.p.length() &gt;= ans.length()) {
                return ans;
            }

            // +
            sum = n.s + n.s;
            if (sum &lt;= t) list.add(new node(n.p + "+", sum));

            // *
            mul = n.s * n.s;
            if (mul &lt;= t &amp;&amp; mul != 1) list.add(new node(n.p + "*", mul));
        }

        return ans;
    }

    public static void main(String[] args) {
        OneRegister app = new OneRegister();
        System.out.println(app.getProgram(7, 392));
        System.out.println(app.getProgram(7, 256));
        System.out.println(app.getProgram(4, 256));
        System.out.println(app.getProgram(7, 7));
        System.out.println(app.getProgram(7, 9));
        System.out.println(app.getProgram(10, 1));
        System.out.println(app.getProgram(1000000000, 536870912));
        System.out.println(app.getProgram(1000000000, 999999999));
        System.out.println(app.getProgram(3, 402653184)); // &lt;&lt;&lt; PROBLEM HERE!
    }
}


Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
 at java.util.Arrays.copyOf(Arrays.java:2367)
 at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:130)
 at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:114)
 at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:415)
 at java.lang.StringBuilder.append(StringBuilder.java:132)
 at javaapplication1.OneRegister.getProgram(OneRegister.java:84)
 at javaapplication1.OneRegister.main(OneRegister.java:104)

If you replace int with long where it's commented in the code, then it will work!!

But why is that?


public class IntLongTest {
    public static void main(String[] args) {
        
        System.out.println(Integer.MAX_VALUE);  // 2147483647
        System.out.println(Long.MAX_VALUE);     // 9223372036854775807
        
        
        // 2147483647
        //  402653184
        //  200000000
        int x = 200000000;
        System.out.println(x * x); // -1090256896 what the fuck!!
    }
}


What happened was an Integer Overflow:
http://stackoverflow.com/questions/3001836/how-does-java-handle-integer-underflows-and-overflows-and-how-would-you-check-fo

Note that if you use a recursive solution, and also commit the mistake of using int instead of long, then you will get another exception:&nbsp;Exception in thread "main" java.lang.StackOverflowError

Petr solution:
http://community.topcoder.com/stat?c=problem_solution&amp;rd=14239&amp;rm=&amp;cr=10574855&amp;pm=10992


Syntax highlighted used&nbsp;http://tohtml.com/java/