Python笔试——雀魂启动

题目描述:

小包最近发明了一种新的麻将,具体的规则如下:

总共有36张牌,每张牌是1~9。每个数字4张牌。
你手里有其中的14张牌,如果这14张牌满足如下条件,即算作和牌
14张牌中有2张相同数字的牌,称为雀头。
除去上述2张牌,剩下12张牌可以组成4个顺子或刻子。顺子的意思是递增的连续3个数字牌(例如234,567等),刻子的意思是相同数字的3个数字牌(例如111,777)

例如:
1 1 1 2 2 2 6 6 6 7 7 7 9 9 可以组成1,2,6,7的4个刻子和9的雀头,可以和牌
1 1 1 1 2 2 3 3 5 6 7 7 8 9 用1做雀头,组123,123,567,789的四个顺子,可以和牌
1 1 1 2 2 2 3 3 3 5 6 7 7 9 无论用1 2 3 7哪个做雀头,都无法组成和牌的条件。

现在,小包从36张牌中抽取了13张牌,他想知道在剩下的23张牌中,再取一张牌,取到哪几种数字牌可以和牌。

输入描述:

输入只有一行,包含13个数字,用空格分隔,每个数字在1~9之间

数据保证同种数字最多出现4次。

输出描述:

输出同样是一行,包含1个或以上的数字。代表他再取到哪些牌可以和牌。

若满足条件的有多种牌,请按从小到大的顺序输出。若没有满足条件的牌,请输出一个数字0

 

思路:

原理:如果该手牌胡牌,那么每个数字必然是,雀头、刻子、顺子的成员,
递归算法 : 从最小的数字开始尝试,如果把其当成雀头成员,该数字划掉两个,并看余下的数字能否划空
如果是刻子成员,该数字划掉三个,并查看余下数字能否划空
如果是顺子成员,划掉该值a, a + 1, a + 2,并查看余下数字能否划空
如果上述三种尝试都无法划空数组,说明存在数字无法是雀头、刻子、顺子的成员,
将一个数字牌补入13个牌之中,判断是否和牌,是则输出,不是则下一个数字牌

代码实现:

getNumFromString = lambda x:list(map(int,x.strip().split()))
def isHePai(str):
    lenth = len(str)
    if lenth == 0:
        return True
    count1 = str.count(str[0])
    # 第一个数字出现的次数 >= 2,且不是刻子,去掉雀头剩下的能不能和牌
    if lenth%3!=0 and count1>=2 and isHePai(str[2:]):
        return True
    # 第一个数字是刻子,去掉刻子剩下的能不能和牌
    if count1>=3 and isHePai(str[3:]):
        return True

    # 如果存在顺子,移除顺子后剩下的能和牌
    if str[0]+1 in str and str[0]+2 in str:
        str1 = str[1:]
        str1.remove(str[0]+1)
        str1.remove(str[0]+2)
        if isHePai(str1):
            return True
    return False


if __name__ == '__main__':
    a = getNumFromString(input())
    flag = 0
    for i in range(1,10):
        li = sorted(a+[i])  #这里要注意a+[i]与a.append(i)的区别(即a本身是否变化)
        if li.count(i)>4:
            continue
        else:
            # 判断
            if isHePai(li):
                flag = 1
                print(i,end=' ')
    # 若到了这步说明还没和牌
    if flag == 0:
        print('0')

 

收获:

  1. 对于列表a,a+[x] 与 a.append(x) 是有区别的,前者a不变,后者a变了。
  2. 做递归时,第一步一定要设置终止条件
  3. 做这类 若没有符合条件的则输出0的题目,可以设置一个标志位(flag)来进行区分。

 

昨天忙太晚了,没有更新题目,今天上午补上!

posted @ 2020-08-07 13:00  Achilles_Heel  阅读(418)  评论(0编辑  收藏  举报