在分配律和交换律下找到等效结果
我有一个脚本,它循环 5 个数字向量,并将它们与所有四个操作混合,搜索给出特定目标数字结果的组合。
该脚本打印如下输出:
312 / 130 x 350 - 122 + 282 = 1000.0
312 / 130 x 350 + 282 - 122 = 1000.0
312 - 282 x 372 / 15 + 256 = 1000.0
142 + 350 - 372 x 125 / 15 = 1000.0
142 + 350 - 372 / 15 x 125 = 1000.0
350 / 130 x 312 + 282 - 122 = 1000.0
350 + 142 - 372 x 125 / 15 = 1000.0
每行均由数字列表和操作列表格式化。
我想做的是删除等效结果,即输出如下:
312 / 130 x 350 - 122 + 282 = 1000.0
312 - 282 x 372 / 15 + 256 = 1000.0
142 + 350 - 372 x 125 / 15 = 1000.0
作为解决方案,首先,我考虑“记住”已经给出 1000 的数字并跳过那些,但后来我意识到这可能会影响新的结果,所以我不知道该怎么办。
如何找到分配律和交换律下的等价结果?
注意:在显示的输出中,括号未显示,但顺序类似于reduce,这意味着,例如:
142 + 350 - 372 x 125 / 15 = 1000.0
计算如下:
(((142 + 350) - 372) x 125) / 15 = 1000.0
这是我到目前为止的代码:
import operator
from itertools import permutations, product, count
from functools import reduce
vectors = [[87, 125, 209, 312],
[29, 122, 254, 372],
[15, 130, 277, 369],
[142, 197, 282, 383],
[64, 157, 256, 350]]
OPER = {operator.add: '+', operator.sub: '-', operator.mul: 'x',
operator.truediv: '/'}
def format_result(nums, ops, res):
s = ' '.join('{} {}'.format(n,OPER[op]) for n,op in zip(nums, ops))
s += ' {} = {}'.format(nums[-1], res)
return s
def calc(vectors, test=lambda x: x == 1000.):
for vv in permutations(vectors):
for indexes in product((0,1,2,3), repeat=5):
numbers = tuple(v[i] for i,v in zip(indexes, vv))
for operations in permutations(OPER):
res = reduce(lambda x,y,n=count(0): operations[next(n)](x,y),
numbers)
if test(res):
print(format_result(numbers, operations, res))
calc(vectors)
I have a script that loops over 5 vectors of numbers and mix them with all the four operations searching for a combination that give a certain target number as a result.
The script prints an output like:
312 / 130 x 350 - 122 + 282 = 1000.0
312 / 130 x 350 + 282 - 122 = 1000.0
312 - 282 x 372 / 15 + 256 = 1000.0
142 + 350 - 372 x 125 / 15 = 1000.0
142 + 350 - 372 / 15 x 125 = 1000.0
350 / 130 x 312 + 282 - 122 = 1000.0
350 + 142 - 372 x 125 / 15 = 1000.0
Each line is formatted from a list of the numbers and a list of the operations.
What I'd like to do, is to remove the equivalent results, i.e. having an output like:
312 / 130 x 350 - 122 + 282 = 1000.0
312 - 282 x 372 / 15 + 256 = 1000.0
142 + 350 - 372 x 125 / 15 = 1000.0
As a solution, at first, I thought about "remembering" the numbers that already gave 1000 and skip those, but then I realized it might shadow new results, so I don't know what to do.
How can I find the equivalent results under distributive and commutative laws?
Note: In the presented output the parentheses are NOT shown, but the order is reduce-like, meaning that, for example:
142 + 350 - 372 x 125 / 15 = 1000.0
is calculated like:
(((142 + 350) - 372) x 125) / 15 = 1000.0
This is the code I have so far:
import operator
from itertools import permutations, product, count
from functools import reduce
vectors = [[87, 125, 209, 312],
[29, 122, 254, 372],
[15, 130, 277, 369],
[142, 197, 282, 383],
[64, 157, 256, 350]]
OPER = {operator.add: '+', operator.sub: '-', operator.mul: 'x',
operator.truediv: '/'}
def format_result(nums, ops, res):
s = ' '.join('{} {}'.format(n,OPER[op]) for n,op in zip(nums, ops))
s += ' {} = {}'.format(nums[-1], res)
return s
def calc(vectors, test=lambda x: x == 1000.):
for vv in permutations(vectors):
for indexes in product((0,1,2,3), repeat=5):
numbers = tuple(v[i] for i,v in zip(indexes, vv))
for operations in permutations(OPER):
res = reduce(lambda x,y,n=count(0): operations[next(n)](x,y),
numbers)
if test(res):
print(format_result(numbers, operations, res))
calc(vectors)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为可以通过根据对操作数执行的操作对操作数进行分组来解决该问题。示例:
然后,您可以对这些组的顺序施加某些限制:
-
组不能直接出现在+
组之前/
组不能直接出现在+
组之前 每个组内的*
组因此,可能的分组如下所示:
+
连接,然后是 2 个 asc与 a 连接的操作数*
"+
连接,然后 2 个操作数与*
连接,然后 2 个操作数连接。与/
”不可能是这样的:
-
连接,然后3个asc与+
连接。 ” (会与“前 3 个 asc. 操作数与+
连接,然后 2 个 asc.操作数与-
连接)发生冲突我尝试了一种强力方法来创建和填充此类分组,但它慢得难以忍受。也许你可以优化它以提高效率:)也可能是那里有一些微妙的错误,但不幸的是我没有更多的时间来处理它:
希望这有帮助(在至少这个想法:)
I think the problem can be approached by grouping the operands according to the operations performed on them. Example:
You can then place certain constraints on the order of these groups:
-
groups cannot occur directly before+
groups/
groups cannot occur directly before*
groupsPossible groupings would thus look like this:
+
, then 2 asc. operands connected with a*
"+
, then 2 asc. operands connected with a*
, then 2 asc. operands connected with/
"Impossible would be something like this:
-
, then 3 asc. operands connected with+
" (would collide with "first 3 asc. operands connected with a+
, then 2 asc. operands connected with-
I tried a brute-force approach to create and fill such groupings, but it's unbearably slow. Maybe you can optimize it to be more efficient :) Could also be that there's some subtle bug in there, but unfortunately I don't have any more time to work on it:
Hope this helps (at least the idea :)