Finding all possible combinations of numbers to reach a given sum

前端 未结 30 3094
一个人的身影
一个人的身影 2020-11-21 06:39

How would you go about testing all possible combinations of additions from a given set N of numbers so they add up to a given final number?

A brief exam

相关标签:
30条回答
  • 2020-11-21 06:56

    C# version of @msalvadores code answer

    void Main()
    {
        int[] numbers = {3,9,8,4,5,7,10};
        int target = 15;
        sum_up(new List<int>(numbers.ToList()),target);
    }
    
    static void sum_up_recursive(List<int> numbers, int target, List<int> part)
    {
       int s = 0;
       foreach (int x in part)
       {
           s += x;
       }
       if (s == target)
       {
            Console.WriteLine("sum(" + string.Join(",", part.Select(n => n.ToString()).ToArray()) + ")=" + target);
       }
       if (s >= target)
       {
            return;
       }
       for (int i = 0;i < numbers.Count;i++)
       {
             var remaining = new List<int>();
             int n = numbers[i];
             for (int j = i + 1; j < numbers.Count;j++)
             {
                 remaining.Add(numbers[j]);
             }
             var part_rec = new List<int>(part);
             part_rec.Add(n);
             sum_up_recursive(remaining,target,part_rec);
       }
    }
    static void sum_up(List<int> numbers, int target)
    {
        sum_up_recursive(numbers,target,new List<int>());
    }
    
    0 讨论(0)
  • 2020-11-21 06:56

    Excel VBA version below. I needed to implement this in VBA (not my preference, don't judge me!), and used the answers on this page for the approach. I'm uploading in case others also need a VBA version.

    Option Explicit
    
    Public Sub SumTarget()
        Dim numbers(0 To 6)  As Long
        Dim target As Long
    
        target = 15
        numbers(0) = 3: numbers(1) = 9: numbers(2) = 8: numbers(3) = 4: numbers(4) = 5
        numbers(5) = 7: numbers(6) = 10
    
        Call SumUpTarget(numbers, target)
    End Sub
    
    Public Sub SumUpTarget(numbers() As Long, target As Long)
        Dim part() As Long
        Call SumUpRecursive(numbers, target, part)
    End Sub
    
    Private Sub SumUpRecursive(numbers() As Long, target As Long, part() As Long)
    
        Dim s As Long, i As Long, j As Long, num As Long
        Dim remaining() As Long, partRec() As Long
        s = SumArray(part)
    
        If s = target Then Debug.Print "SUM ( " & ArrayToString(part) & " ) = " & target
        If s >= target Then Exit Sub
    
        If (Not Not numbers) <> 0 Then
            For i = 0 To UBound(numbers)
                Erase remaining()
                num = numbers(i)
                For j = i + 1 To UBound(numbers)
                    AddToArray remaining, numbers(j)
                Next j
                Erase partRec()
                CopyArray partRec, part
                AddToArray partRec, num
                SumUpRecursive remaining, target, partRec
            Next i
        End If
    
    End Sub
    
    Private Function ArrayToString(x() As Long) As String
        Dim n As Long, result As String
        result = "{" & x(n)
        For n = LBound(x) + 1 To UBound(x)
            result = result & "," & x(n)
        Next n
        result = result & "}"
        ArrayToString = result
    End Function
    
    Private Function SumArray(x() As Long) As Long
        Dim n As Long
        SumArray = 0
        If (Not Not x) <> 0 Then
            For n = LBound(x) To UBound(x)
                SumArray = SumArray + x(n)
            Next n
        End If
    End Function
    
    Private Sub AddToArray(arr() As Long, x As Long)
        If (Not Not arr) <> 0 Then
            ReDim Preserve arr(0 To UBound(arr) + 1)
        Else
            ReDim Preserve arr(0 To 0)
        End If
        arr(UBound(arr)) = x
    End Sub
    
    Private Sub CopyArray(destination() As Long, source() As Long)
        Dim n As Long
        If (Not Not source) <> 0 Then
            For n = 0 To UBound(source)
                    AddToArray destination, source(n)
            Next n
        End If
    End Sub
    

    Output (written to the Immediate window) should be:

    SUM ( {3,8,4} ) = 15
    SUM ( {3,5,7} ) = 15
    SUM ( {8,7} ) = 15
    SUM ( {5,10} ) = 15 
    
    0 讨论(0)
  • 2020-11-21 06:56

    To find the combinations using excel - (its fairly easy). (You computer must not be too slow)

    1. Go to this site
    2. Go to the "Sum to Target" page
    3. Download the "Sum to Target" excel file.

      Follow the directions on the website page.

    hope this helps.

    0 讨论(0)
  • 2020-11-21 06:56

    I ported the C# sample to Objective-c and didn't see it in the responses:

    //Usage
    NSMutableArray* numberList = [[NSMutableArray alloc] init];
    NSMutableArray* partial = [[NSMutableArray alloc] init];
    int target = 16;
    for( int i = 1; i<target; i++ )
    { [numberList addObject:@(i)]; }
    [self findSums:numberList target:target part:partial];
    
    
    //*******************************************************************
    // Finds combinations of numbers that add up to target recursively
    //*******************************************************************
    -(void)findSums:(NSMutableArray*)numbers target:(int)target part:(NSMutableArray*)partial
    {
        int s = 0;
        for (NSNumber* x in partial)
        { s += [x intValue]; }
    
        if (s == target)
        { NSLog(@"Sum[%@]", partial); }
    
        if (s >= target)
        { return; }
    
        for (int i = 0;i < [numbers count];i++ )
        {
            int n = [numbers[i] intValue];
            NSMutableArray* remaining = [[NSMutableArray alloc] init];
            for (int j = i + 1; j < [numbers count];j++)
            { [remaining addObject:@([numbers[j] intValue])]; }
    
            NSMutableArray* partRec = [[NSMutableArray alloc] initWithArray:partial];
            [partRec addObject:@(n)];
            [self findSums:remaining target:target part:partRec];
        }
    }
    
    0 讨论(0)
  • 2020-11-21 06:57

    In Haskell:

    filter ((==) 12345 . sum) $ subsequences [1,5,22,15,0,..]
    

    And J:

    (]#~12345=+/@>)(]<@#~[:#:@i.2^#)1 5 22 15 0 ...
    

    As you may notice, both take the same approach and divide the problem into two parts: generate each member of the power set, and check each member's sum to the target.

    There are other solutions but this is the most straightforward.

    Do you need help with either one, or finding a different approach?

    0 讨论(0)
  • 2020-11-21 06:58
    Thank you.. ephemient
    

    i have converted above logic from python to php..

    <?php
    $data = array(array(2,3,5,10,15),array(4,6,23,15,12),array(23,34,12,1,5));
    $maxsum = 25;
    
    print_r(bestsum($data,$maxsum));  //function call
    
    function bestsum($data,$maxsum)
    {
    $res = array_fill(0, $maxsum + 1, '0');
    $res[0] = array();              //base case
    foreach($data as $group)
    {
     $new_res = $res;               //copy res
    
      foreach($group as $ele)
      {
        for($i=0;$i<($maxsum-$ele+1);$i++)
        {   
            if($res[$i] != 0)
            {
                $ele_index = $i+$ele;
                $new_res[$ele_index] = $res[$i];
                $new_res[$ele_index][] = $ele;
            }
        }
      }
    
      $res = $new_res;
    }
    
     for($i=$maxsum;$i>0;$i--)
      {
        if($res[$i]!=0)
        {
            return $res[$i];
            break;
        }
      }
    return array();
    }
    ?>
    
    0 讨论(0)
提交回复
热议问题