3

经典练习题:百钱买百鸡、谁家孩子跑得最慢、杨辉三角 | CHEGVA

 2 years ago
source link: https://chegva.com/4929.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Python基础(33)–经典练习题:百钱买百鸡、谁家孩子跑得最慢、杨辉三角

◎知识点

  1. 百钱买百鸡

  2. 谁家孩子跑得最慢

  3. 杨辉三角

◎脚本练习

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
 @FileName:    python_practice2.py
 @Function:    python practice
 @Author:      Zhihe An
 @Site:        https://chegva.com
 @Time:        2021/7/6
"""


"""一、百钱买百鸡"""

"""
【问题描述】
    用100文钱买100只鸡,其中公鸡5文钱1只,母鸡3文钱1只,小鸡1文钱3只
    求各买了几只公鸡、母鸡和小鸡
    
【设计思路】
    设计思路一:
    设公鸡、母鸡和小鸡的只数分别为x、y和z,根据问题描述可以得到如下方程组:
    x + y + z = 100
    5x + 3y + z/3 = 100
    
    如果100文钱全买公鸡,最多可买100 / 5 = 20只,所以x的取值范围是:[0, 20]
    如果100文钱全买母鸡,最多可买100 / 3 = 33只,所以y的取值范围是:[0, 33]
    如果100文钱全买小鸡,最多可买100 * 3 = 300只
    因为总共买了100只鸡,且1文钱3只,所以z的取值范围是:[0, 100],并且z能被3整除
    
    通过三重循环穷举x、y和z的值
    在穷举的过程中,只要x、y和z满足上面的方程组,则得到一组符合条件的解
"""

# 通过三重循环穷举x、y和z的值
# 如果100文钱全买公鸡,最多可买100 / 5 = 20只,所以x的取值范围是:[0, 20]
for x in range(21):
    # 如果100文钱全买母鸡,最多可买100 / 3 = 33只,所以y的取值范围是:[0, 33]
    for y in range(34):
        # 如果100文钱全买小鸡,最多可买100 * 3 = 300只
        # 因为总共买了100只鸡,且1文钱3只,所以z的取值范围是:[0, 100], 并且z能被3整除
        for z in range(0, 101, 3):
            if x + y + z == 100 and 5 * x + 3 * y + z / 3 == 100:
                print('公鸡的只数:%d,母鸡的只数:%d,小鸡的只数:%d' % (x, y, z))

"""
    设计思路二:
    通过二重循环穷举x和y的值
    在穷举的过程中,求出z = 100 - x - y
    只要z满足:z >= 0 且 z能被3整除 且 5x + 3y + z/3 = 100,则得到一组符合条件的解
"""

for x in range(21):
    for y in range(34):
        z = 100 - x - y
        if z >= 0 and z % 3 == 0 and 5 * x + 3 * y + z / 3 == 100:
            print('公鸡的只数:{},母鸡的只数:{},小鸡的只数:{}'.format(x, y, z))


"""二、谁家孩子跑得最慢"""

"""
【问题描述】
    张家、王家和李家各有三个孩子
    一天,三家的九个孩子在一起比赛跑步,规定:
    跑第一名得9分,跑第二名得8分,跑第三名得7分,...,跑第九名得1分
    
    比赛结果如下:
    (1) 各家三个孩子的总分相同
    (2) 第一名是李家的孩子,第二名是王家的孩子
    (3) 所有孩子的名次没有并列的
    (4) 各家三个孩子的名次都没有相连的
    求最后一名是谁家的孩子
    
【设计思路】
    由1可知:
    各家三个孩子的总分都是:(1+2+3+4+5+6+7+8+9)/3=15
    
    由2可知:
    因为第1名是李家的孩子,所以可设李家孩子的分数分别为:9、x、15-(9+x),即:9、x、6-x,其中,x的取值范围是[1, 5]
    因为第2名是王家的孩子,所以可设王家孩子的分数分别为:8、y、15-(8+y),即:8、y、7-y,其中,y的取值范围是[1, 6]
    
    由3和4可知:
    x-(6-x)>1,y-(7-y)>1
    
    通过循环穷举李家三个孩子的分数和王家三个孩子的分数
    在穷举的过程中,定义一个列表存放所有名次对应的分数
    每穷举一次李家三个孩子的分数,就把李家三个孩子的分数从列表中删除
    每穷举一次王家三个孩子的分数,就把王家三个孩子的分数从列表中删除
    列表中剩余的元素即为张家三个孩子的分数,从大到小分别为zhang[2]、zhang[1]、zhang[0]
    因为张家三个孩子的名次没有相连的
    所以zhang[2] - zhang[1] > 1,并且zhang[1] - zhang[0] > 1 
"""

def slowest_child():
    for li in [[9, x, 6 - x] for x in range(1, 6) if x - (6 - x) > 1]:
        # 在穷举的过程中,定义一个列表存放所有名次对应的分数
        scores = list(range(1, 10))
        # 每穷举一次李家三个孩子的分数,就把李家三个孩子的分数从列表中删除
        for score in li:
            scores.remove(score)

        for wang in [[8, y, 7 -y] for y in scores if 7 -y in scores and y - (7 - y) > 1]:
            for score in wang:
                scores.remove(score)

        # 列表中剩余的元素即为张家三个孩子的分数,从大到小分别为zhang[2]、zhang[1]、zhang[0]
        zhang = scores
        # 因为张家三个孩子的名次没有相连的
        # 所以zhang[2] - zhang[1] > 1,并且zhang[1] - zhang[0] > 1
        if zhang[2] - zhang[1] > 1 and zhang[1] - zhang[0] > 1:
            print('李家三个孩子的分数:', li)
            print('王家三个孩子的分数:', wang)
            print('张家三个孩子的分数:', zhang)

slowest_child()


"""三、杨辉三角"""

"""
【问题描述】
    打印下图所示的杨辉三角:
             1
       1 1
      1 2 1
     1 3 3 1
    1 4 6 4 1
   1 5 10 10 5 1
  1 6 15 20 15 6 1
 1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
......
【设计思路】
    杨辉三角的特点:
    (1) 第i行有i个数
    (2) 每行的第一个数和最后一个数都是1
    (3) 每行除了第一个数和最后一个数,其余各数都是其两肩上的数之和

如果将所有的数存在一个二维列表L中,则有:
[[1],
 [1, 1]
 [1, 2, 1]
 [1, 3, 3, 1]
 [1, 4, 6, 4, 1]
 [1, 5, 10, 10, 5, 1]
 [1, 6, 15, 20, 15, 6, 1]
 [1, 7, 21, 35, 35, 21, 7, 1]
 [1, 8, 28, 56, 70, 56, 28, 8, 1]]
 
假设要打印n行,对于特点2,则有:
L[i][0] = L[i][i] = 1(i =  0,1,2,...,n-1)
对于特点3,则有:
当j != 0 且 j != i时,L[i][j] = L[i-1][j-1] + L[i-1][j]

首先,初始化一个所有元素都为1的n行二维列表,第i行有i个数
然后,根据上述特点3的条件和公式更新二维列表,对杨辉三角中不为1的位置进行更新
最后,根据杨辉三角的格式打印二维列表
    打印每行的内容前,先打印一定数量的水平制表符,第i行打印n-i个
    打印每行的内容时,除最后一个数之外,每打印一个数之后打印两个水平制表符
    对于每行的最后一个数,打印之后换行,准备打印下一行
"""

# 首先,初始化一个所有元素都为1的n行二维列表,第i行有i个数
L = [[1 for j in range(i + 1)] for i in range(9)]

# 然后,对杨辉三角中不为1的位置进行更新
for i in range(2, 9):
    for j in range(i + 1):
        # 每行除了第一个数和最后一个数,其余各数都是其两肩上的数之和
        if j != 0 and j != i:
            L[i][j] = L[i - 1][j - 1] + L[i - 1][j]

# 最后,根据杨辉三角的格式打印二维列表
for i in range(9):
    # 打印每行的内容前,先打印一定数量的水平制表符,第i行打印n-i个
    print('\t' * (8 - i), end = '')

    # 打印每行的内容时
    for j in range(i + 1):
        # 除最后一个数之外
        if j != i:
            # 每打印一个数之后打印两个水平制表符
            print('%d\t\t' % L[i][j], end = '')
        # 对于每行的最后一个数
        else:
            # 打印之后换行,准备打印下一行
            print('%d' % L[i][j])
Python

◎脚本地址:https://github.com/anzhihe/learning/blob/master/python/practise/learn-python/python_basic/python_practice2.py

anzhihe安志合个人博客,版权所有丨 如未注明,均为原创 丨转载请注明转自:https://chegva.com/4929.html | ☆★★每天进步一点点,加油!★★☆

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK