如何创建所有部分组合

时间:2017-03-20 03:57:04

标签: sql postgresql combinations

我试图解决一个谜题,通过使用一些狡猾和蛮力我达到48级。但现在想用一些Memoization来重用计算。

我有一些表格:

puzzles: (puzzle_id, level, flips)
CONSTRAINT puzzle_id_pk PRIMARY KEY (puzzle_id)

puzzle_rows  (puzzle_id, row_id, row_flips)
CONSTRAINT puzzle_row_pk PRIMARY KEY (puzzle_id, row_id),
CONSTRAINT puzzle_row_puzzle_id_fk FOREIGN KEY (puzzle_id)

pieces: (puzzle_id, piece_id, flips_row1, flips_row2, flips_row3, flips_row4, flips_row5)
CONSTRAINT piece_id_pk PRIMARY KEY (puzzle_id, piece_id),
CONSTRAINT piece_puzzle_id_fk FOREIGN KEY (puzzle_id)

这个级别是18件:

+-----------+-----------+-------------+-------------+-------------+-------------+-------------+
| puzzle_id |  piece_id |  flips_row1 |  flips_row2 |  flips_row3 |  flips_row4 |  flips_row5 |
+-----------+-----------+-------------+-------------+-------------+-------------+-------------+
|         1 |         1 |           2 |           1 |           2 |           0 |           0 |
|         1 |         2 |           2 |           1 |           0 |           0 |           0 |
|         1 |         3 |           2 |           2 |           2 |           0 |           0 |
|         1 |         4 |           3 |           1 |           3 |           0 |           0 |
|         1 |         5 |           4 |           3 |           3 |           3 |           0 |
|         1 |         6 |           3 |           0 |           0 |           0 |           0 |
|         1 |         7 |           3 |           1 |           3 |           0 |           0 |
|         1 |         8 |           3 |           4 |           1 |           2 |           2 |
|         1 |         9 |           1 |           0 |           0 |           0 |           0 |
|         1 |        10 |           2 |           2 |           2 |           0 |           0 |
|         1 |        11 |           2 |           3 |           4 |           0 |           0 |
|         1 |        12 |           1 |           3 |           1 |           3 |           2 |
|         1 |        13 |           1 |           2 |           2 |           0 |           0 |
|         1 |        14 |           2 |           4 |           1 |           1 |           0 |
|         1 |        15 |           1 |           2 |           1 |           0 |           0 |
|         1 |        16 |           1 |           1 |           3 |           0 |           0 |
|         1 |        17 |           3 |           2 |           3 |           1 |           0 |
|         1 |        18 |           1 |           3 |           2 |           2 |           0 |
+-----------+-----------+-------------+-------------+-------------+-------------+-------------+

我需要帮助填写表solution_pieces所有的组合。在这种情况下,2^18 = 262144的想法是首先检查行奇偶校验以避开搜索空间。 (SUM(pieces.flips_row1) + puzzle_row[1].flips) % 3 = 0

例如,如下图所示,第一行有{14,15}件:pieces total flips (3) + row_flips (3) = 6 % 3 = 0

solutions: (solution_id, puzzle_id, 
           flips_row1, flips_row2, flips_row3, flips_row4, flips_row5)
CONSTRAINT solution_pk PRIMARY KEY (solution_id),
CONSTRAINT solution_puzzle_id_fk FOREIGN KEY (puzzle_id)

solution_pieces: (solution_id, piece_id)
CONSTRAINT solution_pieces_pk PRIMARY KEY (solution_id, piece_id),
CONSTRAINT solution_pieces_solution_id_fk FOREIGN KEY (solution_id)
CONSTRAINT solution_puzzle_id_fk FOREIGN KEY (puzzle_id)

所以我需要像这样填写表格solution_pieces

 solution_id   piece_id
    1             1
    ....                  -- solutions with only one piece
    18            18

    19            1
    19            2
    20            1 
    20            3
    ....                  -- solutions with two pieces
    262144       {1..18}  -- solution with all pieces

然后,表solutions只填充GROUP BY

enter image description here

1 个答案:

答案 0 :(得分:0)

使用Erwin Brandstetter解决方案,只需添加unexst即可将数组转换为行。

WITH cte as (
    SELECT row_number() over () as rn, *
    FROM f_combos(array(SELECT piece_id FROM pieces ORDER BY piece_id)) 
)
SELECT rn, unnest( f_combos ) AS id
FROM cte    
ORDER BY 1;