Example #1
0
def solve(takuzu):
    '''Solve a puzzle using backtracking (also a fall back for the human solver).'''

    queue = [takuzu]

    # DEBUG
    spots = 0
    for row in range(takuzu.size):
        for col in range(takuzu.size):
            if not takuzu.get(row, col):
                spots += 1

    logging.debug('Starting backtracker, {} possibilities to try ({} spots)'.format(
        2 ** spots,
        spots
    ))
    # /DEBUG

    while queue:
        takuzu = queue.pop()
        logging.animate(takuzu)
        logging.debug('Current board:\n' + str(takuzu).strip())

        # Solved, we're done!
        if takuzu.is_solved():
            return takuzu

        # If we don't have a valid solution, stop looking on this branch
        if not takuzu.is_valid():
            continue

        # Otherwise, find one empty spot and try both possiblities
        def enqueue():
            for row in range(takuzu.size):
                for col in range(takuzu.size):
                    if not takuzu.get(row, col):
                        for value in '01':
                            queue.append(takuzu.set(row, col, value))
                        return
        enqueue()

    return False
Example #2
0
def solve(takuzu):
    '''
    Solve a puzzle using a hybrid model.

    Start with the human solver.
    Every time you get stuck, guess at a spot.
    Switch back to the human solver (backtracking to step 2 on failures).
    '''

    queue = [takuzu]

    # DEBUG
    spots = 0
    for row in range(takuzu.size):
        for col in range(takuzu.size):
            if not takuzu.get(row, col):
                spots += 1

    logging.debug('Starting hybrid backtracker, {} possibilities to try ({} spots)'.format(
        2 ** spots,
        spots
    ))
    # /DEBUG

    while queue:
        takuzu = queue.pop()

        # Solved, we're done!
        if takuzu.is_solved():
            return takuzu

        # If we don't have a valid solution, stop looking on this branch
        if not takuzu.is_valid():
            continue

        # Try to advance using the human rules until they all fail
        while True:
            logging.animate(takuzu)
            logging.debug('Current board:\n' + str(takuzu).strip())
            updated = False
            for rule in RULES:
                logging.debug('Trying {}'.format(rule))
                next_takuzu = rule(takuzu)

                if next_takuzu:
                    takuzu = next_takuzu
                    updated = True
                    break

            if not updated:
                break

        # Solved, we're done!
        if takuzu.is_solved():
            return takuzu

        # Once they've failed, find one empty spot and try both possiblities
        def enqueue():
            for row in range(takuzu.size):
                for col in range(takuzu.size):
                    if not takuzu.get(row, col):
                        for value in '01':
                            queue.append(takuzu.set(row, col, value))
                        return
        enqueue()


    return False