Skip to content

Instantly share code, notes, and snippets.

@adrian17
Created February 23, 2015 14:40
Show Gist options
  • Save adrian17/3a6def9f9ba22076233c to your computer and use it in GitHub Desktop.
Save adrian17/3a6def9f9ba22076233c to your computer and use it in GitHub Desktop.
Kakuro solver in Python
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()
@dandax123
Copy link

dandax123 commented Apr 1, 2019

Please, can you give a sample input format and a sample output format.
Also can this code check if multiple possible solutions exists

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment