HNU计算机概论课实训题代码日记(20230315)

这次的作业确实难。涉及到while和for_in循环、循环嵌套、break和continue语句的应用,所以我拖到现在才更新,还请见谅。

1.4循环结构(一)
第1关:金箍棒长度

本关任务:孙悟空金箍棒长度2m,每次可以缩短到原来1/2的长度,求多少次后长度小于 1cm 即 0.01m。

为了完成这关,我们首先需要声明变量金箍棒长度和缩短次数,当然这一步题目中已经给出。下一步是利用while循环使金箍棒在长度小于0.01m之前多次缩短,同时每缩短一次就为count变量+1来计算次数。当长度小于0.01m时停止循环。

#金箍棒长度
d=2     #金箍棒长度
count=0  #次数
#代码开始
while d >= 0.01:
    d=0.5*d
    count=count+1
print(count)
#代码结束
第2关:乌龟旅行

本关任务:乌龟决心去做环球旅行,第 1小时爬行了 10 米,第 2 小时爬行了 5 米,第 3 小时爬行 2.5 米,速度不断减半,请问多少小时后可以爬行 19.99米。

这关与上一关比较类似,这里不多作阐述,都是利用while循环进行的基础操作。

#乌龟旅行
total=10  #总路程
d=10      #速度
t=1       #时间
#代码开始
while total<19.99:
    d=0.5*d
    total=total+d
    t=t+1
print(t)
#代码结束
第3关:计算正弦值

本关任务:正弦值的近似计算公式为:sin⁡x=x−3!x3​+5!x5​−7!x7​+⋯(注:这里的公式是我直接从原题上复制粘贴过来的所以变成了这鬼样子,其实就是泰勒展开)从键盘输入x的值(x为弧度值),利用以上公式计算sinx,将所有绝对值大于等于精度eps的项值进行累加(eps的值设为1e−7即10−7)(注:这里的显示也不太对劲,以平台上的题目为准)。结果保留7位小数。

这关相比之前难了不少。这里规定t,s,n三个变量。s是各项的总值,t对应每一项,n则用来表示每一项分母的值。

#求正弦值
from math import *
x=eval(input())  #输入弧度值
#代码开始
t=x
s=0
n=1 
while abs(t)>=10**(-7): #abs( )是绝对值函数,对应题干中“大于等于精度eps”的要求。
    s+=t #这关开始使用赋值符号,s+=t即将符号两端相加,再赋值给前面的s。
    n+=2 #每一项次数+2,共下一行代码的计算使用。
    t*=-x**2/(n*(n-1)) #下一项的分母是上一项乘上n(n-1),分子是上一项乘以x^2。
print("%.7f"%s)
#代码结束
第4关:求水仙花数

本关任务:水仙花数是一个三位数的自然数,该数各位数字的立方和等于该数本身,例如:153为水仙花数,1^3+3^3+5^3=153。由小到大分行输出所有水仙花数。

这关需要使用for_in循环。由于是初次接触,难度比较低,只需表达出水仙花数的各位数字就行。

#水仙花数由小到大分行输出
#代码开始
for n in range(100,1000):
    a=n//100 #百位数
    b=(n//10)%10 #十位数
    c=n%10 #个位数
    if n == a**3 + b**3 + c**3:
        print(n)
#代码结束
第5关:continue用法

本关任务:通过循环计算并输出满足条件的正方体的体积:正方体棱长从1到10依次计算,当体积小于100不输出。

这关是continue语句入门关,continue语句可以跳过循环体后还未执行的语句,直接进行下一次循环。

#continue的用法
#代码开始
for a in range(1,11):
    b=a**3
    if b < 100:
       continue #直接进行下一次,也就是a+1的循环。
    else:
        print(b)
#代码结束
第6关:break用法

本关任务:输入若干个学生成绩,当成绩小于0时输入结束。计算出平均分,并输出不及格的人数。

break语句被执行时,跳过循环体中其他未执行的语句并提前结束该层循环。利用break语句达到“成绩小于0时输入结束”的要求。

#break的用法
sum=0   #总分
n=0     #总人数
average=0  #平均分
count=0  #不及格人数
while 1:
    mark=eval(input())   #循环输入分数
#代码开始 
    if mark < 0:
        break #使用break语句结束该层循环
    elif mark < 60:
        count+=1
        sum+=mark
    else:
        sum+=mark
    n+=1    
average=sum/n
#代码结束
print("%.2f"%average,count)
第7关:求前n项之和

本关任务:求s= a + aa + aaa + … + aa…a 的值(最后一项中 a 的个数为 n ),其中 a 是一个1~9的数字,例如: 当a=2,n=5时,s= 2 + 22 + 222 + 2222 + 22222

规定两个变量,就用高中数列里熟悉的an和sn,这样看上去更加直观。an=an-1+an-1*10^i,sn就是前n项和。

#求s= a + aa + aaa + … + aa…a
a=eval(input())   #输入a值
n=eval(input())   #输入最后一项中 a 的个数 n 
#代码开始 
an=0 
sn=0
for i in range(n):
    an+=a*10**(i)
    sn+=an
print(sn)
#代码结束
第8关:凯撒密码加密

本关任务:编写程序,实现凯撒密码的加密。

我第一篇文章最后一道凯撒密码解密一直没有更新,这次把加密和解密一并解决。

ord()和chr()函数可以实现ascii值或者Unicode数值与单个字符的互换。利用这点并结合for_in循环就可以将字符对应的Unicode数值向前或向后推一定位数来进行凯撒密码的加密和解密。由于直接将ord(n)加或减一定位数会遗漏xyz三个字母,我们采用(ord('a')+(ord(n)-ord('a')+3)%26)的方式来将所有字母考虑进去。

#凯撒密码加密
plaincode= input("")  #输入明文
#代码开始 
for n in plaincode:
    if 'a' <= n <= 'z':
        print(chr(ord('a')+(ord(n)-ord('a')+3)%26),end='')
    elif 'A' <= n <= 'Z': #大小写字母对应的Unicode值不同,因此需要分开考虑。
        print(chr(ord('A')+(ord(n)-ord('A')+3)%26),end='')
    else:
        print(n,end='') #这行是用来处理空格和标点符号的。
#代码结束
1.4 循环结构(二)
第1关:输出给定范围内的所有素数

本关任务:输出给定范围以内的所有素数。输出时,每行显示10个数。程序从测试集中读取到数据范围m,求2~m之间所有素数。

这关难点倒不在输出素数,而是……控制每行显示10个数。当时搞到凌晨才发现原来一直没过是因为忽略了这点。

#求给定范围内的所有素数
m=eval(input())  #输入范围
#代码开始
count=0 #用来计算每行数字的个数
for i in range(2,m+1):
    for j in range(2,i):
        if i%j == 0:
            break #两数可整除说明该数字为合数,利用break语句终止循环。
    else:
        print(i,end=' ')
        count+=1
        if count % 10 == 0:
            print(end='\n') #每行数字的个数达到10后强行换行
#代码结束
第2关:求表达项n项之和

本关任务:输入n,求下列表达式的值:1+1/(1+2)​+1/(1+2+3)1+⋯+1/(1+2+3+⋯+n),​结果保留6位小数。

这关可以逃课,解法如下:

#求n项之和
n=eval(input())
#代码开始
a=2*(1-(1/(n+1)))
print("{:.6f}".format(a))
#代码结束

正常解法等我把这周高数大物作业交完以后再更新[doge]。

第3关:n个钱买n只鸡的问题

本关任务:每只公只因价值5元,每只母只因价值3元,每3只小只因价值1元。现有n个钱想买n只只因,问公只因、母只因、小只因各买几只? 依次输出公只因母只因小只因的数目,如输出结果:22 23 45

我们把三种我家鸽鸽分别命名为"cai","xu"和"kun"三个变量。如果将三个变量的和是n,每个变量乘以各自的价格也是n,这道题就能解决了。

#n个钱买n只鸡问题
print("依次输出公鸡 母鸡 小鸡的数量:")
n=eval(input()) #n表示钱的总数和鸡的总数
#代码开始
for cai in range(n//5+1): 
    for xu in range(n//3+1):
        if 5*cai+3*xu+kun/3==n and cai+xu+kun==n:
            print (cai,xu,kun)
#代码结束

理论上是这样的。但头歌平台不知道抽什么风,这样评测结果会超时。难道是我家鸽鸽觉得我香翅捞饭了?不过我们可以用另一个方式来解决:

#n个钱买n只鸡问题
print("依次输出公鸡 母鸡 小鸡的数量:")
n=eval(input()) #n表示钱的总数和鸡的总数
#代码开始
for cai in range(n//5+1):
    for xu in range(n//3+1):
        kun = n - cai - xu
        if 5*cai+3*xu+kun/3==n:
            print (cai,xu,kun)
#代码结束

虽然这两种方法区别不大,但第一种就是会超时。幸好不是我家鸽鸽的问题。

第4关:剩余材料最短

本关任务:求出剩余材料最短的切割方案。 一根长度为n米的钢管,需要截成长度为19米和23米的两种短管。求两种短管各截多少根时剩余的材料最少?(钢管的长度大于等于42)

注意:1、每种短管必须大于等于一根。

2、如果存在多种方案时,请输出19米的数目最少的方案。

为了解决这道题,我们需要设置i和j两个变量,具体以后更新,理由同第2关。

#剩余材料最短
length=eval(input())   #输入钢管长度
n=0      #19米为n段
m=0      #23米为m段
rest=length   #剩余材料长度
#代码开始
for j in range(1,length//19+1):
    for i in range(1,length//23+1):
        k=length-19*j-23*i 
        if rest>k>=0:
            n=j
            m=i
            rest=k
#代码结束
print("切割方案:19米{}段,23米{}段,剩余{}米.".format(n,m,rest))
第5关:打印图形

从这关开始,字的颜色就和我做题时的心情一样灰暗。

本关任务:

输入行数,打印如下字母金字塔图形:

输入:7

打印图形如下:

A

BAB

CBABC

DCBABCD

EDCBABCDE

FEDCBABCDEF

GFEDCBABCDEFG

提示:

打印图案关键是找出其中的规律。

根据打印第几行,算出每行打印多少列。

输出的每一行包括三部分组成:空格、字符串和换行。

提示看上去像假的一样,但实际上能起到很大的作用。

既然是遍历循环,我们就一行一行的考虑。对于某一行,可以用if和else语句来判断出空格和字母的位置。

A对应的Unicode值是65,我们可以先写出某一行的一部分字母:

n=eval(input())
for i in range(n):
    for j in range(i+1):
        print(chr(65+j),end='')
    print('') #用于在每次循环后强制换行

如上所示,假设输入n=3,则输出结果是:

A

AB

ABC

我们可以在前面添加空格。观察金字塔的形状,每行需要的空格数量实际上只是左半段。第n行需要的空格数量是0,由此向前每一行空格数量+1,第一行需要(n-1)个空格。从这个规律中我们可以总结出第i行需要的空格数量是(n-i-1)个(i从0开始计)。于是,我们在line.2和line.3之间添加以下代码:

    for k in range(n-i-1):
        print(" ",end='')

之后得到新的结果:

A

AB

ABC

(发布后发现这里显示有问题,第一行字母前面应该有两个空格,第二行有一个)

最后,我们需要在每一行的空格和已有的字母之间加上剩余的字母。现有的字母并不是一半,而是类似于……《成龙历险记》面具篇里,有一副面具被摔成两半,大概就和瓦龙戴的那一半召唤出来的忍者团差不多。需要添加的是小玉召唤出来的那部分。在两段代码之间加上如下代码:

    for l in range(i):
        print(chr(65+i-l),end='')

完整代码如下:

#打印字母图形
n = eval(input())  #输入行数
#代码开始 
for i in range(n):
    for k in range(n-i-1):
        print(' ',end='')
    for l in range(i):
        print(chr(65+i-l),end='')
    for j in range(i+1):
            print(chr(65+j),end='')
    print('')
#代码结束 

老师是有点高估我们的技术了。

第6关:判断身份证号码是否有效

本关任务:输入一个身份证号码,判断其是否有效:

  • 若不为18位,提示“长度错误”;

  • 若前17位存在非数字,提示“存在无效字符”;

  • 最后一位为校验码,若错误,提示“校验码错误”, 若正确,提示“校验码正确”。

  • 相关知识

    为了完成本关任务,你需要掌握:1.校验码产生规则,2.循环和分支,3.字符串的遍历。

    校验码产生规则

    身份证校验码产生的规则如下所示:(1) 将身份证号码的前17位数字分别乘以不同的系数,从第1位到第17位的系数分别为:7、9、10、5、8、4、2、1、6、3、7、9、10、5、8、4、2 ;(2) 将这17位数字和系数相乘的结果进行相加;(3) 用加出来的和除以11,看余数是多少;(4) 余数只可能是0、1、2、3、4、5、6、7、8、9、10这11个数字。其分别对应的最后一位身份证的号码为1、0、X、9、8、7、6、5、4、3、2,其中的X(大写)是罗马数字10; 通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ;如果余数是10,身份证的最后一位号码就是2。

    这关需要用到字符串、字典和列表,让人不禁怀疑是留给我们以后做的内容。

    第一步是判断长度错误。这一步不需要用到循环,这里不多说。

    第二步需要利用遍历循环来检验身份证号中是否出现了非数字。为此我们需要建立一个含有所有个位数字的字典并检验身份证号中的每一项是否在字典里。

    第三步是检验校验码是否正确。按照公式慢慢写。

    #判断身份证号是否有效
    id=input("请输入身份证号:")
    #代码开始
    m=list('0123456789')
    a=[7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2]
    e='10X98765432'
    if len(id)!=18:
        print("长度错误")
    else:
        for n in range(17):
            if id[n] not in m:
                print("存在无效字符")
                break
        else:
            b=0
            for c in range(17):
                b+=int(id[c])*a[c]
            d=b%11
            if id[17]==e[d]:
                print('正确校验码')
            else:
                print('错误校验码')

    总结:哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈Python太好玩了哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈我下周不想看见这么好玩的课了哈哈哈哈哈哈哈哈哈哈哈哈两套实训爆肝三个晚上哈哈哈哈哈哈哈哈哈哈哈哈哈一行报错卡一个半小时哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊👊!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    本期题目的截止日期相较于上周的题目延后了两周,老师估计没想让我们一周之内做完。既然如此,下周的实训题是不是可以免了?[doge]

    在此特别感谢萌稣群群友们在我做题时提供的思路和建议。

    物联沃分享整理
    物联沃-IOTWORD物联网 » HNU计算机概论课实训题代码日记(20230315)

    发表评论