OJ上的三道Python题
昨天在OJ上做了19级理科大计基的12道题,有两个始终过不去,今天写了最后一道,过了。
把这三道题分享一下。
超市收银系统
时间限制: 1000 ms 内存限制: 65536 kb
题目
题目描述
本题描述有更改,清注意
一般超市或商店的收银台在对商品扫码之后会得到一串数字,这串数字代表一种商品。假设已知所有商品的名称、代码和单价,现在需要你写一个程序,输入扫码得到的商品代码(假设固定为6位数字),计算所购买的每种商品的数量(件数)、总价,并按照字典序打印商品的小票(如果某种商品购买了多件,应在同一行内输出该商品的名称、数量、单价和总价)。计算所购买所有商品的总金额,并打印。 给出商品目录如下:
格式:名称 代码 单价
chips 932071 3.50
chocolate 114049 8.00
soap 304985 2.90
cupcake 955962 4.90
cookie 313903 6.50
milk 243813 3.20
toothbrush 961995 4.80
toothpaste 933328 9.30
teapot 914500 29.80
输入
每行为一个6位数字,代表所购买的商品代码。当所有购买商品输入完毕时,以输入0为结束输入标志。(毕竟你不可能跟收银员说我买了n件商品嘛)。
输出
一张小票,要求: 第一行包含“NAME”、“QUANTITY”、“PRICE”、“SUM”(代表商品的名称、数量、单价和总价),各单词之间用若干空格分隔。
接下来若干行,每行对应所购买的某种商品的明细。要求每列按照该项目内容字符数量最多的那一项填充空格补齐(第一行也要补齐),要求每列左对齐,对齐之后项目之间还要空一格。
总价输出保留两位小数,其余数字按照Python默认输出。
按照商品名称的字典序输出。提示:可使用list.sort()
最后一行是所购买所有商品的总金额,格式为:total:xxx.xx(注意:这里是西文的冒号,保留小数点后2位)
输入样例
932071
114049
932071
932071
114049
114049
932071
0
输出样例
NAME QUANTITY PRICE SUM
chips 4 3.5 14.00
chocolate 3 8.0 24.00
total:38.00
解答
由于商品信息已经给出,所以就直接手动排好序存在list
里。
扫描商品时录入的是代码,为了方便查询,这里使用了dict
,以商品代码作为key
,在list
中的索引为value
,便于直接查找。每扫描一个就增加对应商品的数量。
最后输出时需要对齐,而商品不确定,所以需要先找到最长的商品名,然后对齐输出。
代码如下:
# 商品信息:商品名,单价,数量
list = [["chips", 3.50, 0], ["chocolate", 8.00, 0], ["cookie", 6.50, 0], ["cupcake", 4.90, 0], [
"milk", 3.20, 0], ["soap", 2.90, 0], ["teapot", 29.80, 0], ["toothbrush", 4.80, 0], ["toothpaste", 9.30, 0]]
# 商品代码及对应序号
dic = {"932071": 0, "114049": 1, "313903": 2, "955962": 3,
"243813": 4, "304985": 5, "914500": 6, "961995": 7, "933328": 8}
# 第一列长度的最大值
maxlen = 4
while True:
x = input()
if x == "0":
break
# 商品数量加1
list[dic[x]][2] += 1
if(len(list[dic[x]][0]) > maxlen):
maxlen = len(list[dic[x]][0])
# 第一列与第二列间有空格
maxlen += 1
total = 0
# 第一列
print("NAME"+" "*(maxlen-4)+"QUANTITY PRICE SUM")
for i in list:
# 输出数量不为0的商品
if i[2] != 0:
sum = i[2]*i[1]
total += sum
print(i[0]+" "*(maxlen-len(i[0]))+"%-9d%-6.1f%.2f" % (i[2], i[1], sum))
print("total:%.2f" % total)
输出和样例一样,却一直报WA,也看不到题解,不知道为啥。
代码对齐
时间限制: 1000 ms 内存限制: 65536 kb
题目
题目描述
Python代码要求严格对齐才能执行。但是对齐问题往往很难发现,有时候只是某一行少了或者多了一个空格,就会报错。现在请你编写一个Python程序来帮你整理一下代码,解决少空格或多空格的问题。
要求:
(1)把所有的tab('\t'
)换成4个空格。
(2)使每一行前的空格数必须是4的倍数。把空格补充成不小于自身的最小的4的倍数。如,3个空格补成4个,5个空格补成8个。
注意:这样的要求并不能保证输出代码一定是语法正确的。
(3)确保“#”与注释文字间至少有一个空格。只需要处理每行的第一个“#”即可,将后面的“#”看做注释中的文字。
输入
第一行是一个正整数n,代表代码的行数。
接下来n行,是需要整理的代码。
输出
整理后的代码。
输入样例
8
#terrible code
for i in range(100):
if i % 2 == 0:
print('%d is an even number\n'%i)
if i % 3 == 0:
print('%d can be divided by 3\n'%i)
#tell people it's over
print('It\'s over')
输出样例
# terrible code
for i in range(100):
if i % 2 == 0:
print('%d is an even number\n'%i)
if i % 3 == 0:
print('%d can be divided by 3\n'%i)
# tell people it's over
print('It\'s over')
解答
先处理tab
,利用str.expandtabs()
函数将所有tab
替换为4个空格。
然后补全空格,先算出行首空格数,然后用str.lstrip()
去掉空格再添加空格。
最后补全#
后的空格,遍历搜索。
代码如下:
import math
n = int(input())
for j in range(n):
line = input()
length = len(line)
# 替换tab后去掉开头空格
line = line.expandtabs(4).lstrip()
# 补全空格
line = " "*math.ceil((length-len(line))/4)*4+line
lis = list(line)
# 补上第一个#后的空格
for i in range(len(lis)):
if(lis[i] == '#' and i+1 < len(lis) and lis[i+1] != ' '):
lis.insert(i+1, ' ')
print("".join(lis))
输出和样例一样,一直报PE。
转圈圈
时间限制: 1000 ms 内存限制: 65536 kb
题目
题目描述
情人节到了(其实是过去了),偷偷送大家一道题。
本题要求你输出一个尺寸为d×d的数阵,数字的排列方式是从1到n循环且顺时针转圈,看样例输出。
输入
两行,第一行是正整数n(n<10),第二行是正整数d(d<20)
输出
转圈圈的数阵
输入样例1
6
4
输出样例1
1 2 3 4
6 1 2 5
5 4 3 6
4 3 2 1
输入样例2
5
5
输出样例2
1 2 3 4 5
1 2 3 4 1
5 4 5 5 2
4 3 2 1 3
3 2 1 5 4
解答
想法比较简单,设置一个变量用于控制填充方向,到达拐点后改变方向。
代码如下:
n = int(input())
d = int(input())
# d*d列表
a = [[0]*d for i in range(d)]
# 填充方向
direct = 0
# 当前填充坐标
x = 0
y = 0
for i in range(d*d):
a[x][y] = i % n+1
if direct == 0:
if y+1 < d and a[x][y+1] == 0:
y += 1
else:
x += 1
direct = 1
elif direct == 1:
if x+1 < d and a[x+1][y] == 0:
x += 1
else:
y -= 1
direct = 2
elif direct == 2:
if a[x][y-1] == 0:
y -= 1
else:
x -= 1
direct = 3
else:
if a[x-1][y] == 0:
x -= 1
else:
y += 1
direct = 0
for i in a:
s = [str(j) for j in i]
print(" ".join(s))
这题总算过了。