简体   繁体   中英

How to convert this recursive Java method to iterative? (CodeJam challenge)

I'm trying to adapt this solution to the Code Jam's Dice Straight problem to Python. Unfortunately, it requires too deep recursion to work correctly in Python (unless both recursion limit and stack size are significantly increased). So I'm trying to convert this recursive method to iterative:

/**
 * Attempt to recursively free a die by selecting a different die for the same value.
 * @return true if the die has been freed, false if no other die can be found.
 */
boolean freeByShuffling(Die die) {
    assert die.valueUsing != null;
    // First check if we can just use another dice for the previous value
    for (Die otherDie : die.valueUsing.dice) {
        if (otherDie.valueUsing == null) {
            otherDie.valueUsing = die.valueUsing;
            die.valueUsing = null;
            return true;
        }
    }
    // Nope, we must free a die recursively
    diceVisitedWhileShuffling.add(die);
    for (Die otherDie : die.valueUsing.dice) {
        if (diceVisitedWhileShuffling.contains(otherDie)) continue;
        if (freeByShuffling(otherDie)) {
            otherDie.valueUsing = die.valueUsing;
            die.valueUsing = null;
            return true;
        }
    }
    return false;
}

This is my Python code which doesn't quite work, although it solves most test cases:

def free_by_shuffling(self, die):
    assert die.current_value is not None

    stack = [(None, die)]
    found = False

    while stack:
        this_die, other_die = stack.pop()
        self.visited.add(other_die)

        if found:
            other_die.current_value = this_die.current_value
            this_die.current_value = None
            continue

        for next_die in other_die.current_value.dice:
            if next_die in self.visited:
                continue
            if next_die.current_value is None:
                found = True
                stack.append((other_die, next_die))
                break
        else:
            for next_die in other_die.current_value.dice:
                if next_die in self.visited:
                    continue
                stack.append((other_die, next_die))

    return found

How do I convert the original method to use iteration instead of recursion?

This Python implementation works well for both 'small' and 'large' input files:

def free_by_shuffling(self, die):
    assert die.current_value is not None

    stack = [die]
    found = False

    while stack:
        this_die = stack.pop()

        if found:
            if stack:
                this_die.current_value = stack[-1].current_value
                stack[-1].current_value = None
            continue

        for other_die in this_die.current_value.dice:
            if other_die.current_value is None:
                stack.extend((this_die, other_die))
                found = True
                break
        else:
            self.visited.add(this_die)

            for other_die in this_die.current_value.dice:
                if other_die not in self.visited:
                    stack.extend((this_die, other_die))
                    break
            else:
                if stack:
                    for other_die in stack[-1].current_value.dice:
                        if other_die not in self.visited:
                            stack.append(other_die)
                            break
    return found

Any comments and suggestions are welcome.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM