给定数字列表,在使用 +-*/ 获得特定结果时保持数字顺序

发布于 2024-11-19 13:08:09 字数 792 浏览 1 评论 0原文

不确定以前是否有人问过这个问题,但找不到此类问题的具体提及。

这是子集和和背包的变体。

虽然类似的问题似乎之前已被问过,但逻辑足够不同,足以保证一个新的线程。

参数 : 给出了总数以及整数列表。 整数可以以任意数量的方式组合(例如 1 2 3 = 12, 3 或 1, 23 或 1, 2 3) 允许 3 种运算:

  • 1 加法
  • 1 减法
  • 1 除法

示例:

1 2 9 3 7 4 = 22

解决方案:

(129 - 3) / 7 + 4 = 22

此类练习有分类吗? (例如子集和等)

一些想法:

  1. 创建所有可能的数字组合的多维数组。 由于只允许使用 3 个运算符,因此该数组将包含 3 列/元素。

  2. 在点 1、2 或 3 处随机插入运算符并进行暴力破解,直到找到解决方案。

这与优雅的解决方案相差甚远。
任何见解将不胜感激。

我可能会用 Perl 编写这个代码,但任何语言的伪代码、指针或语法都很棒。对我缺乏数学资金的傲慢嘲笑也很酷;)

提前致谢!

Not sure if this has been asked before, but couldn't find a specific mention of this type of problem.

This is a variant of subset sum and knapsack.

Although a similar question appears to have been asked before, but the logic is different enough to warrant a new thread.

Parameters :
The total is given as well as a list of integers.
The integers can be combined any number of ways (e.g. 1 2 3 = 12, 3 or 1, 23 or 1, 2 3)
3 operations are allowed :

  • 1 addition
  • 1 subtraction
  • 1 division

Sample :

1 2 9 3 7 4 = 22

Solution :

(129 - 3) / 7 + 4 = 22

Is there a classification for this type of exercise? (e.g. subset-sum, etc.)

Some thoughts :

  1. Create a multidimensional array of all possible number combinations.
    Since only 3 operators are allowed, the array would contain 3 columns/elements.

  2. Randomly insert the operators at points 1, 2 or 3 and brute-force until a solution is reached.

This is monumentally distant from an elegant solution.
Any insight would be appreciated.

I will probably code this in Perl, but pseudo code, pointers or syntax in any language would be great. Haughty sneering at my lack of mathematical wherewithal is also cool ;)

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

颜漓半夏 2024-11-26 13:08:09

我刚刚回答了这个问题,但它被错误地迁移到另一个 stackexchange 站点:https://codegolf.stackexchange.com/questions/ 3019/从数字串中获取答案/3027#3027

这种类型的运动有分类吗? (例如子集和等)

我将其称为查找列表的所有二元运算符“约简”,以任意顺序应用,使用运算符 +-*/10a+b/concat


这是 Python 中的一种强力方法。在下面树中的每个节点,取左侧和右侧可能性的笛卡尔积。对于每一对,将所有运算符应用于它,以产生一组新的可能性。你必须小心不要这样做 (1-2)3 = -13;您可以通过创建 Digit 对象来解决此问题。

下面是加泰罗尼亚数字的图示,其中每个节点都是一个运算符。操作数量大致为 Catalan(#digits-1) * #operators^(#digits-1)。如果#digits=10那么应该只需要尝试大约十亿件事。

在此处输入图像描述

使用 如何打印表达式所有可能的平衡括号? 我们可以这样写:

#!/usr/bin/python3

import operator as op
from fractions import Fraction
Fraction.__repr__ = lambda self: '{}/{}'.format(self.numerator, self.denominator)

Digits = tuple

operators = {op.add, op.sub, op.mul, Fraction}

def digitsToNumber(digits):
    """
        (1,2,3) -> 123
        123 -> 123
    """
    if isinstance(digits, Digits):
        return sum(d * 10**i for i,d in enumerate(reversed(digits)))
    else: # is int or float
        return digits

def applyOperatorsToPossibilities(left, right):
    """
        Takes every possibility from the left, and every
        possibility from the right, and takes the Cartesian
        product. For every element in the Cartesian product,
        applies all allowed operators.

        Returns new set of merged possibilities, ignoring duplicates.
    """
    R = set() # subresults
    def accumulate(n):
        if digitsToNumber(n)==TO_FIND:
            raise Exception(n)
        else:
            R.add(n)

    for l in left:
        for r in right:
            if isinstance(l, Digits) and isinstance(r, Digits):
                # (1,2),(3) --> (1,2,3)
                accumulate(l+r)
            for op in operators:
                #  12,3 --> 12+3,12-3,12*3,12/3
                l = digitsToNumber(l)
                r = digitsToNumber(r)
                try:
                    accumulate(op(l,r))
                except ZeroDivisionError:
                    pass

    return R

def allReductions(digits):
    """
        allReductions([1,2,3,4])
        [-22, -5, -4, -3, -5/2, -1/1, -1/3, 0, 1/23, 1/6, 1/5, 1/3, 2/3, 1/1, 3/2, 5/3, 2, 7/2, 4/1, 5, 6, 7, 9, 15, 23, 24, 36, 123]
    """
    for reduction in set.union(*associations(
            digits, 
            grouper=applyOperatorsToPossibilities, 
            lifter=lambda x:{(x,)})
            ):
        yield digitsToNumber(reduction)

TO_FIND = None
INPUT = list(range(1,4))
print(sorted(allReductions(INPUT)))

I just answered this question, but it was incorrectly migrated to another stackexchange site: https://codegolf.stackexchange.com/questions/3019/getting-an-answer-from-a-string-of-digits/3027#3027

Is there a classification for this type of exercise? (e.g. subset-sum, etc.)

I would call it finding all the binary-operator "reductions" of a list, applied in arbitrary order, with the operators +, -, *, /, and 10a+b/concat


Here's a brute-force approach in python. At every node in the trees below, take the Cartesian product of the possibilities on the left and the right. For each pair, apply all operators to it, to produce a set of new possibilities. You have to be careful not to do (1-2)3 = -13; you can get around this issue by creating Digit objects.

Below is an illustration of Catalan numbers where each node is an operator. The number of operations will be roughly Catalan(#digits-1) * #operators^(#digits-1). If #digits=10 then it should only be about a billion things to try.

enter image description here

Using How to print all possible balanced parentheses for an expression? we can write:

#!/usr/bin/python3

import operator as op
from fractions import Fraction
Fraction.__repr__ = lambda self: '{}/{}'.format(self.numerator, self.denominator)

Digits = tuple

operators = {op.add, op.sub, op.mul, Fraction}

def digitsToNumber(digits):
    """
        (1,2,3) -> 123
        123 -> 123
    """
    if isinstance(digits, Digits):
        return sum(d * 10**i for i,d in enumerate(reversed(digits)))
    else: # is int or float
        return digits

def applyOperatorsToPossibilities(left, right):
    """
        Takes every possibility from the left, and every
        possibility from the right, and takes the Cartesian
        product. For every element in the Cartesian product,
        applies all allowed operators.

        Returns new set of merged possibilities, ignoring duplicates.
    """
    R = set() # subresults
    def accumulate(n):
        if digitsToNumber(n)==TO_FIND:
            raise Exception(n)
        else:
            R.add(n)

    for l in left:
        for r in right:
            if isinstance(l, Digits) and isinstance(r, Digits):
                # (1,2),(3) --> (1,2,3)
                accumulate(l+r)
            for op in operators:
                #  12,3 --> 12+3,12-3,12*3,12/3
                l = digitsToNumber(l)
                r = digitsToNumber(r)
                try:
                    accumulate(op(l,r))
                except ZeroDivisionError:
                    pass

    return R

def allReductions(digits):
    """
        allReductions([1,2,3,4])
        [-22, -5, -4, -3, -5/2, -1/1, -1/3, 0, 1/23, 1/6, 1/5, 1/3, 2/3, 1/1, 3/2, 5/3, 2, 7/2, 4/1, 5, 6, 7, 9, 15, 23, 24, 36, 123]
    """
    for reduction in set.union(*associations(
            digits, 
            grouper=applyOperatorsToPossibilities, 
            lifter=lambda x:{(x,)})
            ):
        yield digitsToNumber(reduction)

TO_FIND = None
INPUT = list(range(1,4))
print(sorted(allReductions(INPUT)))
余罪 2024-11-26 13:08:09

一种简单的暴力方法似乎效果很好。

让我们使用 RPN 来避免括号。将输入拆分为单个数字,并尝试在数字之间插入运算符(即:无、空格和算术运算符),直到结果字符串计算为目标值。

javascript 中的示例: http://jsfiddle.net/B5NdN/4 。我只是从 0 到 6^(输入长度​​)循环以获得所有可能的运算符组合,您的任务可能需要更复杂的东西,但原则仍然存在。

A simple brute-force approach that seems to work quite well.

Let's use RPN to avoid parenthesis. Split the input into single digits and try inserting operators (which are: nothing, space and arithmetic operators) in between digits until the resulting string evaluates to the target value.

An illustration in javascript: http://jsfiddle.net/B5NdN/4 . I simply loop from 0 to 6^(input length) to obtain all possible operators' combinations there, your task may require something more sophisticated, but the principle remains.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文