九宫格问题、16宫格

本文介绍了九宫格和16宫格问题的解决方法,包括全排列、检查函数、数字分组、行和列相等的调整以及验证函数。通过递归和非递归算法探讨了不同大小宫格的排列,最终得出16宫格的48个完美解。同时,文章提到了一些解决问题中涉及的数学技巧,如排列组合、取模取余等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

九宫格(Lo Shu Square)问题

将1到9的数字按照一定方式填入九宫格内。使得每一列、每一行以及两条对角线上的值都相等。

全排列(递归)

首先,用枚举法,生成各种(3, 3)的二维数组:

def perm(li):
    """递归实现列表的全排列
    如果输入是[1],那么返回[[li],]表示有一种排列
    如果输入是[1, 2],期望的返回的是[[1, 2], [2, 1]],这是要之后的递归实现的
    """
    if len(li) <= 1:
        return [li]
    ret = []
    for i in range(len(li)):
        s1 = li[i:i + 1]  # 取出一个元素,组成一个列表
        rest = li[:i] + li[i + 1:]  # 剩余的元素组成一个列表
        p = perm(rest)
        for j in p:  # 迭代每一种排列
            ret.append(s1 + j)  # 和之前取出的1个元素进行拼接
    return ret

简单验证一下:

>>> perm([1, 2, 3])
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]

递归算法比较费时,如果是9个数字的全排列,要1秒左右。如果数组更大比如(4, 4)就几乎跑不完了:

995 ms ± 12.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

检查函数

各种求和,然后进行检查:

def is_lo_shu_square(arr):
    """接收numpy的二维数组"""
    if np.shape(arr)[0] != np.shape(arr)[1]:
        return  False
    d = np.shape(arr)[0]
    n = np.sum(arr) / d
    for i in np.sum(arr, axis=0):
        if i != n:
            return False
    for i in np.sum(arr, axis=1):
        if i != n:
            return False
    if np.sum(np.eye(d, dtype=int) * arr) != n:  # 检查对角线
        return False
    if np.sum(np.eye(d, dtype=int)[::-1] * arr) != n:  # 检查次对角线
        return False
    return True

简单验证一下:

>>> np.array(([1, 1], [1, 1]))
array([[1, 1],
       [1, 1]])
>>> a = np.array(([1, 1], [1, 1]))
>>> is_lo_shu_squar(a)
True

计算结果

>>> li = [i+1 for i in range(9)]
>>> for i in perm(li):
    a = np.array(i).reshape(3, 3)
    if is_lo_shu_square(a):
        print(a)

[[2 7 6]
 [9 5 1]
 [4 3 8]]
[[2 9 4]
 [7 5 3]
 [6 1 8]]
[[4 3 8]
 [9 5 1]
 [2 7 6]]
[[4 9 2]
 [3 5 7]
 [8 1 6]]
[[6 1 8]
 [7 5 3]
 [2 9 4]]
[[6 7 2]
 [1 5 9]
 [8 3 4]]
[[8 1 6]
 [3 5 7]
 [4 9 2]]
[[8 3 4]
 [1 5 9]
 [6 7 2]]

全排列(非递归)

标准库itertools里提供了排列的函数,算法比较复杂j就不研究了,顺便还有组合的函数:

import itertools
>>> l
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值