Find all possible factors in the KenKen Multiply Domain

The KenKen puzzle is a Latin square divided into domains associated with the edge: one cell, two adjacent cells inside the same row or column, three cells located in a row or in ell, etc. Each domain has a label, gives the target number and one arithmetic operation (+ - * /), which must be applied to the numbers in the cells of the domain to get the target number. (If there is only one cell in the domain, the operator is not specified, just the goal --- the square is solved for you. If the operator is either /, then there are only two cells in the domain.) The goal of the puzzle is to (re) construct a Latin square consistent with domain boundaries and labels. (I think I only saw the puzzle with a unique solution once.)

The number in the cell can vary from 1 to the width (height) of the puzzle; usually puzzles are 4 or 6 cells per side, but consider puzzles of any size. Domains in published puzzles (4x4 or 6x6) usually have no more than 5 cells, but, again, this does not seem like a hard limit. (However, if the puzzle had only one domain, there would be as many solutions as the Latin squares of this dimension ...)

The first step in writing the KenKen solver is to create routines that can lead to possible combinations of numbers in any field, ignoring domain geometry first. (A linear area, like a line of three cells, cannot have duplicate numbers in an allowed puzzle, but at the moment we are ignoring this.) I was able to write a Python function that in each case handles additive labels: give it the width of the puzzle, the number of cells in domain and the target amount, and it returns a list of tuples of real numbers that add up to the target.

The case of multiplication eludes me. I can get a dictionary with keys equal to the products achievable in a domain of a given size, in a puzzle of a given size, and the values ​​are lists of tuples containing factors that give the product, but I can not make out the case but not bad.

, . ( Fascicle 3 4 Knuth TAOCP, "" , , . !)

"" , , , 100 2 50 .

+3
1

: , , , .

, , , , , . ( , , , , , max_entry, , n_boxes_in_domain.)

, max_entry=6, n_boxes_in_domain=3, target_number=20: 20 (2, 2, 5); (2, 2, 5) (1, 4, 5).

, , . , , , , . ( , ):

def xgroup(items):
    L = len(items)
    for i in range(L-1):
        for j in range(1, L):
            temp = list(items)
            a = temp.pop(j)
            b = temp.pop(i)
            temp.insert(0, a*b)
            yield temp
            for x in xgroup(temp):
                yield x

def product_combos(max_entry, n_boxes, items):
    r = set()
    if len(items)<=n_boxes:
        r.add(tuple(items))
    for i in xgroup(items):
        x = i[:]
        x.sort()
        if x[-1]<=max_entry and len(x)<=n_boxes:
            r.add(tuple(x))
    r = [list(i) for i in r]
    r.sort()
    for i in r:
        while len(i)<n_boxes:
            i.insert(0, 1)
    return r

, , ,

max_entry=6, n_boxes=3, items=(2,2,5)
[2, 2, 5]
[1, 4, 5]

, , , target_number=2106

max_entry=50, n_boxes=6, items=(2,3,3,3,3,13)
[2, 3, 3, 3, 3, 13]
[1, 2, 3, 3, 3, 39]
[1, 2, 3, 3, 9, 13]
[1, 1, 2, 3, 9, 39]
[1, 1, 2, 3, 13, 27]
[1, 1, 2, 9, 9, 13]
[1, 1, 1, 2, 27, 39]
[1, 3, 3, 3, 3, 26]
[1, 3, 3, 3, 6, 13]
[1, 1, 3, 3, 6, 39]
[1, 1, 3, 3, 9, 26]
[1, 1, 3, 3, 13, 18]
[1, 1, 3, 6, 9, 13]
[1, 1, 1, 3, 18, 39]
[1, 1, 1, 3, 26, 27]
[1, 1, 1, 6, 9, 39]
[1, 1, 1, 6, 13, 27]
[1, 1, 1, 9, 9, 26]
[1, 1, 1, 9, 13, 18]
+4

Source: https://habr.com/ru/post/1709894/


All Articles