Python趣味算法入门 - 抓交通肇事犯 & 最佳存款方案

这两个问题都太短太简单了,干脆放在一起了。原书分别位于1.1和1.7章节。


问题一描述

一辆卡车违反交通规则,撞人后逃跑。现场有三人目击事件,但都没有记住车号,只记下车号的一些特征。甲说:牌照的前两位数字是相同的;乙说:牌照的后两位数字是相同的,但与前两位不同; 丙是数学家,他说:四位的车号刚好是一个整数的平方。请根据以上线索求出车号。

分析

根据以上线索,可以得到以下几个条件:
1. 车号是4位整数
2. 车号的千位与百位相同,十位与个位数字相同,但彼此不同
3. 车号是另一个整数的平方

很自然地,我们可以根据条件3想到去遍历平方数是四位数的整数(条件1),然后判断这个平方数是否符合条件2,那么如何决定遍历区间呢?由条件1可以想到,四位整数的范围是1000到9999,而结合条件2,这个四位数的范围又可以缩小到1100到9988。第这两个边界数字进行开平方运算,对结果取整,得到范围是33到99。所以我们只要计算33到99的平方,然后将结果对比条件2,符合条件即为结果。于是编写代码如下:

for i in range(int(1100**0.5),int(9988**0.5)+1):
    s = i**2
    a, b = s//100, s%100 # 拆分为前两位和后两位
    if a!=b and a%11==0 and b%11==0: # 如果一个两位数的个位和十位相同,则必能被11整除
        print(f"车号为:{s}")

此外,验证条件2,我们也可以将四位数转成字符串,然后进行字符串的比较,不过因为要调用每个位置的数字,这样写稍微麻烦一点。当然,如果符合条件,我们也不需要再将结果转成数字,直接输出即可。代码如下:

for i in range(int(1100**0.5),int(9988**0.5)+1):
    s = str(i**2)
    if s[0]!=s[2] and s[0]==s[1] and s[2]==s[3]:
        print(f"车号为:{s}")

当然,换个角度,我们也可以先把所有符合条件2的4位数找出来,然后依次判断其是否是某一个整数的平方,从而找到答案。

for a in range(1,10):
    for b in range(10):
        if a==b:
            continue # 如果千位百位与十位个位相同,则跳过
        s = a*1100+b*11
        if int(s**0.5)==s**0.5: # 判断该四位数开平方后是否是一个整数
            print(f"车号为:{s}")

当然,常识的数学判断,可以知道b不可能取0,所以也可以写成for b in range(1,10)。

另外,根据该应用的常识判断,应该是有唯一解(不然抓不了交通肇事犯),所以在代码找到符合条件的数字后,可以不用继续后面的运算,直接break返回。

输出

车号为:7744

问题二描述

假设银行一年整存零取的月息为0.63%。现在某人手中有一笔钱,他打算在今后5年中的每年年底取出1000元,到第5年时刚好取完,请算出他存钱时应存入多少。

分析

这题是一道简单的数学题,和算法其实扯不上边,硬要编程的话,也只是把程序当做计算器那样进行数学计算而已。

已知第五年底刚好取完存款,说明第五年的利息加本金正好1000,按照这个办法逆推即可。月息0.63%,则年息0.63%*12(如果没有特殊计算年息的要求的话),所以:

第五年初的本金*(1+0.63%*12) = 1000

第四年初的本金*(1+0.63%*12) = 第五年初的本金+1000

第三年初的本金*(1+0.63%*12) = 第四年初的本金+1000

第二年初的本金*(1+0.63%*12) = 第三年初的本金+1000

第一年初的本金*(1+0.63%*12) = 第二年初的本金+1000

要求存钱时该存多少,也就是第一年初的本金,依次倒着计算五次就好。代入公式转换一下,就是每年末剩余的钱加上1000除以年息。

代码如下:

interest = 1+0.0063*12
y = 5
money = 0
while y>0:
    money = (1000+money)/interest
    y -= 1
print(round(money,2),"元")

输出

4039.44 元

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

请叫我问哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值