【问题标题】:AS3: adding different numbers in an array to get specific result.AS3:在数组中添加不同的数字以获得特定的结果。
【发布时间】:2023-03-04 17:11:01
【问题描述】:

我有一个 numberArray。 它包含整数 - 在特定范围内随机化。 我想得到一个特定的总和,但不是针对 numberArray 中的所有内容, 更多的尝试在 numberArray 中总结不同数量的数字(总共 5 个),看看它是否会得到所需的特定总数。如果没有,它将随机化另一个数字来接管 numberArray 中的一个数字。

最简单的方法是什么?

做很多事情

    if (numberArray[1] + numberArray[2] == specificNumber) 
    {
    }
    if (numberArray[1] + numberArray[3] == specificNumber)
    {
    }

等等。等等等等 代码行太多,似乎有更简单的代码。现在我的数组中只有5个不同的数字,所以它仍然可以忍受,但是如果数字的数量更高...... ......

【问题讨论】:

  • 问题是什么?
  • 假设numberArray是[ 1, 2, 3, 4, 5, 2, 3],具体的num是8,要不要找出1+2+5 = 8, 3 + 5 = 8 等等?
  • 是的。甚至 2+2+3+1 = 8。

标签: actionscript-3 flash


【解决方案1】:

像这样阅读您的问题:对于您的随机整数数组,找到一组(或所有)具有给定总和的整数。

这是一个 NP 完全问题 - 即没有已知的算法可以有效地解决它

fastest known way 相当复杂,因此我们将采用一个简单的解决方案 - 如果您不是在每一帧上都这样做或者输入集很大,那么应该就足够了。

这也适用于输入集中的 0 或负值。

// The sum we're looking for:
var requiredSum:int              = 8;
// Our input set:
var numberArray:Array            = [1, 2, 3, 4, 5, 2, 3];
// Results will be stored here:
var resultSets:Array             = [];

// Go through all possible subset sizes.
// This allows subset sizes all the way up to the size of 
// the input set (numberArray.length).
// You can modify it to a fixed value (say, 5), of course:
for (var subsetSize:int = 1; subsetSize <= numberArray.length; subsetSize++)
{
   // We'll use the same array for all our attempts of this size:
   var subset:Array = new Array(subsetSize);
   findSum(numberArray, subset, 0, 0);
}

// Output results:
for (var i:int = 0; i < resultSets.length; i++)
{
    trace(resultSets[i].join("+"));
}

// numberArray : Our input set
// subset      : The set we're currently filling
// setIndex    : The position we're at in numberArray
// subsetIndex : The position we're at in the set we're filling
function findSum(numberArray:Array, subset:Array, setIndex:int, 
                 subsetIndex:int):void
{
   // Try every value from the input set starting from our current position, 
   // and insert the value at the current subset index:
   for (var index:int = setIndex ; index < numberArray.length; index++)
   {
      subset[subsetIndex] = numberArray[index];

      // Have we filled the subset?
      if (subsetIndex == subset.length - 1)
      {
         var sum:int = 0;
         for (var i:int = 0; i < subset.length; i++)
         {
            sum += subset[i];
         }

         if (sum == requiredSum)
         {
            // Clone the array before adding it to our results, 
            // since we'll be modifying it if we find more:
            resultSets.push(subset.concat());
         }
      }
      else
      {
         // Recursion takes care of combining our subset so far
         // with every possible value for the remaining subset indices:
         findSum(numberArray, subset, index + 1, subsetIndex + 1);
      }
   }
}

上述代码中使用的值的输出:

3+5
5+3
1+2+5
1+3+4
1+4+3
1+5+2
2+3+3
2+4+2
3+2+3
1+2+3+2
1+2+2+3

如果我们只需要知道是否存在和,则不需要结果集 - 我们只需返回真/假,并在找到和时完全退出递归算法:

var requiredSum:int   = 8;
var numberArray:Array = [1, 2, 3, 4, 5, 2, 3];

// Go through all possible subset sizes:
for (var subsetSize:int = 1; subsetSize <= numberArray.length; subsetSize++)
{
   // We'll use the same array for all our attempts of this size:
   var subset:Array = new Array(subsetSize);
   if (findSum(numberArray, subset, 0, 0))
   {
      trace("Found our sum!");
      // If we found our sum, no need to look for more sets:
      break;
   }
}

// numberArray : Our input set
// subset      : The set we're currently filling
// setIndex    : The position we're at in numberArray
// subsetIndex : The position we're at in the set we're filling
// RETURNS     : True if the required sum was found, otherwise false.
function findSum(numberArray:Array, subset:Array, setIndex:int, 
                 subsetIndex:int):Boolean
{
   // Try every value from the input set starting from our current position, 
   // and insert the value at the current subset index:
   for (var index:int = setIndex ; index < numberArray.length; index++)
   {
      subset[subsetIndex] = numberArray[index];

      // Have we filled the subset?
      if (subsetIndex == subset.length - 1)
      {
         var sum:int = 0;
         for (var i:int = 0; i < subset.length; i++)
         {
            sum += subset[i];
         }

         // Return true if we found our sum, false if not:
         return sum == requiredSum;
      }
      else
      {
         if (findSum(numberArray, subset, index + 1, subsetIndex + 1))
         {
            // If the "inner" findSum found a sum, we're done, so return
            // - otherwise stay in the loop and keep looking:
            return true;
         }
      }
   }
   // We found no subset with our required sum this time around:
   return false;
}

ETA:这是如何工作的...如前所述,这是一个简单的解决方案 - 换句话说,我们只是检查 numberArray 的每一个排列,对每个排列求和,然后检查它是否是我们想要的总和。

最复杂的部分是进行所有排列。这段代码的方式是通过递归 - 即,findSum() 函数填充一个槽,然后 调用自己 来填充下一个槽,直到所有槽都被填满并且它可以检查总和。我们在这里以numberArray [1, 5, 4, 2] 为例:

  1. 在一个循环中遍历所有子集大小 - 即,首先创建所有 [a],然后创建所有 [a,b]、[a,b,c]、[a,b,c,d]...等
  2. 对于每个子集大小:
    1. 填充槽1的子集...
    2. ... numberArray 的每个值 - [1, ?, ?], [5, ?, ?], [4, ?, ?]...
    3. 如果子集中的所有槽都已填满,请检查总和是否匹配并跳过第 4 步。
    4. (递归)调用findSum 到:
      1. 填充子集的槽2...
      2. ... numberArray 的每个剩余值 - [1, 5, ?], [1, 4, ?], [1, 2, ?]
      3. 如果子集中的所有槽都已填满,请检查总和是否匹配并跳过第 4 步。
      4. (递归)调用findSum 到:
        1. 填充子集的槽3
        2. ... numberArray 的每个剩余值 - [1, 5, 4], [1, 5, 2]
        3. 如果子集中的所有槽都已填满,请检查总和是否匹配并跳过第 4 步。
        4. (递归)调用findSum(这会“永远”继续,或者直到所有插槽都被填满并且我们“跳过第4步”)
        5. 转到 2.4.4.1。尝试插槽 3 的下一个值。
      5. 转到 2.4.1 以尝试插槽 2 的下一个值。
    5. 转到 2.1 以尝试插槽 1 的下一个值。

这样,我们遍历大小为 1、2、3、4...的每个排列

这里可以进行更多优化,因为代码从不检查输入集中实际上是否有足够的值来填充剩余的插槽 - 即它会执行一些不需要的循环和对 findSum() 的调用。然而,这只是效率问题 - 结果仍然是正确的。

【讨论】:

  • O_____O 我有点困惑......但如果没有任何东西可以加起来具体数字,这会起作用吗?因为我并不真正关心输出,所以需要的主要是告诉 flash 这些数字无法相加,因此会生成新的数字。
  • 是的,如果什么都不能加起来,它将返回一个空数组。但是,如果您不需要输出,只需要一个真/假,则可以对其进行一些优化 - 因为它可能会在找到第一个结果后停止查找。
  • erm.... 我不明白代码:findSum(numberArray, subset, 0, 0) 和函数 findSum(numberArray:Array, subset:Array, setIndex:int, subsetIndex:int):布尔值和 if (findSum(numberArray, subset, index + 1, subsetIndex + 1)) 对不起,我只是脚本和编码的初学者。
  • 哦……我明白了……你用了几个我不明白的词,但谷歌(dictionary.com)有点解决了……谢谢:D
  • 请随意询问任何给您带来麻烦的具体词语。理解代码最简单的方法可能是在这里和那里添加几个trace() 调用,以查看运行时的执行顺序和状态。递归函数可能让你头疼 - 但它们更难解释清楚。 :-)
【解决方案2】:

我会做如下的事情:

  • 洗牌数组
  • 从数组中随机取数
  • 总结一下
  • 如果总和不是您想要的总和,请重复

【讨论】:

  • 但是,不会有一个“结论”,即无论我们如何添加,数字都无法添加到那个数量。示例:如果 numberArray 是 [4,7,6,5,6] 但具体数字是 8,那么它将不断重复 shuffle 数组,并且不会认为它需要更改其中一个数字。对?或者当数字是 [1,2,1,1,2] 并且具体的总和是 8 时,它也不起作用,对吧?
【解决方案3】:

hm,不确定当得出“结论”或“无结论”时你想在最后做什么,但你可以从你的一组数字中生成一个Power set,然后为每个子集加起来所有的数字看看你是否得到了你想要的金额。

(这将是一种“蛮力”方法,如果您有很多数字,可能会很慢。)

可能对如何创建幂集有用: Calculating all of the subsets of a set of numbers

【讨论】:

  • 如果得出结论,那么什么也不会发生。比赛将继续进行。但是如果没有得出结论,那么它会给出新的数字以便得出结论,因此没有人可以卡在游戏中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-01
  • 2013-03-08
  • 1970-01-01
  • 2019-11-13
  • 2019-07-31
相关资源
最近更新 更多