ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python算法专项(一)——基础练习

2021-02-28 22:58:44  阅读:230  来源: 互联网

标签:囚犯 python 练习 lamp 算法 num result print def


正在学习方老师的课程,打算边学习边写一个系列的博客,从python的基础练习到深度学习,方老师的教学非常仔细,在此表示感激。也希望通过此次学习让自己编程水平更上一层楼,不辜负自己,也不辜负老师的耐心教导——2021.2.6

目录

1、5猴分桃问题

题目:
有五个猴子上山去摘桃子,一直摘到天黑。五个猴子把所有的桃子放在一起,然后约定第二天一早来分桃。第二天早晨,来了一只猴子。它等了一会儿后心想:不如干脆我把桃子分了吧。于是他把桃子分成了5等份,分完后发现多了一只桃子。他想:我这么辛苦把桃子分了,这多出的一只桃子理应归我!于是他吃了这只桃子,然后带上一等份桃子走了。过了一会儿,第二只猴子来了,他也等了一会儿,不耐烦之后也把桃子分成了五等份,也发现多一只桃子。他同样吃了那个桃子之后也带走了一等份桃子。后来,第三、第四、第五只猴子都是先五等分桃子,然后吃掉多出来的一个桃子,最后再带走一等份桃子。问最初一共有多少只桃子。

代码:

def getPeaches(monkeys):
    unit = 1
    while True:
        ok,peaches = divide((monkeys-1)*unit,monkeys)
        if ok:
            return peaches
        unit +=1

def divide(peaches,monkeys):
    for _ in range(monkeys):
        if(peaches % (monkeys-1)==0):
            peaches = peaches//(monkeys-1)*monkeys + 1
        else:
            return False,0
    return True, peaches

2、翻扑克牌问题

题目:

1、有一幅只有点数没有花色的扑克牌,点数分别是1,2,3,…,20,一共20张。
2、我们把所有牌正面朝下堆成一叠放在手上,然后用另一只手翻开第一张,发现是1点。我们把这张1点牌放在一边,然后再摸下一张牌。这时我们并不看它的点数,而是把它放在这叠牌的末尾,使之成为最后一张。
3、接着,我们翻开下一张牌,发现是2点。我们把这张2点牌也放在一边,然后按顺序摸两张牌,不看点数,而是把它们放在这叠牌的末尾。
注意:是把它们一起放在末尾还是把他们一张一张按顺序放在末尾的结果是一样的。
再翻开下一张牌,发现是3.这张3点牌也被放在一边,我们再一张一张地摸3张牌,并按顺序放在末尾…以此类推,直到把所有牌都翻开并放在了一边。检查被翻开的牌的点数,发现按顺序分别是1、2、3、。。。、20
问:最初牌的顺序是什么?

代码:


#逆向思维程序========================================
def get_pokes(num):
    result = [num]
    p = num -1
    while p>0:
        insert(p,result)
        p -=1
    return result

def insert(p,result):
    for _ in range(p):
        last = result[-1]
        del result[-1]
        result.insert(0,last)
    result.insert(0,p)
print("逆向思维:\n")
print(get_pokes(20))


#
def get_pokesV2(num):
    result = [0]* num
    loc = [e for e in range(num)]
    for p in range(1,num):
        move(p,result,loc)
    result[loc[0]] = num
    return result

def move(p,result,loc):
    first = loc[0]
    del loc[0]
    result[first] = p
    for _ in range(p):
        first = loc[0]
        del loc[0]
        loc.append(first)

print("正向思维:\n")
print(get_pokesV2(20))

3、100阶乘,进阶

题目:

100的阶乘可以写作如下表达式:
100! = 1*2*3*....*98*99*100
这个如果用python一般的写法很简单就可以写出来,代码如下:

def GetFac(num):
    result = 1
    for i in range(1,num+1):
        result = result*i
    return result
 print('%d! = %d ' % (100,GetFac(100)))

结果:
在这里插入图片描述
可以看到结果是个很大的数字,如果用C/C++语言编写的时候很容易出现内存溢出,而导致无法求解的问题。
问题:
现在用python模拟如果限定最大数的情况下,计算并将其输出结果,用这个思路用C/C++写一个程序计算100阶乘。
解题思路:
1、将计算的结果每一位都放在list中,每一位的计算方法是相乘的结果加上进位
2、最后将list中的结果拼接为字符串输出结果
所以核心问题在于如何将多位数相乘的结果装到list中,这里采用分位乘法,记住进的位数,和乘法取余的结果进行保留。
python代码

def fac(n):
    result = [1]
    while n > 1:
        print("n=%d,result=%s"%(n,result))
        mul(result,n)#依次取出要乘的数字,将结果计算出来
        n -=1
    return to_str(result)

def mul(result,n):
    add = 0#进位
    for i in range(len(result)):
        r = n *result[i] + add
        result[i] = r %10
        add = r //10
    while add > 0:
        result.append(add%10)#如果进位超过了10则反复取余数放进列表中
        add //= 10#最后取出整数值
        
def to_str(list):#将列表连接起来,第一个是个位、第二个是十位...
    s = ''
    for i in list:
        s = str(i)+s
    return s

print('%d! = %s ' % (100,fac(100)))

4、囚犯放风问题

题目:

一群囚犯即将被带到牢房坐牢,看守把他们集中在一起,宣布:
1、每个囚犯将被单独关在一个牢房里;
2、每天会随机地抽取一名囚犯放风;
3、放风的地方有一盏电灯,囚犯可以任意开关这盏电灯;
4、电灯永久有电,永远不会损坏;
5、囚犯在防风的地方以及来回的路上都不会被其他囚犯看见;
6、牢房相互之间隔绝,囚犯相互之间不可能传递任何消息;
7、囚犯在放风时出了开关电灯不能留下任何痕迹或者信息;
8、看守只负责随机抽取囚犯,不会帮助囚犯传递信息;
9、如果有人确定所有人都被放风过,可以通知看守,看守确认之后可以把所有囚犯释放。如果永远没有人通知,或者通知的人弄错了(并不是所有人都被防风过),则所有人将永久坐牢,永无出头之日;
10、囚犯们可以商议一个方法出来以便避免永久坐牢。商议好之后就会被关进各自的牢房
我们的问题时:囚犯们会商议出什么办法?

解题思路:

1、推荐一个囚犯作为计数员,他看到灯亮着就灭掉灯,并且计数加1;
2、其他所有人是普通囚犯,看到等亮了就不管,灯灭了就点亮它。同时自己点亮过就不要再点亮,否则会出现重复的;
3、一直循环,如果总囚犯数是N,当计数员的计数等于N-1的时候就跳出循环(因为计数员可以计数说明)
python代码

import random#随机数生成包

def solve_prisons(num):
    counter = num -1 #一个主囚犯,负责计数
    print("计数员ID:%d\n"%(counter))
    turn_ons = [False]*(num - 1)
    lamp = False#灯的状态
    count = 0#计数
    while True:
        lucky = random.randint(0,num-1)#random.randint第二个参数是包含随机生成在内的,但是在numpy中np.random.randint第二个参数是不包含随机生成的
        lamp ,count = get_free(lucky,counter,turn_ons,lamp,count)
        if count == num - 1:
            break

def get_free(lucky,counter,turn_ons,lamp,count):#放风函数
    if lucky == counter:
        if lamp:
            lamp = False
            count +=1
    else:
        if not lamp and not turn_ons[lucky]:
            lamp = True
            turn_ons[lucky] = True
    print('lucky = %d,lamp = %s,count = %d,turn_ons:%s' %(lucky,lamp,count,turn_ons))
    return lamp,count
print("方案1:\n")
solve_prisons(4)

5、猜姓名游戏

一个算命先生,给几个姓名卡片(假设你的姓名就在卡片里存在)让你判别你的名字在不在卡片里面,就可以准确的说出你的姓氏,请想一想为什么,用程序模拟一下。

import math

def guess_name():
    names = '赵钱孙李周吴郑王冯程储卫姜武韩万祝董刘田汪'
    lines = get_lines(names)
    while True:
        answers = []  # 用户输入
        for line in lines:
            print(', '.join(line))
            answer = input('Is your name in this line?(y/n)')
            answer = 1 if answer in ('y','Y')else 0
            answers.append(answer)
        name = get_name(answers,names)
        print('Yor name is :',name)
        answer = input('Is continu guess name?(y/n)')
        if answer not in ('y','Y'):
            break



def get_lines(names):
    rows = int(math.log2(len(names)))+1
    lines = [[] for _ in range(rows)]
    for i,name in enumerate(names):
        id = i+1
        for j in range(rows):
            if id%2 == 1:
                lines[j].append(name)
            id //=2
    return lines


def get_name(answers,names):
    id = 0
    for digit in reversed(answers):#reversed反转列表
        id = id *2 +digit
    return "不存在的姓名" if id ==0 else names[id - 1]


guess_name()

标签:囚犯,python,练习,lamp,算法,num,result,print,def
来源: https://blog.csdn.net/weixin_42727069/article/details/113728900

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有