1043 输出PATest

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( ) 方法对于传入的 列表中没有的元素是会返回异常

总结:


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值