趣味Python100例初学者练习01
1. 1 抓交通肇事犯
一辆卡车违反交通规则,撞人后逃跑。现场有三人目击该事件,但都没有记住车号,只记下了车号的一些特征。甲说:牌照的前两位数字是相同的;乙说:牌照的后两位数字是相同的,但与前两位不同;丙是数学家,他说:4位的车号刚好是一个整数的平方。
请根据以上线索求出车号。
if __name__ == '__main__':
for i in range(10): # 牌照的前两位数字
for j in range(10): # 牌照的后两位数字
if i != j: # 前两位不同
x = 1000 * i + 100 * i + 10 * j + j
for m in range(31, 100): # 4位的车号刚好是一个整数的平方
if m * m == x:
print("车牌号为:", x)
1.2 兔子产子
有一对兔子,从出生后的第3个月起每个月都生一对兔子。小免子长到第3个月后每个月又生一对兔子,假设所有的兔子都不死,问n个月内每个月的兔子总对数为多少?
if __name__ == '__main__':
rb1 = 1 # 第一个月的兔子对数
rb2 = 1 # 第二个月的兔子对数
n = int(input("请输入您查询月份:"))
if n <= 2:
print(f"前 {n} 个月的兔子总对数为 1 对")
else:
for i in range(3, n + 1): # 从第3个月开始计算
sum_rb = rb1 + rb2
rb2 = rb1
rb1 = sum_rb
print(f'{n} 个月后兔子总对数为:{sum_rb}')
1.3 牛顿选代法求方程根
编写用牛顿迭代法求方程根的函数。方程为ax^3+bx^2+cx+d=0,系数a、b、c、d由主函数输入,求x在1附近的一个实根。求出根后,由主函数输出。
def newton_method(a, b, c, d, x0, tol=1e-6, max_iter=100):
"""
牛顿迭代法求解方程 ax^3 + bx^2 + cx + d = 0 的根
:param a: 三次项系数
:param b: 二次项系数
:param c: 一次项系数
:param d: 常数项
:param x0: 初始猜测值
:param tol: 容差,默认 1e-6
:param max_iter: 最大迭代次数,默认 100
:return: 求得的实根
"""
def f(x):
return a * x ** 3 + b * x ** 2 + c * x + d # 定义方程 f(x)
def f_prime(x):
return 3 * a * x ** 2 + 2 * b * x + c # 定义导数 f'(x)
x = x0 # 初始猜测值
for i in range(max_iter):
fx = f(x)
fpx = f_prime(x)
if abs(fx) < tol: # 如果 f(x) 接近 0,则认为找到了根
return x
if fpx == 0: # 如果导数为 0,无法继续迭代
raise ValueError("导数为 0,无法继续迭代")
x = x - fx / fpx # 牛顿迭代公式
return x # 返回最终的近似根
if __name__ == '__main__':
# 输入方程的系数
a = float(input("请输入系数 a: "))
b = float(input("请输入系数 b: "))
c = float(input("请输入系数 c: "))
d = float(input("请输入系数 d: "))
# 初始猜测值为 1 附近的点
x0 = 1.0
# 调用牛顿迭代法求解
try:
root = newton_method(a, b, c, d, x0)
print(f"方程的一个实根为: {root:.6f}")
except ValueError as e:
print(e)
1.4 百钱百鸡
中国古代数学家张丘建在他的《算经》中提出了一个著名的“百钱百鸡问题”:一只公鸡值五钱,一只母鸡值三钱,三只小鸡值一钱,现在要用百钱买百鸡,请问公鸡、母鸡、小鸡各多少只?
if __name__ == '__main__':
for x in range(20):
for y in range(33):
for z in range(100):
if 5 * x + 3 * y + (z / 3 == 100):
if x + y + z == 100:
print(x, y, z)
1.5 借书方案知多少
小明有5本新书,要借给A、B、C三位小朋友,若每人每次只能借1本,则可以有多少种不同的借法?
if __name__ == '__main__':
total = 0
for a in range(1, 6):
for b in range(1, 6):
for c in range(1, 6):
if a != b and b != c and a != c:
total += 1
print(f"{a},{b},{c}")
print(f"{total}种")
1.6 打鱼还是晒网
中国有句俗语叫“三天打鱼两天晒网”。某人从1990年1月1日起便开始“三天打鱼两天晒网”,问这个人在以后的某一天中是“打鱼”还是“晒网”。
def is_leap_year(year):
"""
判断某一年是否为闰年
:param year: 年份
:return: True 是闰年,False 不是闰年
"""
return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)
def days_from_1990(year, month, day):
"""
计算从 1990 年 1 月 1 日到给定日期的总天数
:param year: 目标年份
:param month: 目标月份
:param day: 目标日期
:return: 总天数
"""
# 每个月的天数
month_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
total_days = 0
# 计算 1990 年到目标年份之间的天数
for y in range(1990, year):
total_days += 366 if is_leap_year(y) else 365
# 计算目标年份中 1 月到目标月份之间的天数
for m in range(1, month):
total_days += month_days[m - 1]
if m == 2 and is_leap_year(year): # 闰年 2 月多一天
total_days += 1
# 加上目标日期的天数
total_days += day - 1 # 减去 1,因为 1990 年 1 月 1 日是第 1 天
return total_days
def fishing_or_drying(year, month, day):
"""
判断某一天是“打鱼”还是“晒网”
:param year: 目标年份
:param month: 目标月份
:param day: 目标日期
:return: "打鱼" 或 "晒网"
"""
total_days = days_from_1990(year, month, day)
remainder = total_days % 5 # 5 天为一个周期
if remainder < 3: # 余数为 0、1、2 表示“打鱼”
return "打鱼"
else: # 余数为 3、4 表示“晒网”
return "晒网"
if __name__ == '__main__':
# 输入目标日期
year = int(input("请输入年份: "))
month = int(input("请输入月份: "))
day = int(input("请输入日期: "))
total_days = days_from_1990(year,month,day)
# 判断是“打鱼”还是“晒网”
result = fishing_or_drying(year, month, day)
print(f"{year}年{month}月{day}日,这一天相差{total_days}天,这一天在{result}。")
1.7 最佳存款方案
假设银行一年整存零取的月息为0.63%。现在某人手中有一笔钱,他打算在今后5年中的每年年底取出1000元,到第5年时刚好取完,请算出他存钱时应存入多少。
if __name__ == '__main__':
m = 0.0063
money = 0.0
for i in range(1,6):
money = (money + 1000) / (1 + m * 12)
print(f"存钱时应存入{money}")
1.8 冒泡排序
对N个整数(数据由键盘输入)进行升序排列。
if __name__ == '__main__':
# 获取用户输入并去除首尾的空白字符
x = input().strip()
# 以空白字符为分隔符将输入字符串分割成多个字符串,再把这些字符串转换为整数,形成列表
a = list(map(int, x.split()))
# 获取列表的长度
n = len(a)
# 冒泡排序
for i in range(n):
for j in range(0, n - i - 1):
if a[j] > a[j + 1]:
# 交换相邻元素的位置
a[j], a[j + 1] = a[j + 1], a[j]
print(a)
1.9 折半查找
N个有序整数数列已放在一维数组中,利用二分查找法查找整数m在数组中的位置。若找到,则输出其下标值;反之,则输出“Not be found!"
def binary_search(arr, m):
# 初始化左右指针
left, right = 0, len(arr) - 1
while left <= right:
# 计算中间元素的索引
mid = (left + right) // 2
if arr[mid] == m:
# 找到目标值,返回其下标
return mid
elif arr[mid] < m:
# 目标值在右半区间,更新左指针
left = mid + 1
else:
# 目标值在左半区间,更新右指针
right = mid - 1
# 未找到目标值
return -1
if __name__ == "__main__":
# 从键盘输入有序整数数列,以空格分隔
input_str = input("请输入有序整数数列(以空格分隔):").strip()
arr = list(map(int, input_str.split()))
# 从键盘输入要查找的整数
m = int(input("请输入要查找的整数 m:"))
# 调用二分查找函数
result = binary_search(arr, m)
if result != -1:
print(f"整数 {m} 在数组中的下标是:{result}")
else:
print("Not be found!")
1.10 数制转换
给定一个M进制的数x,实现对x向任意一个非M进制的数的转换。
def m_to_decimal(x, m):
"""
将 M 进制的数 x 转换为十进制数
:param x: M 进制的数,字符串类型
:param m: M 进制
:return: 十进制数
"""
decimal_num = 0
power = len(x) - 1
for digit in x:
if digit.isdigit():
value = int(digit)
else:
# 处理字母表示的数字,如 A 表示 10,B 表示 11 等
value = ord(digit.upper()) - ord('A') + 10
decimal_num += value * (m ** power)
power -= 1
return decimal_num
def decimal_to_n(decimal_num, n):
"""
将十进制数转换为 N 进制的数
:param decimal_num: 十进制数
:param n: 目标进制
:return: N 进制的数,字符串类型
"""
if decimal_num == 0:
return '0'
result = ''
while decimal_num > 0:
remainder = decimal_num % n
if remainder < 10:
result = str(remainder) + result
else:
# 处理大于 9 的余数,用字母表示
result = chr(ord('A') + remainder - 10) + result
decimal_num //= n
return result
def convert_number(x, m, n):
"""
将 M 进制的数 x 转换为 N 进制的数
:param x: M 进制的数,字符串类型
:param m: M 进制
:param n: 目标进制
:return: N 进制的数,字符串类型
"""
# 先将 M 进制的数转换为十进制数
decimal_num = m_to_decimal(x, m)
# 再将十进制数转换为 N 进制的数
return decimal_to_n(decimal_num, n)
# 示例使用
if __name__ == "__main__":
x = input("请输入 M 进制的数: ")
m = int(input("请输入当前进制 M: "))
n = int(input("请输入目标进制 N: "))
result = convert_number(x, m, n)
print(f"{m} 进制的数 {x} 转换为 {n} 进制的数是: {result}")