【发布时间】:2019-01-27 00:25:47
【问题描述】:
我想在 Python 中生成所有可能的 RPN (Reverse Polish notation) 表达式,这些表达式使用输入列表中的字母(例如 ['a', 'b', 'c'])并包含运算符 ['+', '-', '*', '/']。
我的想法是,我们可以向当前表达式添加元素,直到发生以下情况之一:要么我们已经使用了所有字母,要么表达式完整(即我们不能添加更多运算符)。
所以我写了以下函数:
1)
'''
The function returns True if we can add operator to current expression:
we scan the list and add +1 to counter when we meet a letter
and we add -1 when we meet an operator (it reduces
last two letters into 1 (say ab+ <--> a + b)
'''
def can_add_operator(string_):
n = 0
for letter in string_:
if letter not in ['+', '-', '*', '/']:
n += 1
else:
n -= 1
result = n > 1
return result
can_add_operator('ab*c+')) #False
can_add_operator('ab*c') #True
2)
'''
The function returns a list, that contains operators and
letters, one of which we can add to the current expression.
'''
def possible_elements(items, string_):
#list of all letters that we have not used yet
result = [x for x in items if x not in string_]
if can_add_operator(string_):
result = ["+", "-", "*", "/"] + result
return result
letters = ['a', 'b', 'c', 'd']
possible_elements(letters, 'ab*c') #['+', '-', '*', '/', 'd']
possible_elements(letters, '') #['a', 'b', 'c', 'd']
possible_elements(letters, 'ab*c+d+') #[]
3) 接下来我把它包装成递归:
#exp -- current expression, base of recursion is exp = ''
def rec(exp, Final_sol = []):
elements_to_try = possible_elements(letters, exp)
for i in elements_to_try:
if len(possible_elements(letters, exp + i)) == 0:
Final_sol.append(exp + i)
else:
rec(exp+i, Final_sol)
return Final_sol
#we start with an empty string
Final_sol = rec('')
print(len(Final_sol)) #7680
该功能有两个困难:
-
第一个是如果列表中有重复字母 字母,它不会返回所有可能的结果。
例如如果
letters = ['a', 'b', 'a']:Final_sol = rec('') print(len(Final_sol)) #32 str(Final_sol) >> "['ab+', 'ab-', 'ab*', 'ab/', 'ba+', 'ba-', 'ba*', 'ba/', 'ba+', 'ba-', 'ba*', 'ba/', 'ab+', 'ab-', 'ab*', 'ab/', 'ab+', 'ab-', 'ab*', 'ab/', 'ba+', 'ba-', 'ba*', 'ba/', 'ba+', 'ba-', 'ba*', 'ba/', 'ab+', 'ab-', 'ab*', 'ab/']"所以输出缺少
'ab+a+'等等。但我确实想归还所有 在这种情况下也有可能的组合。 第二个问题是有很多"equivalent"字符串在 输出。因为我们有commutative 和associative 前缀形式的属性,表达式如
ab+c+/abc++/ca+b+应该被认为是等效的:我只想要每个组中的一个 函数rec()的输出。
我们如何改变上面的函数来克服这些困难?解决问题最优雅的方法是什么?
【问题讨论】:
-
您认为不同的表达方式是什么?例如,
ab+和ba+是否不同?abc++和ab+c+怎么样? (取决于你对第一个问题的回答,ca+b+和朋友?) -
@rici 嗯,这是个好问题。起初我没有想到这种情况:) 如果我能生成“不同”,因为它们以前缀形式提供不同的 results,那将是最好的,这样
ab+/ba+和abc++/ab+c+是相同的等等。 -
@Dima:通过在所有输入(包括子表达式!)上定义一个顺序并要求交换运算符的操作数以升序出现(所以没有
ba+at全部)。 -
为什么我们不能在字母用完之前无法附加我们的表达式?例如。
<letter> +可以安全地添加到任何 RPN 表达式中。 -
我想知道
'ab+'是否仍然是letters = ['a', 'b', 'a']的解决方案,这意味着应该使用所有元素还是只是从字母中随机挑选。
标签: python algorithm recursion postfix-notation rpn