Python練習100題

'''
题目001：有四个数字：1、2、3、4，能组成多少个互不相同且无重复数字的三位数？各是多少？
'''
def tm001():
    '''
    【个人备注】：按题意直接写出来
    '''
    arr = []
    for i in range(1,5):
        for j in range(1,5):
            for k in range(1,5):
                num = 100*i+10*j+k
                if i!=j and j!=k and i!=k and num not in arr:# 互不相同且无重复数字的三位数
                    arr.append(num)
    print(len(arr),arr)
 
def tm001_1():
    '''
    【个人备注】：其实python自带排列组合模块，可以直接调用。
    也知道这个写法，只是函数记不住，还是百度一下才能写出来。
    如果这是面试题，能写出后一种当然好，不能的话还是老老实实的按照上面的思路来吧。
    '''
    import itertools
    temp_arr = list(itertools.permutations([1, 2, 3, 4], 3)) # 排列  # A_4^3 = (4)!/(4-3)! = (4*3*2*1)/1 = 24
    arr = [100*t[0]+10*t[1]+t[2] for t in temp_arr]
    print(len(arr),arr)
 
 
'''
题目002：企业发放的奖金根据利润(I)的多少来提成：
低于或等于10万元时，奖金可提10%；
利润高于10万元，低于20万元时，低于10万元的部分按10%提成，高于10万元的部分，可提成7.5%；
20万到40万之间时，高于20万元的部分，可提成5%；
40万到60万之间时高于40万元的部分，可提成3%；
60万到100万之间时，高于60万元的部分，可提成1.5%；
高于100万元时，超过100万元的部分按1%提成。
从键盘输入当月利润I，求应发放奖金总数？
'''
def tm002():
    '''
    程序分析：请利用数轴来分界，定位。
    【个人备注】：这种处理数轴问题的写法，值得参考。比elif的写法，简洁方便的多。
    '''
    money = int(input('净利润:'))
    arr = [1000000,600000,400000,200000,100000,0]
    rat = [0.01,0.015,0.03,0.05,0.075,0.1]
    bonus = 0
    for i in range(len(arr)):
        if money>arr[i]:                    # 对于处于区间的部分
            bonus+=(money-arr[i])*rat[i]    # 计算并累加奖励
            money=arr[i]                    # 剩余部分
    print(bonus)
 
 
'''
题目003：一个整数，它加上100后是一个完全平方数，再加上168又是一个完全平方数，请问该数是多少？
'''
def tm003():
    '''
    【个人备注】：网站上是求了一下方程，没细看。
    python又不是没有开方函数，直接按字面意思解了。
    '''
    import math
    for i in range(1000):
        x = math.sqrt(i+100)
        y = math.sqrt(i+100+168)
        if x%1==0 and y%1==0:
            print(i)
 
 
'''
题目004：输入某年某月某日，判断这一天是这一年的第几天？
'''
def tm004():
    '''
    【个人备注】：知道python有时间元组这一概念，这道题完全不需要计算。
    时间元组包含九个属性
    tm_year     年
    tm_mon      月(1~12)
    tm_mday     日(1~31)
    tm_hour     时(0~23)
    tm_min      分(0~59)
    tm_sec      秒(0~61, 60或61是闰秒)
    tm_wday     星期(0~6, 0是周一)
    tm_yday     第几天(1~366, 366是儒略历)
    tm_isdst    夏令时(平时用不到)
    '''
    import time
    date = input('输入时间(例如2018-01-23):')
    st = time.strptime(date,'%Y-%m-%d') # 时间文本转化成时间元祖
    num = st.tm_yday
    print(num)
 
 
 
'''
题目005：输入三个整数x,y,z，请把这三个数由小到大输出。
'''
def tm005():
    print('输入三个数字')
    x = input('输入第1个数字:')
    y = input('输入第2个数字:')
    z = input('输入第3个数字:')
    l = [x,y,z]
    arr = sorted(l)  # 你也可以使用list.sort()方法来排序，此时list本身将被修改
    print(arr)
 
 
 
'''
题目006：斐波那契数列。
'''
def tm006():
    '''
    程序分析：斐波那契数列，又称黄金分割数列，指的是这样一个数列：0、1、1、2、3、5、8、13、21、34、……。
    【个人备注】：很多种解法，我是按照分割的方式，每次取列表后两项，然后相加。
    '''
    l = [0,1]
    for i in range(10):
        arr = l[-2:]
        l.append(arr[0]+arr[1])
    print(l)
 
 
'''
题目007：将一个列表的数据复制到另一个列表中。
'''
def tm007():
    '''
    【个人备注】：如果系统的看过python教程之类的应该都知道。
    Python里面一切都是对象，list的复制需要用[:]的方式。
    至于b=a只是相当于给a取了个别名而已，指向的是同一个列表，并没有实现复制。
    '''
    a = [1, 2, 3]
    b = a[:]
    '''题外话'''
    a[0]=0
    print(id(a),id(b))  # 可以看到a,b的内存不一致，是复制
    print(a,b)          # 修改a，b不变
    a = [1, 2, 3]
    b = a
    a[0]=0
    print(id(a),id(b))  # 如果去掉[:]，可以看到a,b的内存一致，并没有复制，指向的是同一个列表
    print(a,b)          # 修改a，b也变
 
 
'''
题目008：题目：输出 9*9 乘法口诀表。
''' 
def tm008():
    #【个人备注】：已经忘了，百度了才想起来口诀表具体长什么样。
    # 注意 %-7s 和 end='' 的用法，其他没什么。
    for i in range(1,10):
        for j in range(1,10):
            if j<=i:
                string = '%d*%d=%d'%(j,i,j*i)
                print('%-7s'%string,end='')
        print('')
 
 
'''
题目009：暂停一秒输出。
'''
def tm009():
    #【个人备注】：time.sleep()，用过的都知道。
    import time
    a = time.time()
    time.sleep(1)
    b = time.time()
    print(b-a)
 
 
'''
题目010：暂停一秒输出，并格式化当前时间。
'''
def tm010():
    #【个人备注】：用过几次，用过就忘。
    import time
    a = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())) # time.localtime()时间戳转化成时间元祖
    print(a)
    time.sleep(1)
    b = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())) # time.strftime()时间元祖转化成时间文本
    print(b)
 
 
'''
题目011：古典问题：
有一对兔子，
从出生后第3个月起每个月都生一对兔子，
小兔子长到第三个月后每个月又生一对兔子。
假如兔子都不死。
问每个月的兔子总数为多少？
'''
def tm011():
    '''
    其实这道题就是斐波那契数列的由来。
    【个人备注】：理清思路是关键，理解成满两个月后，每月都能生兔子，就好办了。
    '''
    m1=1 # 满月
    m2=0 # 满俩月（下个月生兔子）
    mm=0 # 可以月月生兔子了
    for i in range(1,10):
        # 过了1个月后
        mm = mm+m2  # 加入新增成年的兔子
        m2 = m1     # 满月的变成满俩月
        m1 = mm     # 这个月新出生兔子
        print(i,mm+m1+m2) # 每个月有多少对兔子
 
 
'''
题目012：判断101-200之间有多少个素数，并输出所有素数。
'''
def tm012():
    '''
    【个人备注】：按照素数不能被之前的素数整除，取200以内所有素数，然后取出101-200之间的部分。
    '''
    arr = [2,3]
    # 取200以内所有素数
    for i in range(4,201):
        for j in arr:
            if i%j==0:
                break
            # else: # 这是一开始我自己的写法，后来发现for可以直接接else子语句
            #     if j==arr[-1]:
            #         arr.append(i)
        else: # 迭代的对象成功迭代完，位于else的子句将执行；而如果在for循环中含有break时则直接终止循环，并不会执行else子句。
            arr.append(i)
    # 取出100-200之间部分                
    for i in range(len(arr)):
        if arr[i]>100:
            l = arr[i:]
            print(len(l),l)
            break
 
 
'''
题目013：打印出所有的"水仙花数"，
所谓"水仙花数"是指一个三位数，其各位数字立方和等于该数本身。
例如：153是一个"水仙花数"，因为153=1的三次方＋5的三次方＋3的三次方。
'''
def tm013():
    '''
    【个人备注】： // 取整，% 求余，**3 三次方。知道取整求玉写法的就没问题。
    '''
    for i in range(100,1000):
        b = i//100      # 百位
        s = i%100//10   # 十位
        g = i%10        # 个位
        if b**3+s**3+g**3==i:
            print(i)
 
 
'''
题目014：将一个正整数分解质因数。例如：输入90,打印出90=2*3*3*5。
'''
def tm014():
    '''
    【个人备注】：拆到拆不动为止，类似012题。
    '''
    import math
    num = int(input('输入一个整数:'))
    arr = []
    while num>1:
        for i in range(2,int(math.sqrt(num))+1): # 因为题目是一个没写范围正整数，开方可以有效减少该值过大时候的计算量
            if num%i==0:
                arr.append(i)
                num = num//i 
                break
        else:
            arr.append(num)
            break
    print(arr)
 
 
 
'''
题目015：利用条件运算符的嵌套来完成此题：学习成绩>=90分的同学用A表示，60-89分之间的用B表示，60分以下的用C表示。
'''
def tm015():
    '''
    【个人备注】：if-else基本用法，没啥说的。
    '''
    score = float(input('输入一个成绩:'))
    if score>=90:
        print('A')
    elif score>=60:
        print('B')
    else:
        print('C')
 
 
'''
题目016：输出指定格式的日期。
'''
def tm016():
    '''
    【个人备注】：用的不多经常忘，整理了一下参考答案和一些转换
    '''
    import time
    print(time.time())                                          # 时间戳 1498539133.655
    print(time.localtime())                                     # 时间元祖 tm_year=2017, tm_mon=6, tm_mday=27, tm_hour=12, tm_min=53, tm_sec=16, tm_wday=1, tm_yday=178, tm_isdst=0
    print(time.asctime())                                       # 时间的一种可读文本形式 'Tue Jun 27 12:53:50 2017'
    print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()))  # 按指定文本格式输出时间 '2017-06-27 13:00:57'
 
    st = time.localtime(time.time())                            # 时间戳 转化成 时间元祖
    st = time.strptime('2018/1/23','%Y/%m/%d')                  # 时间文本 转化成 时间元祖
    date = time.strftime('%Y-%m-%d',st)                         # 时间元祖 转化成 时间文本  '%Y-%m-%d %H:%M:%S'
    print(date)                                                 # 前面两条函数配合着用，相当于将时间文本重新格式化。
    
    # 另外我们可以通过datetime模块来计算时间差，例如：
    import datetime
    dt1 = datetime.datetime.fromtimestamp(1517302458)
    print(dt1,type(dt1))
    dt2 = datetime.datetime.now()
    print(dt2)
    print('相差%d天零%.1f个小时'%((dt2-dt1).days,(dt2-dt1).seconds/60/60))
    '''
    2018-01-30 16:54:18 <class 'datetime.datetime'>
    2018-02-01 16:27:47.524774
    相差1天零23.6个小时
    '''
    # 注意上面的日期虽然看起来是文本，但实际上是datetime类型的。
    # 可以通过时间戳/时间文本转换得到，然后才能进行日期时间计算。
    d1 = datetime.datetime.strptime('2017-10-16 19:21:22', '%Y-%m-%d %H:%M:%S')
 
 
'''
题目017：输入一行字符，分别统计出其中英文字母、空格、数字和其它字符的个数。
'''
def tm017():
    '''
    【个人备注】：本来想写成这种格式来着
    import string
    if c in string.ascii_letters: # abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
    if c == ' ':                  # 空格
    if c in string.digits:        # 0123456789
    看了参考答案才知道有现成的函数可以用。
    其实随便哪种都行，甚至直接把一串字母粘上去看起来更直接。
    '''
    s = raw_input('input a string:\n')
    letters,space,digit,others = 0,0,0,0
    for c in s:
        if c.isalpha(): 
            letters += 1
        elif c.isspace():
            space += 1
        elif c.isdigit():
            digit += 1
        else:
            others += 1
    print('char = %d,space = %d,digit = %d,others = %d' % (letters,space,digit,others))
 
 
'''
题目018：求s=a+aa+aaa+aaaa+aa...a的值，其中a是一个数字。例如2+22+222+2222+22222(此时共有5个数相加)，几个数相加由键盘控制。
'''
def tm018():
    '''
    【个人备注】：答案给的解法很多种，但是我还是认为我写的方法最简单。
    2+22+222+2222+22222
    可以理解为：
    20000 + 2*2000 + 3*200 + 4*20 + 5*2
    也就是：
    1*2*10^4 + 2*2*10^3 + 3*2*10^2 + 4*2*10^1 + 5*2*10^0
    所以简单迭代就可以出结果
    '''
    a = 2
    t = 5
    num = 0
    for i in range(1,t+1):
        num+=i*a*(10**(t-i))
    print(num)
 
 
'''
题目019：一个数如果恰好等于它的因子之和，这个数就称为"完数"。例如6=1＋2＋3.编程找出1000以内的所有完数。
'''
def tm019():
    '''
    【个人备注】：题意看的不是太懂，于是百度了一下：完数就是除了自身之外的所有约数之和等于他本身。
    第一个完全数是6，它有约数1、2、3、6，除去它本身6外，其余3个数相加，1+2+3=6。
    第二个完全数是28，它有约数1、2、4、7、14、28，除去它本身28外，其余5个数相加，1+2+4+7+14=28。
    终于看懂了题意。
    先求出所有约数，然后求和比一下是否相等就行了，没有难度
    '''
    for num in range(1,1000):
        arr = []
        for i in range(1,num):
            if num%i==0:
                arr.append(i)
        if sum(arr)==num:
            print(num,arr)
 
 
'''
题目020：一球从100米高度自由落下，每次落地后反跳回原高度的一半；再落下，求它在第10次落地时，共经过多少米？第10次反弹多高？
'''
def tm020():
    '''
    【个人备注】：很简单，没啥说的
    '''
    total = 0
    m = 100                # 第一次落地，经过了一百米
    total += m
    for i in range(10-1):  # 之后9次弹起到落地
        m = m/2            # 弹起的高度
        total += 2*m       # 弹起然后重新落地，一共经过的距离
    print(total)
    print(m/2)