用排除推导的方式,得到数独的解

第一部分是,定义一些字典,用来存一些数据

# 存每个格子,已经确定的数,不确定的是‘0’
dic_shu = {
    '11': 0, '12': 0, '13': 0, '14': 0, '15': 0, '16': 0, '17': 0, '18': 0, '19': 0,
    '21': 0, '22': 0, '23': 0, '24': 0, '25': 0, '26': 0, '27': 0, '28': 0, '29': 0,
    '31': 0, '32': 0, '33': 0, '34': 0, '35': 0, '36': 0, '37': 0, '38': 0, '39': 0,
    '41': 0, '42': 0, '43': 0, '44': 0, '45': 0, '46': 0, '47': 0, '48': 0, '49': 0,
    '51': 0, '52': 0, '53': 0, '54': 0, '55': 0, '56': 0, '57': 0, '58': 0, '59': 0,
    '61': 0, '62': 0, '63': 0, '64': 0, '65': 0, '66': 0, '67': 0, '68': 0, '69': 0,
    '71': 0, '72': 0, '73': 0, '74': 0, '75': 0, '76': 0, '77': 0, '78': 0, '79': 0,
    '81': 0, '82': 0, '83': 0, '84': 0, '85': 0, '86': 0, '87': 0, '88': 0, '89': 0,
    '91': 0, '92': 0, '93': 0, '94': 0, '95': 0, '96': 0, '97': 0, '98': 0, '99': 0,

}
# 存,每个方块(3*3),每行,每列,数字已确定的格子的数量
dic_jiu = {'fang': {
    '123_123': 0, '123_456': 0, '123_789': 0,
    '456_123': 0, '456_456': 0, '456_789': 0,
    '789_123': 0, '789_456': 0, '789_789': 0, },
    'heng': {'1_19': 0, '2_19': 0, '3_19': 0, '4_19': 0, '5_19': 0, '6_19': 0, '7_19': 0, '8_19': 0, '9_19': 0, },
    'shu': {'19_1': 0, '19_2': 0, '19_3': 0, '19_4': 0, '19_5': 0, '19_6': 0, '19_7': 0, '19_8': 0, '19_9': 0}
}
# 每个数,可能出现在方块中的坐标
# 2-9类似,不在重复
dic_1_9 = {
    1: {
        '123_123': [11, 12, 13, 21, 22, 23, 31, 32, 33],
        '123_456': [14, 15, 16, 24, 25, 26, 34, 35, 36],
        '123_789': [17, 18, 19, 27, 28, 29, 37, 38, 39],
        '456_123': [41, 42, 43, 51, 52, 53, 61, 62, 63],
        '456_456': [44, 45, 46, 54, 55, 56, 64, 65, 66],
        '456_789': [47, 48, 49, 57, 58, 59, 67, 68, 69],
        '789_123': [71, 72, 73, 81, 82, 83, 91, 92, 93],
        '789_456': [74, 75, 76, 84, 85, 86, 94, 95, 96],
        '789_789': [77, 78, 79, 87, 88, 89, 97, 98, 99],
    },
}
# 每行,每个数字,可能出现先的坐标,2-9不再重复
dic_1_9_heng = {
    1: {
        '1_19': [11, 12, 13, 14, 15, 16, 17, 18, 19],
        '2_19': [21, 22, 23, 24, 25, 26, 27, 28, 29],
        '3_19': [31, 32, 33, 34, 35, 36, 37, 38, 39],
        '4_19': [41, 42, 43, 44, 45, 46, 47, 48, 49],
        '5_19': [51, 52, 53, 54, 55, 56, 57, 58, 59],
        '6_19': [61, 62, 63, 64, 65, 66, 67, 68, 69],
        '7_19': [71, 72, 73, 74, 75, 76, 77, 78, 79],
        '8_19': [81, 82, 83, 84, 85, 86, 87, 88, 89],
        '9_19': [91, 92, 93, 94, 95, 96, 97, 98, 99],
    },
}
# 每列,每个数字,可能出现先的坐标,2-9不再重复
dic_1_9_shu = {
    1: {
        '19_1': [11, 21, 31, 41, 51, 61, 71, 81, 91],
        '19_2': [12, 22, 32, 42, 52, 62, 72, 82, 92],
        '19_3': [13, 23, 33, 43, 53, 63, 73, 83, 93],
        '19_4': [14, 24, 34, 44, 54, 64, 74, 84, 94],
        '19_5': [15, 25, 35, 45, 55, 65, 75, 85, 95],
        '19_6': [16, 26, 36, 46, 56, 66, 76, 86, 96],
        '19_7': [17, 27, 37, 47, 57, 67, 77, 87, 97],
        '19_8': [18, 28, 38, 48, 58, 68, 78, 88, 98],
        '19_9': [19, 29, 39, 49, 59, 69, 79, 89, 99],
    },
    
}

排除的方法
1.确定一个坐标,进行赋值
a.给坐标所属的块就是字典【dic_1_9】赋坐标的 int
b.给坐标所属行,字典【dic_1_9_heng】赋坐标int
c.给坐标所属列,字典【dic_1_9_shu】赋坐标int
2.确定一个坐标,排除
a.移除此数字,所属,方块、行、列,的所有其他值
b.移除别的数字,方块、行、列此坐标
3.字典(dic_1_9/dic_1_9_heng/dic_1_9_shu)中某块、或列、或行,已确定8个值,推出第九个值
4.某数字,某一方块内,仅剩两个坐标
a.两个坐标 横坐标一样,排除此数字此行坐标
b.连个坐标 竖坐标一样,排除此数字此列坐标

from jiaoben.shudu.shudu_count import *


class Testshudu:
    # 给单元格赋值
    def set_value(self, key, value: int):
        if dic_shu[key] != 0:
            print(f'出错了,dic_shu[{key}]={dic_shu[key]},不能再赋值:{value}')
        else:

            dic_shu[key] = value
            fang = self.get_suoshufang(key)
            dic_1_9[value][fang] = int(key)
            dic_1_9_heng[value][key[0]+'_19'] = int(key)
            dic_1_9_shu[value]["19_" + key[1]] = int(key)
            self.update_tianxieshu(key, value)
            self.get_remove_dic_by1(key, value)

    # 得到位置所属方位,左上、右上,上等
    def get_suoshufang(self, zuobiao: str):
        h = zuobiao[0]
        s = zuobiao[1]
        suoshu_fang = ''
        for fang_i in dic_jiu['fang'].keys():
            if h in fang_i[:3] and s in fang_i[3:]: suoshu_fang = fang_i
        return suoshu_fang

    # 判断坐标是否可以移除,并移除
    def remover_dic_1_9(self, remove_dic):

        num = remove_dic['num']
        fang = remove_dic['fang']
        zhi = remove_dic['zhi']
        remove_list = dic_1_9[num][fang]
        if isinstance(remove_list,list):
            if len(remove_list)>1 and zhi in remove_list:
                dic_1_9[num][fang].remove(zhi)
            if len(remove_list) == 1:
                self.set_value(str(remove_list[0]),num)
        if isinstance(dic_1_9_heng[num][str(zhi)[0]+'_19'],list):
            if len(dic_1_9_heng[num][str(zhi)[0]+'_19']) >1 and zhi in dic_1_9_heng[num][str(zhi)[0]+'_19']:
                dic_1_9_heng[num][str(zhi)[0] + '_19'].remove(zhi)
            if len(dic_1_9_heng[num][str(zhi)[0]+'_19']) == 1:
                self.set_value(str(dic_1_9_heng[num][str(zhi)[0]+'_19'][0]),num)
        if isinstance(dic_1_9_shu[num]["19_" + str(zhi)[1]],list):
            if len(dic_1_9_shu[num]["19_" + str(zhi)[1]]) >1 and zhi in dic_1_9_shu[num]["19_" + str(zhi)[1]]:
                dic_1_9_shu[num]["19_" + str(zhi)[1]].remove(zhi)
            if len(dic_1_9_shu[num]["19_" + str(zhi)[1]]) == 1:
                self.set_value(str(dic_1_9_shu[num]["19_" + str(zhi)[1]][0]),num)


    # 确定一个位置后,移除坐标坐在横竖两条线上的坐标
    def get_remove_dic_by1(self, zhi, num):
        other_num_fang = self.get_suoshufang(zhi)
        for i in range(1, 10):
            if i != num:
                remove_dic = {'num': i, 'fang': other_num_fang, 'zhi': int(zhi)}
                self.remover_dic_1_9(remove_dic)
        remove_h = self.get_list_by_hs('heng', zhi)
        for i in remove_h:
            fang = self.get_suoshufang(str(i))
            remove_dic = {'num': num, 'fang': fang, 'zhi': i}
            self.remover_dic_1_9(remove_dic)
        remove_s = self.get_list_by_hs('shu', zhi)
        for i in remove_s:
            fang = self.get_suoshufang(str(i))
            remove_dic = {'num': num, 'fang': fang, 'zhi': i}
            self.remover_dic_1_9(remove_dic)

    # 根据坐标判断
    def get_list_by_hs(self, h_or_s, zhi):
        r_zhi_l = []
        list = []
        xx = 0
        if h_or_s == 'heng':
            xx = int(zhi[1])
        if h_or_s == 'shu':
            xx = int(zhi[0])
        if xx in [1, 2, 3]:
            list = [4, 5, 6, 7, 8, 9]
        elif xx in [4, 5, 6]:
            list = [1, 2, 3, 7, 8, 9]
        elif xx in [7, 8, 9]:
            list = [1, 2, 3, 4, 5, 6]
        if h_or_s == 'heng':
            for i in list:
                h_z = int(zhi[0]) * 10
                r_zhi_l.append(h_z + i)
        if h_or_s == 'shu':
            for i in list:
                h_z = int(zhi[1])
                r_zhi_l.append(h_z + i * 10)
        return r_zhi_l

    def remove_get_two(self, num):
        for a in dic_1_9.keys():
            for b in dic_1_9[a].keys():
                linshi_list = dic_1_9[a][b]
                if isinstance(linshi_list, list) and len(linshi_list) == 2:
                    # 横坐标一样,说明这个数只能在 在这一行,移除当前行,别的坐标
                    if str(linshi_list[0])[0] == str(linshi_list[1])[0]:
                        remove_h = self.get_list_by_hs('heng', str(linshi_list[0]))
                        for i in remove_h:
                            fang = self.get_suoshufang(str(i))
                            remove_dic = {'num': a, 'fang': fang, 'zhi': i}
                            self.remover_dic_1_9(remove_dic)
                if isinstance(linshi_list, list) and len(linshi_list) == 2:
                    # 数字a,在当前方块,仅有两个坐标值,并且两个坐标竖坐标一致,可排除坐标坐在竖坐标其他方块中的坐标
                    if str(linshi_list[0])[1] == str(linshi_list[1])[1]:
                        remove_s = self.get_list_by_hs('shu', str(linshi_list[1]))
                        for i in remove_s:
                            fang = self.get_suoshufang(str(i))
                            remove_dic = {'num': a, 'fang': fang, 'zhi': i}
                            self.remover_dic_1_9(remove_dic)

    # 更新每个方块,每行、每列数值已确定格子的数量
    def update_tianxieshu(self, x, value):
        fang = self.get_suoshufang(x)
        heng = x[0] + '_19'
        shu = '19_' + x[1]
        dic_jiu['fang'][fang] += 1
        dic_jiu['heng'][heng] += 1
        dic_jiu['shu'][shu] += 1
        # 方块、横、竖 数值已确定格子数量=8,可推导出第9个格子的数值
        if dic_jiu['fang'][fang] == 8:
            self.get_8_1('fang', fang)
        if dic_jiu['heng'][heng] == 8:
            self.get_8_1('heng', heng)
        if dic_jiu['shu'][shu] == 8:
            self.get_8_1('shu', shu)

    # 根据 已确定数值的8个格子,得到第9个格子的  数值
    def get_8_1(self, fenlei, key):
        list_1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
        list_2 = []
        set_key = ''
        if fenlei == 'fang':
            for heng in key[:3]:
                for shu in key[4:]:
                    if dic_shu[heng + shu] != 0:
                        list_2.append(dic_shu[heng + shu])
                    else:
                        set_key = heng + shu

        if fenlei == 'heng':
            for i in range(1, 10):
                if dic_shu[key[0] + str(i)] != 0:
                    list_2.append(dic_shu[key[0] + str(i)])
                else:
                    set_key = key[0] + str(i)
        if fenlei == 'shu':
            for i in range(1, 10):
                if dic_shu[str(i) + key[-1]] != 0:
                    list_2.append(dic_shu[str(i) + key[-1]])
                else:
                    set_key = str(i) + key[-1]
        list3 = list(set(list_1) - set(list_2))
        self.set_value(set_key, list3[0])


def test_new():
    sd = Testshudu()
    test_dic = {'11': 5, '13': 2, '14': 4, '17': 3, '18': 6, '21': 6, '23': 4, '36': 6, '39': 2,
                '45': 2, '46': 8, '47': 5, '53': 7, '57': 8, '63': 9, '64': 7, '65': 5,
                '71': 8, '74': 6, '87': 9, '89': 8, '92': 7, '93': 1, '96': 2, '97': 4, '99': 6
                }

    for key in test_dic.keys():
        sd.set_value(key, test_dic[key])
    sd.remove_get_two(1)
    sd.remove_get_two(2)
    sd.remove_get_two(3)
    print(dic_1_9)
    print(dic_jiu)
    print(dic_1_9_heng)
    for i in range(1, 10):
        str_some = ''
        for j in range(1, 10):
            s = str(i) + str(j)
            str_some += (' ' + str(dic_shu[s]) + '-')
            if j % 3 == 0:
                str_some += '*'
        print('——————————————————————————————————————————————————————————————————————')
        print(f'第{i}行:{str_some}')

    print(type(dic_shu.keys()))

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,928评论 6 509
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,748评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,282评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,065评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,101评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,855评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,521评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,414评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,931评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,053评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,191评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,873评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,529评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,074评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,188评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,491评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,173评论 2 357

推荐阅读更多精彩内容