一、主要思路

  • 拒绝多个 for 循环,本题只有 4 张牌,但如果是 8、16、32、64、128、256、1024 张牌,难道还写 for 循环吗?
  • 四张牌计算得 24,可以拆解为 3 张牌计算结果和第四章进行计算的 24。可以采用递归。
  • 可以使用字典或列表的 index 来转换牌的面值和实际的大小

二、简化问题

2.1 思路

首先可以计算简单的场景,假设四张牌按顺序是固定的,看能否得出 24。

  1. 首先将牌面切换成牌的实际大小组成新的列表,方便比较
  2. 每次取前面的 2 张牌,并且记住顺序,分别进行 + - * // 运算,然后将其值插入剩余的牌的开头组成新的牌组(该牌组中的牌的值,可能会超出正常牌组所有可能出现的值),迭代此过程
  3. 迭代的终点:当牌组中牌的数量为 1 时,该张牌的值即为最终的计算结果,若等于 24,本次计算过程即为最终答案。
  4. 若存在正确的计算结果,则将每次计算的过程添加到一个专门用于存储计算步骤的列表中,该列表即为最后需要的答案

2.2 代码

cards = ['0', 'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'joker', 'JOKER']


class A:
    def __init__(self, nums):
        self.nums = nums
        self.rst = []

    def __func(self, nums):
        # print(nums)
        if len(nums) == 1:
            if nums[0] == 24:
                return True
            else:
                return False

        cur1 = nums.pop(0)
        cur2 = nums.pop(0)
        if self.__func([cur1 + cur2] + nums):
            self.rst.insert(0, cur2)
            self.rst.insert(0, '+')
            return True
        elif self.__func([cur1 - cur2] + nums):
            self.rst.insert(0, cur2)
            self.rst.insert(0, '-')
            return True
        elif self.__func([cur1 * cur2] + nums):
            self.rst.insert(0, cur2)
            self.rst.insert(0, '*')
            return True
        elif self.__func([cur1 // cur2] + nums):
            self.rst.insert(0, cur2)
            self.rst.insert(0, '/')
            return True
        return False

    def func(self):
        self.__func(self.nums[:])
        if self.rst:
            self.rst.insert(0, self.nums[0])


s = input()
if 'joker' in s or 'JOKER' in s:
    print('ERROR')
else:
    nums = [cards.index(_) for _ in s.split()]
    a = A(nums=nums)
    a.func()
    if a.rst:
        print("".join(cards[_] if isinstance(_, int) else _ for _ in a.rst))
    else:
        print('NONE')

三、最终解法

3.1 思路

  • 在前目的步骤中,我们每次取牌组中的牌时,可以不按顺序取,则每次第一张牌可以取的方式为 len(牌组) 个,第二张牌可以取的方式为 len(剔除第一张牌后的新牌组) 个
  • 首先随机取出第一张牌,然后剩余的牌组成新的牌组,使用第一张牌和剩余牌组进行迭代,每次迭代只需要循环取第二张牌然后和第一张牌进行计算即可

3.2 代码

cards = ['0', 'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'joker', 'JOKER']


class A:
    def __init__(self, nums):
        self.nums = nums
        self.rst = []

    def __func(self, cur1, nums):
        # print(nums)
        if len(nums) == 0:
            if cur1 == 24:
                return True
            else:
                return False

        for i in range(len(nums)):
            nums2 = nums[:]
            cur2 = nums2.pop(i)
            if self.__func(cur1 + cur2, nums2):
                self.rst.insert(0, cur2)
                self.rst.insert(0, '+')
                return True
            elif self.__func(cur1 - cur2, nums2):
                self.rst.insert(0, cur2)
                self.rst.insert(0, '-')
                return True
            elif self.__func(cur1 * cur2, nums2):
                self.rst.insert(0, cur2)
                self.rst.insert(0, '*')
                return True
            elif cur2 != 0 and self.__func(cur1 // cur2, nums2):
                self.rst.insert(0, cur2)
                self.rst.insert(0, '/')
                return True
        return False

    def func(self):
        for i in range(len(self.nums)):
            nums = self.nums[:]
            cur1 = nums.pop(i)
            if self.__func(cur1, nums):
                self.rst.insert(0, cur1)
                break


s = input()
if 'joker' in s or 'JOKER' in s:
    print('ERROR')
else:
    nums = [cards.index(_) for _ in s.split()]
    a = A(nums=nums)
    a.func()
    if a.rst:
        # print(a.rst)
        print("".join(cards[_] if isinstance(_, int) else _ for _ in a.rst))
    else:
        print('NONE')