user977680
user977680

Reputation: 25

Need help porting Java to Ruby. Strange behavior

I've been trying to figure this out for hours with no success. I'm trying to re-write this Java code into Ruby and I thought I was done, however, something strange is happening.

Java method:

static void analyze (int n, int seriesLen)
{
    int digit[] = new int [9];
    int d = 0;
    int m = n;

    series[seriesLen - 1] = n;

    while (m >= 10) {
        digit[d++] = m % 10;
        m /= 10;
    }
    digit[d++] = m;
    for (int subset = (1 << d) - 2; subset > 0; subset--) {
        int j = 0;
        int s = subset;
        int pos = d - 1;
        /* find first digit */
        while ((s & 1) == 0) {
            s >>= 1;
            pos--;
        }

        /* if first digit is a 0, move on */

        if (digit[pos] == 0) continue;

        do {
            if ((s & 1) == 1) j = j*10 + digit[pos];
            s >>= 1;
            pos--;
            } while (s > 0);


        if (j > 1 && n % j == 0) {
            int k = 0;
            s = subset ^ ((1 << d) - 1);
            pos = d - 1;

            while (s > 0) {
                if ((s & 1) == 1) k = k*10 + digit[pos];
                s >>= 1;
                pos--;
            }

            analyze (k, seriesLen + 1);
        }
    }

    System.out.println("seriesLen: " + seriesLen);
    if (betterSeries (seriesLen)) {
        for (int i = 0; i < seriesLen; i++) {
            best[i] = series[i];
        }
        bestLen = seriesLen;
    }

}

Ruby method:

def analyze(n, seriesLen)
    @digit = [0,0,0,0,0,0,0,0,0]
    m = n
    d = 0
    $series[seriesLen-1] = n

    while(m >= 10)
        @digit[d] = (m % 10)
        d = d + 1
        m /= 10
    end
    @digit[d] = m
    d = d + 1
    subset = (1 << d) - 2
    while (subset > 0)
        j = 0
        s = subset
        pos = d - 1
        while ((s & 1) == 0)
            s >>= 1
            pos -= 1
        end
        if (@digit[pos] == 0):
            subset -= 1
            next
        end
        begin
            j = (j*10 + @digit[pos]) if ((s & 1) == 1)
            s >>= 1
            pos -= 1
        end while s > 0
        if (j > 1 && n % j == 0):
            k = 0
            s = (subset) ^ ((1 << d) - 1)
            pos = d - 1
            while (s > 0)
                k = (k*10 + @digit[pos]) if ((s & 1) == 1)
                s >>= 1
                pos -= 1
            end

            analyze(k, seriesLen + 1)
        end

        subset -= 1
    end

    if (betterSeries(seriesLen)):
        for i in 0...seriesLen
            $best[i] = $series[i]
        end
        $bestLen = seriesLen;
    end
end

I did some traces on the relevant data for both versions of the code. Everything is exactly the same until about halfway through. After this point, the digit[] array in the Java version has all zeros except for a 2 at digit[2] (which is correct). However, at this point in the Ruby version, digit[2] is zero along with all the other elements. I am very confused about why they seem to work in perfect harmony for so long until this discontinuity appears. I can't even figure out why digit[2] = 2 in the Java version (and I am positive the Java code is correct).

Upvotes: 2

Views: 117

Answers (1)

cHao
cHao

Reputation: 86525

Your @digit is an instance variable, not a local. (That's what the @ means.) It will get reset to all zeros every time you call analyze. And since analyze calls itself halfway through, it ends up overwriting the previous call's version with an array of all zeros before it starts doing its thing. (In the Java code, on the other hand, it's a local -- and each call has its own digit.)

Try getting rid of the @ in the variable name, and see if that helps.

Upvotes: 1

Related Questions