OJ 上的三道 Python 题

昨天在 OJ 上做了 19 级理科大计基的 12 道题,有两个始终过不去,今天写了最后一道,过了。

把这三道题分享一下。

超市收银系统

这题一直报WA

时间限制: 1000 ms 内存限制: 65536 kb

题目

题目描述

本题描述有更改,清注意

一般超市或商店的收银台在对商品扫码之后会得到一串数字,这串数字代表一种商品。假设已知所有商品的名称、代码和单价,现在需要你写一个程序,输入扫码得到的商品代码(假设固定为 6 位数字),计算所购买的每种商品的数量(件数)、总价,并按照字典序打印商品的小票(如果某种商品购买了多件,应在同一行内输出该商品的名称数量单价总价)。计算所购买所有商品的总金额,并打印。 给出商品目录如下:

1
2
3
4
5
6
7
8
9
10
格式:名称 代码 单价
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 位)

输入样例

1
2
3
4
5
6
7
8
932071
114049
932071
932071
114049
114049
932071
0

输出样例

1
2
3
4
NAME      QUANTITY PRICE SUM
chips 4 3.5 14.00
chocolate 3 8.0 24.00
total:38.00

解答

由于商品信息已经给出,所以就直接手动排好序存在list里。

扫描商品时录入的是代码,为了方便查询,这里使用了dict,以商品代码作为key,在list中的索引为value,便于直接查找。每扫描一个就增加对应商品的数量。

最后输出时需要对齐,而商品不确定,所以需要先找到最长的商品名,然后对齐输出。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 商品信息:商品名,单价,数量
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,也看不到题解,不知道为啥。

代码对齐

这题一直报PE

时间限制: 1000 ms 内存限制: 65536 kb

题目

题目描述

Python 代码要求严格对齐才能执行。但是对齐问题往往很难发现,有时候只是某一行少了或者多了一个空格,就会报错。现在请你编写一个 Python 程序来帮你整理一下代码,解决少空格或多空格的问题。

要求:

(1)把所有的 tab('\t')换成 4 个空格。

(2)使每一行前的空格数必须是 4 的倍数。把空格补充成不小于自身的最小的 4 的倍数。如,3 个空格补成 4 个,5 个空格补成 8 个。

注意:这样的要求并不能保证输出代码一定是语法正确的。

(3)确保“#”与注释文字间至少有一个空格。只需要处理每行的第一个“#”即可,将后面的“#”看做注释中的文字。

输入

第一行是一个正整数 n,代表代码的行数。

接下来 n 行,是需要整理的代码。

输出

整理后的代码。

输入样例

1
2
3
4
5
6
7
8
9
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')

输出样例

1
2
3
4
5
6
7
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')

解答

先处理tab,利用str.expandtabs()函数将所有tab替换为 4 个空格。

然后补全空格,先算出行首空格数,然后用str.lstrip()去掉空格再添加空格。

最后补全#后的空格,遍历搜索。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

1
2
6
4

输出样例 1

1
2
3
4
1 2 3 4
6 1 2 5
5 4 3 6
4 3 2 1

输入样例 2

1
2
5
5

输出样例 2

1
2
3
4
5
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

解答

想法比较简单,设置一个变量用于控制填充方向,到达拐点后改变方向。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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))

这题总算过了。