Нужна помощь в портировании Java на Ruby. Странное поведение - PullRequest
2 голосов
/ 20 октября 2011

Я пытался понять это часами, но безуспешно. Я пытаюсь переписать этот Java-код на Ruby, и я подумал, что все готово, однако происходит нечто странное.

Java-метод:

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;
    }

}

Рубиновый метод:

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

Я сделал несколько следов соответствующих данных для обеих версий кода. Все точно так же, пока примерно на полпути. После этой точки массив digit [] в версии Java имеет все нули, кроме цифры 2 в цифре [2] (что правильно). Однако на данный момент в версии Ruby цифра [2] равна нулю вместе со всеми остальными элементами. Я очень озадачен тем, почему они, кажется, работают в идеальной гармонии так долго, пока не появится этот разрыв. Я даже не могу понять, почему digit [2] = 2 в версии Java (и я уверен, что код Java верный).

1 Ответ

1 голос
/ 20 октября 2011

Ваш @digit является переменной экземпляра, а не локальной. (Вот что означает @.) Он будет сбрасываться на все нули при каждом вызове analyze. И поскольку analyze вызывает себя на полпути, он заканчивает тем, что переписывает версию предыдущего вызова массивом всех нулей, прежде чем он начнет делать свое дело. (С другой стороны, в коде Java он является локальным - и каждый вызов имеет свой собственный digit.)

Попробуйте избавиться от @ в имени переменной и посмотрите, поможет ли это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...