Example #1
0
def _pointing_pairs_test(s, region, verbose=0):
    """
    :type s: Sudoku
    :type region: set
    :type verbose: int
    """
    changes = 0
    freq = collections.defaultdict(set)
    taken_poss = set()
    for loc in region:
        for poss in s.fields[loc]:
            if len(s.fields[loc]) == 1:
                taken_poss = taken_poss | s.fields[loc]
                continue
            freq[poss].add(loc)
    for poss in taken_poss:
        try:
            freq.pop(poss)
        except KeyError:
            pass
    for poss, locs in freq.items():
        for _, area in s.areas.items():
            if not locs.issubset(area):
                continue
            for loc in region - locs:
                old_possibles = s.fields[loc]
                new_possibles = old_possibles - {poss}
                change = len(old_possibles - new_possibles)
                assert len(new_possibles) != 0
                if change:
                    changes += change
                    if verbose:
                        Colors.yellow(REMOVE.format(old_possibles, poss, loc))
                    s.fields[loc] = new_possibles
    return changes
Example #2
0
def _hidden_singles(s, region, verbose=0):
    changes = 0
    freq = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    locations = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    for loc in region:
        for poss in s.fields[loc]:
            freq[poss] += 1
            locations[poss] = loc
    for poss in range(1, 10):
        if freq[poss] == 1:
            loc = locations[poss]
            changes += len(s.fields[loc]) - 1
            if verbose >= 3:
                Colors.yellow(REMOVE.format(loc, s.fields[loc], poss))
            s.fields[loc] = {poss}
    return changes
Example #3
0
 def solve_current_puzzle_file(self, verbose=0, chucksize=42):
     changes = 0
     count = 0
     solved = 0
     start = time()
     middle_time = time()
     try:
         Colors.yellow(self.update.format(0, 0, 0, 0, 0), end="\r")
         while True:
             su = self.next_sudoku()
             count += 1
             if verbose >= 2:
                 Colors.blue("[*] Puzzle #{}".format(count))
             if verbose >= 4:
                 su.print()
             changes += self.solve_current_sudoku(verbose)
             if verbose >= 4:
                 su.print()
             if self.check_sudoku(su, verbose):
                 solved += 1
             if verbose == 1 and count % chucksize == 0:
                 total_duration = time() - start
                 duration = time() - middle_time
                 middle_time = time()
                 Colors.yellow(self.update.format(count,
                                                  changes,
                                                  (solved / count) * 100,
                                                  total_duration,
                                                  chucksize / duration),
                               end="\r")
             # input("Press Enter to continue...")
     except StopIteration:
         if verbose >= 2:
             Colors.blue("[*] End of puzzle file.")
         pass
     end = time()
     total_time = end - start
     status_message = self.status.format(self.current_puzzles,
                                         changes,
                                         solved,
                                         count,
                                         (solved / count) * 100,
                                         total_time,
                                         count / total_time)
     if verbose >= 2:
         print(status_message)
     return changes, solved, count, status_message
Example #4
0
def _eliminate_from_regions(s, source_loc, poss, verbose=0):
    """
    :type s: Sudoku
    :type source_loc: int
    :type poss: set
    :type verbose: int
    :return:
    """
    changes = 0
    target_locs = s.matching_regions_single(s, source_loc)
    for loc in target_locs:
        if poss.issubset(s.fields[loc]):
            changes += 1
            if verbose >= 3:
                Colors.yellow(REMOVE.format(source_loc, poss, loc, s.fields[loc]))
            s.fields[loc] = s.fields[loc] - poss
    return changes
Example #5
0
def _pointing_pairs(s, locs, verbose=0):
    """
    :type s: Sudoku
    :type locs: set
    :type verbose: int
    """
    changes = 0
    freq = collections.defaultdict(list)
    for loc in locs:
        for poss in s.fields[loc]:
            freq[poss].append(loc)
    for poss, pair_locs in {p: set(ls) for p, ls in freq.items() if len(ls) in (2, 3)}.items():
        target_locs = s.matching_regions(s, pair_locs)
        for loc in target_locs:
            if poss in s.fields[loc]:
                changes += 1
                s.fields[loc].remove(poss)
                if verbose:
                    Colors.yellow(REMOVE.format(pair_locs, poss, loc))
                assert len(s.fields[loc]) > 0
    return changes
Example #6
0
def _hidden_singles_test(s, region, verbose=0):
    changes = 0
    freq = collections.defaultdict(list)
    for loc in region:
        for poss in s.fields[loc]:
            freq[poss].append(loc)
    for poss, locs in freq.items():
        if len(locs) > 1:
            continue
        for loc in region:
            if loc in locs:
                continue
            old_possibles = s.fields[loc]
            new_possibles = old_possibles - {poss}
            change = len(old_possibles - new_possibles)
            if change:
                changes += change
                if verbose >= 3:
                    Colors.yellow(REMOVE.format(loc, s.fields[loc], poss))
                s.fields[loc] = new_possibles
    return changes
Example #7
0
def _find_hidden_pairs(s, region, verbose=0):
    changes = 0
    freq = collections.defaultdict(set)
    already_set = 0
    for loc in region:
        length = len(s.fields[loc])
        if length == 1:
            already_set += 1
            continue
        for poss in s.fields[loc]:
            freq[poss].add(loc)
    pairs = []
    taken_poss = set()
    max_length = 9 - already_set
    for length in reversed(range(2, max_length + 1)):
        try:
            for candidates in itertools.combinations(freq, length):
                all_locs = set()
                all_poss = set()
                for p in candidates:
                    all_locs = all_locs | freq[p]
                    all_poss = all_poss | {p}
                if len(all_locs) == max_length:
                    raise StopIteration
                for (poss, locs) in pairs:
                    if all_poss.issubset(poss):
                        raise StopIteration
                if len(all_poss) == len(all_locs):
                    # Leaves a pair that is not a pair
                    # So...
                    # There are false hits, or freq should be redone for each iteration (meaning, return changes)
                    changes += _remove_pairs(s, all_poss, all_locs, verbose)
                    pairs.append((all_poss, all_locs))
                    taken_poss = taken_poss | all_poss
        except StopIteration:
            continue
    if len(pairs) == 0:
        return changes
    for poss, locs in pairs:
        for loc in region:
            old_possibles = s.fields[loc]
            if loc in locs:
                new_possibles = old_possibles & poss
                change = len(old_possibles - new_possibles)
                if change:
                    if verbose >= 3:
                        Colors.yellow(REMOVE.format(locs, old_possibles - poss, loc, old_possibles))
                    s.fields[loc] = new_possibles
                    changes += change
            else:
                new_possibles = old_possibles - poss
                change = len(old_possibles - new_possibles)
                if change:
                    if verbose >= 3:
                        Colors.yellow(REMOVE.format(locs, poss, loc, old_possibles))
                    s.fields[loc] = new_possibles
                    changes += change
            # change = len(old_possibles - new_possibles)
            # if change:
            #     if verbose >= 3:
            #         Colors.yellow(REMOVE.format(locs, poss, loc, old_possibles))
            #     s.fields[loc] = new_possibles
            #     changes += change
    # if changes:
    #     print("Boo!")
    return changes