【问题标题】:Pattern Calculator Python模式计算器 Python
【发布时间】:2019-11-30 02:17:54
【问题描述】:

我的一个朋友在一次采访中向我展示了他在编码挑战中遇到的一个有趣的问题。所以你有一个像 n = 3413289830 这样的数字和像 p = a-bcdefghij 这样的模式,你需要创建一个函数来接受这个输入和输出 -413289827。显然,它应该适用于任何数字和字母的加减法组合。我编写了这段代码,但我很确定它可以改进,因为我认为它有点低效。

pattern = 'a-bcdefghij'       
n = '3413289830'
lst = []
def splitnb(n, pattern):
    save = dict()
    if(len(n) != len(pattern) - 1):
        print('Pattern needs to match number')
    else:
        if( '-' in pattern):
            patlst = pattern.split('-')
        elif('+' in pattern):
            patlst = pattern.split('+')
        for char in n:
            a = list(n)
        for pat in patlst:
            first  = patlst[0].split()
            rest = pat.split()
        for l in first[0]:
            f1 = l
            lst.append(f1)
        for l2 in rest[0]:
            f2 = l2
            lst.append(f2)
        save = dict(zip(lst, a))
        nb = ''
        if( '-' in pattern):
            for i in first[0]:
                numb = int(save.get(i))
            for j in rest[0]:
                nb += save.get(j)
                numb1 = numb - int(nb)
        elif('+' in pattern):
            for i in first[0]:
                numb = int(save.get(i))
            for j in rest[0]:
                nb += save.get(j)
                numb1 = numb + int(nb)
    return numb1

f1 = splitnb(n, pattern)
f2 = splitnb('1234', 'ab+cd')
f3 = splitnb('22', 'a-b')

【问题讨论】:

  • 如果有-,就不能有+
  • @AMC 显然那将是理想的,我只是在它只包含一个操作的级别上想到它
  • 我已经忘记了这一切。快速提问:你为什么到处使用dict.get()
  • @AMC ,我正在遍历字典并使用 dict.get(index) 获取该索引处的项目并计算数字
  • @AMC,我基本上将整个操作拆分为 2 个列表,第一个列表和其余列表,然后将它们压缩到 dict 中迭代它们以计算结果。我知道这不是迄今为止最好的方法,但它是第一次尝试并在大约 35-40 分钟内完成,所以我本可以更明显地完成它

标签: python python-3.x algorithm calculator


【解决方案1】:

一种方法是采用模式并将每个字符替换为应该存在的数字,然后eval 结果

string.ascii_letters 是一个由所有 ascii 字符组成的字符串,按字母顺序以小写开头。这可用于将 char 转换为应从 n 中提取的数字的索引

>>> [n[string.ascii_letters.index(x)] if x in string.ascii_letters else x for x in pattern]
['3', '-', '4', '1', '3', '2', '8', '9', '8', '3', '0']

我们添加if x in string.ascii_letters else x,这样操作符就不会被转换。然后加入结果列表以获取字符串

>>> ''.join(n[string.ascii_letters.index(x)] if x in string.ascii_letters else x for x in pattern)
'3-413289830'

删除括号会将列表理解变成一个生成器,它应该会稍微提高一点性能。然后你可以使用eval 来运行这个字符串,就像它是 python 代码一样

>>> eval(''.join(n[string.ascii_letters.index(x)] if x in string.ascii_letters else x for x in pattern))
-413289827

只有在您信任所提供的输入时才应该使用 eval,因为它可以执行任意代码

【讨论】:

  • @AlexanderCécile 这里有一个问题可以解决这个问题,尽管它涉及安装第三方包stackoverflow.com/questions/43836866/…
  • 哦不,我的意思是像没有任何东西eval()-style。
【解决方案2】:

可以使用正则表达式拆分和 zip_longest 将其变得小而干净,如下所示

import re
from itertools import zip_longest

pattern = 'a-bcdefghij'       
n = '3413289830'

lst = re.split("[^a-z]", pattern)
oprs = [None] + re.findall("[^a-z]", pattern)

result = 0
for x, opr in zip_longest(lst, oprs):
    op = int(n[:len(x)])
    n = n[len(x):]

    if opr == "-":
        op = -op
    result+=op


result

【讨论】:

    【解决方案3】:

    你想要

    • 确定应该应用的操作
    • 找到分割的位置
    • 使用拆分的部分作为操作数来应用操作

    一种方法是循环遍历模式以查找操作数及其在列表中的位置,这也是拆分的位置,然后将运算符与执行所需操作的operator 模块中的函数匹配.如果不允许使用 operator 模块,您可以编写自己的函数。

    import operator
    
    operators = { 
        '+': operator.add,
        '-': operator.sub,
        '*': operator.mul,
        '/': operator.truediv,
    }
    # operator not allowed?  Then '+': def add(a, b):return a + b etc.
    
    def splitnb(n, pattern):
        if len(n) != len(pattern) - 1:
            print("Pattern needs to match number")
            return
        # Find the operator and its position.
        for _i, op in enumerate(pattern):
            if not op.isalpha():
                break
        # Lookup the operator and execute it.
        return operators[op](int(n[:_i]), int(n[_i:]))
    

    如果允许pattern 不包含运算符,或者运算符可能位于数字字符串的开头或结尾,那么您需要为这些情况添加一些验证。

    【讨论】:

      猜你喜欢
      • 2015-02-25
      • 2021-07-28
      • 1970-01-01
      • 1970-01-01
      • 2020-07-23
      • 1970-01-01
      • 2010-10-05
      • 1970-01-01
      相关资源
      最近更新 更多