AS3:在数组中添加不同的数字以获得特定结果。

时间:2013-08-09 15:08:43

标签: actionscript-3 flash

我有一个号码阿雷。 它包含在特定范围内随机化的整数。 我想得到一个特定的金额,但不是为numberArray里面的所有东西, 更多的是尝试在numberArray中总结不同数量的数字(总共只有5个),看看它是否会得到所需的特定总数。如果没有,它会随机化另一个数字来接管numberArray中的一个数字。

最简单的方法是什么?

做很多事情

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

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

3 个答案:

答案 0 :(得分:0)

我会做以下事情:

  • shuffle array
  • 从数组中随机抽取数量
  • 总结一下
  • 如果总和不是您想要的总金额,请重复

答案 1 :(得分:0)

嗯,当达到“结论”或“没有结论”时,不确定你最后想做什么,但是你可以从你的数字集生成一个Power set然后为每个子集加起来它中的数字,看你是否得到了你想要的总和。

(这将是一种'暴力'方法,如果你有很多数字,可能会很慢。)

如何创建Power Set可能很有用: Calculating all of the subsets of a set of numbers

答案 2 :(得分:0)

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

这是一个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

如果我们只需要知道如果存在一个和,就不需要结果集 - 我们只返回true / false,并在找到一个总和时完全打破递归算法:

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. 填充子集
        2. 的广告位3
        3. ...使用numberArray的每个剩余值 - [1,5, 4 ],[1,5,2]
        4. 如果子集中的所有插槽都已填满,请检查总和是否匹配并跳过步骤4.
        5. (递归地)调用findSum(这将继续“永久”,或直到所有广告位都填满,我们“跳过第4步”)
        6. 转到2.4.4.1。尝试插入3的下一个值。
      5. 转到2.4.1尝试插槽2的下一个值。
    5. 转到2.1尝试插槽1的下一个值。
  3. 这样,我们经历了大小1,2,3,4 ......

    的每个排列

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