Python:应用数学运算顺序按照括号中的层次结构对字符串重新排序
Python: apply math order of operations to reorder strings following hierarchy in parentheses
如何使用 Python 重新排序字符串,应用带括号的数学运算顺序?
让我举个例子:
"son(father(granpa)mother))" ===> "granpa father mother son"
想法是使用标准数学排序运算重新排序 原始字符串。在数学顺序操作中,括号具有最高优先级。让我举一个数学例子:
4 + (5 + (3 + 3)) = ((3 + 3) + 5 ) + 4 = 3 + 3 + 5 + 4 = 14
编辑:这个例子只使用+因为python总是在+之前做*,在同一个括号级别,那不是重点,重点是顺序在字符串中,因为只会连接重新排序的结果。
目标是重新排序包含变量的字符串,以研究对操作的可能优化。
我要重新排序的字符串示例:
def xor_with_nands(a,b):
return f"~(~(~({a} & {b}) & {a}) & ~(~({a} & {b}) & {b}))"
>> xor_with_nands(0,1)
>> ~(~(~(0 & 1) & 0) & ~(~(0 & 1) & 1))
>> eval(xor_with_nands(0,1))
>> 1
如果有一种方法可以创建一个函数来根据括号的数学顺序(只是括号,而不是其他数学运算顺序)对字符串进行重新排序,则可以分析某些过程中的优化。
目标是获得一种工具,可以按执行顺序可视化嵌套逻辑操作,以便直观地理解它们并希望简化它们。
您正在寻找调车场算法。
这会将您的数学符号(也称为 中缀符号)转换为计算机可以轻松处理的格式(称为 后缀符号).请参阅此处:https://en.wikipedia.org/wiki/Shunting-yard_algorithm 以获得更好的描述。
本质上,该算法会将您的表达式转换为已正确排序的队列。
这是从 Brilliant.org 中提取的一些伪代码:
1. While there are tokens to be read:
2. Read a token
3. If it's a number add it to queue
4. If it's an operator
5. While there's an operator on the top of the stack with greater precedence:
6. Pop operators from the stack onto the output queue
7. Push the current operator onto the stack
8. If it's a left bracket push it onto the stack
9. If it's a right bracket
10. While there's not a left bracket at the top of the stack:
11. Pop operators from the stack onto the output queue.
12. Pop the left bracket from the stack and discard it
13. While there are operators on the stack, pop them to the queue
这将允许您定义自定义运算符并且定义它们的优先级。
这里我使用了逐个字符处理字符串的递归方法。它不是非常有效,但它完成了工作。
def tokenize_parentheticals(s, idx=None):
# first, use a single-element list as essentially a 'mutable integer'
# that we can pass up and down the chain of recursive calls to never
# move backwards in the string
if idx is None:
idx = [0]
# the start of each token is the character at the beginning of the string.
start = idx[0]
# We will store all tokens in each 'layer' and yield them all at the
# end of the layer
tokens = []
# count through the string character by character, and look for either
# an open-paren or a close-paren
while idx[0] < len(s):
c = s[idx[0]]
idx[0] += 1
# if we encounter an open-paren, then
# (1) terminate the current token and add it to our list
# (2) recurse inside the next set of parentheses
# once we return from the recursion, update the start of the next
# token to the character after the most recent close-paren
if c == '(':
tokens.append(s[start:idx[0] - 1])
yield from tokenize_parentheticals(s, idx)
start = idx[0]
# If we encounter a close-paren, then
# (1) terminate the current token and add it to our list
# (2) un-recurse, go up a level
elif c == ')':
tokens.append(s[start:idx[0] - 1]
break
# before exiting, yield all non-empty tokens
yield from (t for t in tokens if t)
inp = "son(father(granpa)mother))"
' '.join(tokenize_parentheticals(inp))
# 'granpa father mother son'
list(tokenize_parentheticals('4 + (5 + (3 + 3))'))
# ['3 + 3', '5 + ', '4 + ']
list(tokenize_parentheticals(xor_with_nands(0, 1)))
# ['0 & 1', '~', ' & 0', '0 & 1', '~', ' & 1', '~', ' & ~', '~']
免责声明:我写这个答案时没有阅读对您问题的编辑以及您对此的实际用途。这可能不是一个足够强大的解决方案来满足您的需求。根据需要自定义。
这可能会有帮助:
from collections import defaultdict
import re
def sort_terms(s, ops = ''):
d = defaultdict(list)
depth = 0
pattern = r'[()]|[^( )' + ops + ']+'
for item in re.findall(pattern,s):
if item == '(':
depth += 1
elif item == ')':
depth -= 1
else:
d[depth].append(item)
terms = []
for depth in sorted(d.keys(),reverse = True):
terms.extend(d[depth])
return terms
示例:
>>> sort_terms("son(father(granpa)mother))")
['granpa', 'father', 'mother', 'son']
>>> sort_terms('4 + (5 + (3 + 3))','+')
['3', '3', '5', '4']
>>> '+'.join(sort_terms('4 + (5 + (3 + 3))','+'))
'3+3+5+4'
>>> sort_terms('~(~(~(0 & 1) & 0) & ~(~(0 & 1) & 1))','~&')
['0', '1', '0', '1', '0', '1']
运算符本身已被剥离,但在问题本身中您表示您只想注意括号。
如何使用 Python 重新排序字符串,应用带括号的数学运算顺序?
让我举个例子:
"son(father(granpa)mother))" ===> "granpa father mother son"
想法是使用标准数学排序运算重新排序 原始字符串。在数学顺序操作中,括号具有最高优先级。让我举一个数学例子:
4 + (5 + (3 + 3)) = ((3 + 3) + 5 ) + 4 = 3 + 3 + 5 + 4 = 14
编辑:这个例子只使用+因为python总是在+之前做*,在同一个括号级别,那不是重点,重点是顺序在字符串中,因为只会连接重新排序的结果。
目标是重新排序包含变量的字符串,以研究对操作的可能优化。 我要重新排序的字符串示例:
def xor_with_nands(a,b):
return f"~(~(~({a} & {b}) & {a}) & ~(~({a} & {b}) & {b}))"
>> xor_with_nands(0,1)
>> ~(~(~(0 & 1) & 0) & ~(~(0 & 1) & 1))
>> eval(xor_with_nands(0,1))
>> 1
如果有一种方法可以创建一个函数来根据括号的数学顺序(只是括号,而不是其他数学运算顺序)对字符串进行重新排序,则可以分析某些过程中的优化。
目标是获得一种工具,可以按执行顺序可视化嵌套逻辑操作,以便直观地理解它们并希望简化它们。
您正在寻找调车场算法。
这会将您的数学符号(也称为 中缀符号)转换为计算机可以轻松处理的格式(称为 后缀符号).请参阅此处:https://en.wikipedia.org/wiki/Shunting-yard_algorithm 以获得更好的描述。
本质上,该算法会将您的表达式转换为已正确排序的队列。
这是从 Brilliant.org 中提取的一些伪代码:
1. While there are tokens to be read:
2. Read a token
3. If it's a number add it to queue
4. If it's an operator
5. While there's an operator on the top of the stack with greater precedence:
6. Pop operators from the stack onto the output queue
7. Push the current operator onto the stack
8. If it's a left bracket push it onto the stack
9. If it's a right bracket
10. While there's not a left bracket at the top of the stack:
11. Pop operators from the stack onto the output queue.
12. Pop the left bracket from the stack and discard it
13. While there are operators on the stack, pop them to the queue
这将允许您定义自定义运算符并且定义它们的优先级。
这里我使用了逐个字符处理字符串的递归方法。它不是非常有效,但它完成了工作。
def tokenize_parentheticals(s, idx=None):
# first, use a single-element list as essentially a 'mutable integer'
# that we can pass up and down the chain of recursive calls to never
# move backwards in the string
if idx is None:
idx = [0]
# the start of each token is the character at the beginning of the string.
start = idx[0]
# We will store all tokens in each 'layer' and yield them all at the
# end of the layer
tokens = []
# count through the string character by character, and look for either
# an open-paren or a close-paren
while idx[0] < len(s):
c = s[idx[0]]
idx[0] += 1
# if we encounter an open-paren, then
# (1) terminate the current token and add it to our list
# (2) recurse inside the next set of parentheses
# once we return from the recursion, update the start of the next
# token to the character after the most recent close-paren
if c == '(':
tokens.append(s[start:idx[0] - 1])
yield from tokenize_parentheticals(s, idx)
start = idx[0]
# If we encounter a close-paren, then
# (1) terminate the current token and add it to our list
# (2) un-recurse, go up a level
elif c == ')':
tokens.append(s[start:idx[0] - 1]
break
# before exiting, yield all non-empty tokens
yield from (t for t in tokens if t)
inp = "son(father(granpa)mother))"
' '.join(tokenize_parentheticals(inp))
# 'granpa father mother son'
list(tokenize_parentheticals('4 + (5 + (3 + 3))'))
# ['3 + 3', '5 + ', '4 + ']
list(tokenize_parentheticals(xor_with_nands(0, 1)))
# ['0 & 1', '~', ' & 0', '0 & 1', '~', ' & 1', '~', ' & ~', '~']
免责声明:我写这个答案时没有阅读对您问题的编辑以及您对此的实际用途。这可能不是一个足够强大的解决方案来满足您的需求。根据需要自定义。
这可能会有帮助:
from collections import defaultdict
import re
def sort_terms(s, ops = ''):
d = defaultdict(list)
depth = 0
pattern = r'[()]|[^( )' + ops + ']+'
for item in re.findall(pattern,s):
if item == '(':
depth += 1
elif item == ')':
depth -= 1
else:
d[depth].append(item)
terms = []
for depth in sorted(d.keys(),reverse = True):
terms.extend(d[depth])
return terms
示例:
>>> sort_terms("son(father(granpa)mother))")
['granpa', 'father', 'mother', 'son']
>>> sort_terms('4 + (5 + (3 + 3))','+')
['3', '3', '5', '4']
>>> '+'.join(sort_terms('4 + (5 + (3 + 3))','+'))
'3+3+5+4'
>>> sort_terms('~(~(~(0 & 1) & 0) & ~(~(0 & 1) & 1))','~&')
['0', '1', '0', '1', '0', '1']
运算符本身已被剥离,但在问题本身中您表示您只想注意括号。