1043 输出PATest (20 分)
题意描述:
给定一个长度不超过 10^4 的、仅由英文字母构成的字符串。请将字符重新调整顺序,按 PATestPATest… 这样的顺序输出,并忽略其它字符。当然,六种字符的个数不一定是一样多的,若某种字符已经输出完,则余下的字符仍按 PATest 的顺序打印,直到所有字符都被输出。
输入格式:
输入在一行中给出一个长度不超过 10^4 的、仅由英文字母构成的非空字符串。
输出格式:
在一行中按题目要求输出排序后的字符串。题目保证输出非空。
输入样例:
redlesPayBestPATTopTeePHPereatitAPPT
输出样例:
PATestPATestPTetPTePePee
解题思路:
Alice: 如何 ?
Bob: 你会不会包饺子 ?
Alice:(⊙_⊙)?啥,你是饿傻了吧。
Bob: 这道题里组成‘PATest’这样的字符串就像包饺子一样,包饺子得有饺子皮,有饺子馅儿,有一个包饺子的人,一个煮饺子的人。要是饺子皮不够了,剩下的饺子馅儿就只能炸肉丸了,要是饺子馅儿不够了了,剩下的饺子皮就只能做面叶儿了。
Alice: 你到底想说啥 ?
Bob: 我的意思是这些字符就像是原料,而“PATest”就像是饺子,只需要统计出来‘PATest’各个字符的数量就能把饺子,面叶,炸肉丸做出来。
Alice: 额,你是在说题目中说的调整顺序完全是不必要的,或者不能只按照字面意思来理解,对吧 ?
Bob: 就是这样啊。
Alice: 看起来和包饺子一样,小菜一碟~
Bob: 赶明我也学一个全套的包饺子,自己动手,丰衣足食。
Alice: 逻辑上面没问题了,代码细节呢 ?
Bob: 没啥特别需要注意的吧。可能会需要多次迭代才能写出优雅的版本来。像烙饼子,需要“翻一翻”。
def main():
temp = input()
# 接收输入的“原材料”,一个由英文字母构成的字符串。
P = A = T = e = s = t = 0
# 声明6个变量,分别用来记录在输入的字符串中字符'P','A','T','e','s','t'的数量。
# 虽然把六个变量的声明写在一行里不是“正规军”的做法,不过写程序还是开心要紧。
for x in temp:
"""
查一查,数一数,在输入的字符串中'P','A','T','e','s','t'的数量。
看,这是一个逻辑很清楚的if else语句块。虽然很容易读懂,但是要打很多字:}
,而且如果else分支有很多(如几千个),写起来麻烦,运行起来效率也很低。
既然人的时间要贵于机器的时间而且我们更喜欢运行效率高的程序,我们在下面提
供了一种更为优雅的方式来统计各个字符出现的次数。
"""
if x == 'P':
P += 1
elif x == 'A':
A += 1
elif x == 'T':
T += 1
elif x == 'e':
e += 1
elif x == 's':
s += 1
elif x == 't':
t += 1
else:
pass
answer = ""
# 用来拼接答案
while True:
"""
我们并不知道要循环多少次,所以就用while而不是for。循环什么时候终止
呢?'P','A','T','e','s','t'都用完的时候,这是一个复杂的条件,我们没法把
它一下子写出来。现在,我们有两条路,一是把判断循环是否终止写成一个函数,
另一条就是在循环内部判断然后break出去。如果你知道“goto 语句是有害的”就应
该知道程序的读者是不喜欢break语句的,不过我们总喜欢一些危险的捷径,不是吗 ?
"""
breaking = True
# 按照PATest的顺序依次拼接字符,只有PATest中有一个字符都没有的时候 breaking 保持为True。
if P:
answer += 'P'
P -= 1
breaking = False
if A:
answer += 'A'
A -= 1
breaking = False
if T:
answer += 'T'
T -= 1
breaking = False
if e:
answer += 'e'
e -= 1
breaking = False
if s:
answer += 's'
s -= 1
breaking = False
if t:
answer += 't'
t -= 1
breaking = False
if breaking:
break
print(answer)
# 输出答案
if __name__ == '__main__':
main()
def main():
temp = input()
# 接收输入的“原材料”,一个由英文字母构成的字符串。
chars = [x for x in 'PATest']
"""
chars 形如 ['P','A','T','e','s','t'], chars的作用是将 字符映射为下标对应的
数字,如chars.index('P') -> 0, chars.index('T') -> 2。 注意
chars.index('k') 会抛出异常,因为 'k' in chars == False。 其实,这里有一个
更好的方式来将字符映射到数字,那就是字典,动动小手自己实现吧。
"""
count = [0 for x in range(len('PATest'))]
# count列表用来记录各个字符出现的次数,如count[0]表示'P'出现的次数,因为'P'在chars中的下标是0.
for x in temp:
# 因为可能会有异常抛出,所以需要使用try catch 语句块。
try:
count[chars.index(x)] += 1
# 如果chars.index(x) 没有抛出异常,就把对应的计数器加一。
except Exception as e:
# 抛出了异常说明遇到了‘PATest’之外的字符,按照题意,忽视。
pass
minn = min(count)
"""
count列表记录了各个字符出现的次数,min(count)就是出现次数最少的字符出现的次
数,也就是说每个字符都至少出现了min(count)次。知道这个有什么用呢? 有用,
每个字符都至少出现了min(count)次就是说在答案中‘PATest’出现了min(count)次。
然后才是那些剩余的,不够组成一个完整的‘PATest’的字符的组合。
"""
if minn:
# 如果minn不是零的话,我们可用的字符数要减去minn。因为每个字符都有minn个被抽去去制作完整的'PATest'。
for x, _ in enumerate(count):
count[x] -= minn
"""
for index, value in enumerate(可迭代对象):
blah
其中value对应可迭代对象中的值,index对应可迭代对象中value的下标。
"""
answer = []
# answer 用来存储完整的‘PATest’后的字符。
while True:
# 同样的, 我们不知道循环的确切次数。同样,我们在循环的内部判断循环终止条件并break出去。
breaking = True
for x, _ in enumerate(count):
if count[x]:
# 对每个字符,如果还有剩的,现在就加上去把。注意for循环已经指定了顺序哦。
answer.extend(chars[x])
count[x] -= 1
breaking = False
# 如果所有字符都消耗完了, breaking就会保持True的状态。
if breaking:
break
print("PATest" * minn + "".join(answer))
# 输出答案,两部分,一是完整的'PATest',二是细碎的字符组成的字符串。
if __name__ == '__main__':
main()
好吧,另一种可能的写法:
def main():
temp = input()
"""
chars2index = {
'P': 0,
'A': 1,
'T': 2,
'e': 3,
's': 4,
't': 5,
}
"""
chars2index = dict(zip([x for x in "PATest"], range(6)))
count = [0 for x in range(6)]
for x in temp:
try:
count[chars2index[x]] += 1
except Exception as e:
pass
answer = []
minn = min(count)
if minn:
for x, _ in enumerate(count):
count[x] -= minn
while True:
breaking = True
for x, _ in enumerate(count):
if count[x]:
answer.extend(list(chars2index.keys())[x])
count[x] -= 1
breaking = False
if breaking:
break
print("PATest" * minn + "".join(answer))
if __name__ == '__main__':
main()
易错点:
- 打字太多就容易出现拼写错误 :}。当程序运行不是如你所愿之时,我认为第一步应该检查是否出现了拼写错误,第二步要看所写之程序的逻辑是否与你想要表达的逻辑准确相吻合。第三步才是反思自己的逻辑是否有漏洞,是否曲解了题意等等。
- python列表的
index( )
方法对于传入的 列表中没有的元素是会返回异常
。
总结:
- extend( )
- dict( )
- enumerate( )
- zip( )
- 如果写程序能让你开心,那再好不过了。(* ^ ▽ ^*)