◎知识点
百钱买百鸡
谁家孩子跑得最慢
杨辉三角
◎脚本练习
#!/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])