Python3 欧拉计划 问题96-100

EulerProject.png

问题91-95参见:https://www.jianshu.com/p/eaf1075ac5e9

96、数独 详细解法参见

  数独是一种热门的谜题。它的起源已不可考,但它与欧拉发明的一种类似的谜题拉丁方阵之间有着千丝万缕的联系。数独是利用1~9的数字替换掉9*9网格中的空白位置,使得每行每列以及每个九宫格中恰好都包含数字1~9。如下是一个典型的数独谜题以及它的解答:

Sudoku.png

  一个构造精良的数独谜题应该包含有唯一解,且能够通过逻辑推断来解决,尽管有时可能必须通过“猜测并检验”来排除一些选项。寻找答案的复杂度决定了题目的难度;上面这个谜题被认为是一个比较简单的谜题,因为可以通过逻辑推断来解决它。
  在文件sudoku.txt中包含有50个不同难度的数独谜题,它们都只有唯一解。上面给出的示例就是文件中的第一个谜题。解开这50个谜题,找出每个谜题解答左上角的三个数字并连接起来,给出这些数的和。例如:上述示例解答左上角的三个数字连接起来构成的数是483

Python3解答
import numpy as np
fan=open(r'C:\Users\GWT9\Desktop\p096_sudoku.txt')#数据文件
an =[]
listfan = []
while 1:
    x = fan.readline()
    if len(x) == 0:
        break
    try:
        int(x)
        fanlist = []
        for jj in x:
            if jj != '\n':
                if jj == '0':
                    fanlist.append(np.nan)
                else:
                    fanlist.append(int(jj))
        listfan.append(fanlist)
    except ValueError:
        pass
    if len(listfan) == 9:
        an.append(listfan)
        listfan = []
fan.close()
#all problem data
an = np.array(an)

#sudoku
# 计算可能性
def ProbNumber(hang, lie, data):
    # 行数据
    H = list(data[hang])
    # 列数据
    L = list(data[:, lie])
    # 宫数据
    G = []
    sfang = int(len(data) ** 0.5)
    hh = hang // sfang
    ll = lie // sfang
    # 宫数据添加
    for ig in range(sfang):
        for gi in range(sfang):
            G.append(data[hh * sfang + ig, ll * sfang + gi])
    # 该点的可能性
    lal = list(H) + list(L) + G
    prob = [ip for ip in list(range(1, len(data) + 1)) if ip not \
            in lal]
    return prob

# 为数据中的空元素选择可能性字典
def ForK(data):
    Kdict = {}
    for ik in range(len(data)):
        for ki in range(len(data)):
            if np.isnan(data[ik, ki]):
                # 转换,便于字典的最下值是唯一的
                trans = ProbNumber(ik, ki, data)
                jieti = len(trans) * 10000000 + ik * 10000 + ki * 10
                Kdict['%s-%s' % (ik, ki)] = [jieti, len(trans), trans]
    return Kdict

# 选择可能性最小的位置
def SeleM(ddict):
    Small = min(ddict.items(), key=lambda x: (x[1][0]))[0]
    # 位置
    weizhi = Small.split('-')
    # hang
    Ha = int(weizhi[0])
    # lie
    Li = int(weizhi[1])
    # 集合
    SE = ddict[Small][2]
    return Ha, Li, SE

ss = 0
global NU
VAR_NAME = locals()
for ifrfr in range(len(an)):
    # 初始状态
    InitialState = {}
    InitialState[0] = an[ifrfr]
    # 取值字典
    NumDict = {}
    NU = 1
    # 状态转移
    # 记录栈中调用函数的次数
    minzhai = 0
    def TransFer(insta, numdi, n=0, c=minzhai):
        # 判断是否满足条件
        if len(ForK(insta[n])) == 0:
            global NU
            NU = 0
            return insta, numdi, n
        # 选择最小的
        mmi = SeleM(ForK(insta[n]))
        if c > 900:
            return insta, numdi, n

        if len(mmi[2]) == 0:
            del insta[n]
            c += 1
            return TransFer(insta, numdi, n - 1, c)
        else:
            middle = insta[n].copy()
            if n in numdi:
                if numdi[n] + 1 < len(mmi[2]):
                    numdi[n] += 1
                    middle[mmi[0], mmi[1]] = mmi[2][numdi[n]]
                    n += 1
                    insta[n] = middle.copy()
                    c += 1
                    return TransFer(insta, numdi, n, c)
                else:
                    del numdi[n]
                    del insta[n]
                    c += 1
                    return TransFer(insta, numdi, n - 1, c)
            else:
                numdi[n] = 0
                middle[mmi[0], mmi[1]] = mmi[2][0]
                n += 1
                insta[n] = middle.copy()
                c += 1
                return TransFer(insta, numdi, n, c)
    c_0 = TransFer(InitialState, NumDict)
    # 最终的函数
    def Sudoku():
        count = 1
        while NU != 0:
            VAR_NAME['c_%s' % count] = TransFer(eval('c_%s' % (count - 1))[0], eval('c_%s' % (count - 1))[1],
                                                eval('c_%s' % (count - 1))[2])
            count += 1
        dd = eval('c_%s' % (count - 1))[0][eval('c_%s' % (count - 1))[2]][0][:3]
        return dd
    ss += np.sum(Sudoku() * np.array([100, 10, 1]))#左上角三个数字连接起来
print(int(ss))
答案:24702

97、非梅森素数

  1999年人们发现了第一个超过100万位的素数,这是一个梅森素数,可以表示为26972593−1,包含2,098,960位数字。在此之后,更多形如2p−1梅森素数被发现,其位数也越来越多。
  在2004年,发现了一个巨大的非梅森素数:28433×27830457+1,包含2,357,207位数字。找出这个素数的最后十位数字。

Python3解答
#这就是python的魔力
print((28433 * (2 ** 7830457) + 1) % (10 ** 10))
答案:8739992577

98、平方数重排

  如果单词CARE中的四个字母依次对应为1、2、9、6四个数字,我们得到了一个平方数:1296 = 362。神奇的是,使用同样的数字字母对应规则,重排后的单词RACE同样也构成了一个平方数:9216 = 962。我们称CARE和RACE为重排平方单词对,同时规定这样的单词对不允许第一个字母对应数字0或是不同的字母对应相同的数字。
  在文件words.txt中包含了将近2000个常见英文单词,找出其中所有的重排平方单词对,一个回文单词不视为它自己的重排。重排平方单词对所给出的最大平方数是多少。注意:所有的重排单词必须出现在给定的文本文件中

Python3解答
fan=open(r'C:\Users\GWT9\Desktop\p098_words.txt')#数据文件
#存储words的list
cclist =[]
fu = []
for i in fan:
    for j in i:
        if j != ',':
            if j != '"':
                fu.append(j)
        else:
            if len(fu) == 1:
                cclist.append(fu[0])
            else:
                cclist.append(('').join(fu))
            fu =[]
cclist.append(('').join(fu))

#获得重排字母对
pair = []
leng = len(cclist)
for iw in range(leng - 1):
    for jw in range(iw, leng):
        iwc, jwc= cclist[iw], cclist[jw]
        if len(iwc) == len(jwc) and sorted(iwc) == sorted(jwc) and iwc != jwc:
            pair.append([iwc, jwc])

#根据字母长度获得该长度范围内的完全平方数
def Squre(length):
    if length == 1:
        return [1, 4, 9]
    gu = [ji ** 2 for ji in range(int((10 ** (length - 1)) ** 0.5), int((10 ** length) ** 0.5))]
    return gu

#根据字母和数字的对应关系获得数字
def Getdigit(exdict, word):
    num = ''
    for hh in word:
        num += exdict[hh]
    return int(num)

print('WORDS PAIR:', pair)
#判断数字和word是否对应
def Judge(number, word):
    accdict = {}
    leng = len(word)
    for jj in range(leng):
        if jj not in accdict:
            accdict[word[jj]] = str(number)[jj]
    #根据字典反写数字与原来数字是否一样
    if Getdigit(accdict, word) == number:
        return accdict
    else:
        return  False

#根据word和数字,求pair word的对应数字
def Getnum(words1, digitset, words):
    fu = []
    for digit in digitset:
        if len(words1) == len(str(digit)) and len(set(words1)) == len(set(str(digit))):#初步判断数字和word是否匹配。
            cdict = Judge(digit, words1)#判断是否匹配
            if cdict:#如果匹配,输出字母和数字的对应字典
                gunum = Getdigit(cdict, words)
                if gunum in digitset:#如果这个数也是完全平方数
                    fu.append([digit, gunum])#输出结果
                    print('%s ==> %s' %([words1, words], fu[0]))
                    return fu
    return False

result = []
for kk in pair:
    setdi = Squre(len(kk[0]))
    number = Getnum(kk[0], setdi, kk[1])
    if number:
        result.append(max(number[0]))
print('最大的平方数:', max(result))
#答案:
WORDS PAIR: [['ACT', 'CAT'], ['ARISE', 'RAISE'], ['BOARD', 'BROAD'], ['CARE', 'RACE'], ['CENTRE', 'RECENT'], ['COURSE', 'SOURCE'], ['CREATION', 'REACTION'], ['CREDIT', 'DIRECT'], ['DANGER', 'GARDEN'], ['DEAL', 'LEAD'], ['DOG', 'GOD'], ['EARN', 'NEAR'], ['EARTH', 'HEART'], ['EAST', 'SEAT'], ['EAT', 'TEA'], ['EXCEPT', 'EXPECT'], ['FILE', 'LIFE'], ['FORM', 'FROM'], ['FORMER', 'REFORM'], ['HATE', 'HEAT'], ['HOW', 'WHO'], ['IGNORE', 'REGION'], ['INTRODUCE', 'REDUCTION'], ['ITEM', 'TIME'], ['ITS', 'SIT'], ['LEAST', 'STEAL'], ['MALE', 'MEAL'], ['MEAN', 'NAME'], ['NIGHT', 'THING'], ['NO', 'ON'], ['NOTE', 'TONE'], ['NOW', 'OWN'], ['PHASE', 'SHAPE'], ['POST', 'SPOT'], ['POST', 'STOP'], ['QUIET', 'QUITE'], ['RATE', 'TEAR'], ['SHEET', 'THESE'], ['SHOUT', 'SOUTH'], ['SHUT', 'THUS'], ['SIGN', 'SING'], ['SPOT', 'STOP'], ['SURE', 'USER'], ['THROW', 'WORTH']]
['BOARD', 'BROAD'] ==> [17689, 18769]
['CARE', 'RACE'] ==> [1296, 9216]
['DEAL', 'LEAD'] ==> [1764, 4761]
['EAST', 'SEAT'] ==> [2916, 1296]
['EAT', 'TEA'] ==> [256, 625]
['FILE', 'LIFE'] ==> [1296, 9216]
['HATE', 'HEAT'] ==> [1369, 1936]
['HOW', 'WHO'] ==> [256, 625]
['ITS', 'SIT'] ==> [256, 625]
['MALE', 'MEAL'] ==> [1369, 1936]
['MEAN', 'NAME'] ==> [2401, 1024]
['NOTE', 'TONE'] ==> [1296, 9216]
['NOW', 'OWN'] ==> [625, 256]
['POST', 'SPOT'] ==> [2916, 1296]
['POST', 'STOP'] ==> [1024, 2401]
['RATE', 'TEAR'] ==> [1024, 2401]
['SHUT', 'THUS'] ==> [1764, 4761]
最大的平方数: 18769

99、幂值比较

  比较两个如211和37这样的幂值大小并不困难,任何计算器都能验证211 = 2048 < 37 = 2187。
  然而,想要验证632382518061 > 519432525806就会变得非常困难,因为这两个数都包含有超过300万位数字。
  在文件base_exp.txt有一千行,每一行有一对底数和指数,找出哪一行给出的幂值最大。文件的前两行就是上面给出的两个例子。

Python3解答
import math
fan=open(r'C:\Users\GWT9\Desktop\p099_base_exp.txt')#数据文件
#存储words的list
explist =[]
for i in fan:
    com = []
    for hh in i.split(','):
        com.append(int(hh))
    explist.append(com)
#转化为对数比较
sinum = 0
hang = 0
for num in explist:
    dlog = math.log(num[0]) * num[1]
    hang += 1
    if sinum < dlog:
        dnum = hang
        sinum = dlog
print(dnum)
答案:709

100、概率反推

  一个盒子中装有21个彩色碟子,其中15个是蓝的,6个是红的。如果随机地从盒子中取出两个碟子,取出两个蓝色碟子的概率是:
  P(BB) = (15/21)×((15-1)/(21-1)) =(15/21)×(14/20) = 1/2
下一组使得取出两个蓝色盘子的概率恰好为50%的安排,是在盒子中装有85个蓝色碟子和35个红色碟子。
  P(BB) = (85/120)×((85-1)/(120-1)) =(85/120)×(84/119) = 1/2
  当盒子中装有超过1012 个碟子时,找出第一组满足上述要求的安排,并求此时盒子中蓝色碟子的数量。

Python3解答
#blue:b, total:t
#2b(b-1)=t(t-1)==>8b^2-8b+1=(2t-1)^2
#pell's Equation2u^2-1=d^2==>2(2b-1)^2-1=(2t-1)^2
#d=2t-1,u=2b-1. t=(d+1)/2, b=(1+u)/2
#pell's Equation==>d^2-2u^2=-1
#初始解
d = 1
u = 1
minnumber = 1e12

while 1:
    if (d + 1) / 2 > minnumber:
        print(int((u + 1) / 2))
        break
    d, u = 3 * d + 4 * u, 2 * d + 3 * u
    print('Total:%d, blue:%d'%((d + 1) / 2, (u + 1) / 2))
#运行结果
Total:4, blue:3
Total:21, blue:15
Total:120, blue:85
Total:697, blue:493
Total:4060, blue:2871
Total:23661, blue:16731
Total:137904, blue:97513
Total:803761, blue:568345
Total:4684660, blue:3312555
Total:27304197, blue:19306983
Total:159140520, blue:112529341
Total:927538921, blue:655869061
Total:5406093004, blue:3822685023
Total:31509019101, blue:22280241075
Total:183648021600, blue:129858761425
Total:1070379110497, blue:756872327473
答案:756872327473

持续更新,欢迎讨论,敬请关注!!!

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

推荐阅读更多精彩内容

  • 46、哥德巴赫的另一个猜想   哥德巴赫曾猜想:每个奇合数可以写成一个素数和一个平方的两倍之和。    9 = 7...
    AiFany阅读 1,147评论 0 0
  • 56 幂的数字和   一古戈尔( 10^100 )是一个巨大的数字:1后面跟着100个0。100^100则更是无法...
    AiFany阅读 1,341评论 0 1
  • 难度划分 影响数独难度的因素很多,就题目本身而言,包括最高难度的技巧、各种技巧所用次数、是否有隐藏及隐藏的深度及广...
    杨过的大雕阅读 3,515评论 0 3
  • 6、平方的和与和的平方之差   前10个自然数平方的和是:1^2 + 2^2 +… + 10^2 = 385。前1...
    AiFany阅读 854评论 1 0
  • 看到这棵树的时候马上想到了秒速五厘米,不知道为什么 “呐,你知道吗?听说樱花飘落的速度是秒速五厘米哦。" 秒速5厘...
    二哈阅读 290评论 0 0