Created
February 23, 2015 14:40
-
-
Save adrian17/3a6def9f9ba22076233c to your computer and use it in GitHub Desktop.
Kakuro solver in Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import itertools | |
from copy import deepcopy | |
def possible_combinations(values, n, total): | |
# generate all combinations of given values with given sum | |
return [combination for combination in itertools.combinations(values, n) if sum(combination) == total] | |
def make_aval(board, clues): | |
""" | |
Generates a set of all digits you can use in each cell, just like you do in sudoku board | |
""" | |
for total, coords in clues: | |
# a set of all the digits you can use, excluding the ones already used | |
all_aval = set(range(1, 10)) - set(board[coord]["val"] for coord in coords) | |
# a number of all cells you still have to fill | |
n_empty = len([1 for coord in coords if board[coord]["val"] == 0]) | |
# a sum you have to get, minus the numbers already written | |
total -= sum(board[coord]["val"] for coord in coords) | |
# all combinations of digits you can enter | |
combinations = possible_combinations(all_aval, n_empty, total) | |
# a set of all the digits you can enter in these cells based on this clue | |
all_aval = {num for combination in combinations for num in combination} | |
# only these digits can be used in these cells, so let's intersect the available digit sets | |
for coord in coords: | |
board[coord]["aval"] &= all_aval | |
def load_data(): | |
first_board = {} | |
clues = [] | |
_, *lines = open("inputs.txt").read().splitlines() | |
for line in lines: | |
total, *coords = line.split() | |
for coord in coords: | |
first_board[coord] = {"val": 0, "aval": set(range(1, 10))} | |
clues.append((int(total), coords)) | |
return first_board, clues | |
def print_board(board): | |
for key in sorted(board): | |
print(key, board[key]) | |
print("") | |
def main(): | |
boards = [] | |
solutions = [] | |
first_board, clues = load_data() | |
boards.append(first_board) | |
# while there are still not-finished boards to analyze: | |
while boards: | |
# take the last one | |
board = boards.pop() | |
# generate all the available digits | |
make_aval(board, clues) | |
# if there is any empty cell with no available digits, the board is invalid | |
if any(cell["val"] == 0 and len(cell["aval"]) == 0 for cell in board.values()): | |
continue | |
# if all cells are filled, we've found a solution | |
if all(cell["val"] != 0 for cell in board.values()): | |
solutions.append(board) | |
continue | |
# find the first empty cell you can try filling | |
coord = next(coord for coord in sorted(board) if board[coord]["val"] == 0) | |
# for each digit you can use in this cell: | |
for candidate in board[coord]["aval"]: | |
new_board = deepcopy(board) | |
# insert this digit in this cell | |
new_board[coord]["val"] = candidate | |
boards.append(new_board) | |
for solution in solutions: | |
print_board(solution) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Please, can you give a sample input format and a sample output format.
Also can this code check if multiple possible solutions exists