0

Task Get all combinations for array (array is very simple 1,2,3,4,5 - just indexes of lines in table, always in order, so we can use just count-number)

I need result looks like : List of array or List Of List (0:0, 1:1, 2:0,1, 3:3, 4: 0,1,2 ...)

Data state I have rows in table, each row contains 6 columns with decimal number. My target to get sum of numbers from that columns for each selected row which closest to my specific number(test say 600). So I have to select only that rows what have the closet number in sum.

Code

  1. cyclical

    Private Function CreateSubsets(Of T)(ByVal originalArray() As T) As List(Of T())
    
    Dim subsets As New List(Of T())
    
    For i As Integer = 0 To originalArray.Length - 1
    
        Dim subsetCount As Integer = subsets.Count
        subsets.Add(New T() {originalArray(i)})
    
        For j As Integer = 0 To subsetCount - 1
            Dim newSubset(subsets(j).Length) As T
            subsets(j).CopyTo(newSubset, 0)
            newSubset(newSubset.Length - 1) = originalArray(i)
            subsets.Add(newSubset)
        Next
    
    Next
    
    Return subsets
    End Function
    
  2. recursive

    Private Function GetAllCombos(Of T)(ByVal list As List(Of T)) As List(Of List(Of T))
    
    Dim result As List(Of List(Of T)) = New List(Of List(Of T))
    'head
    result.Add(New List(Of T))
    result.Last().Add(list(0))
    
    If (list.Count = 1) Then
        Return result
    End If
    
    'tail
    Dim tailCombos = GetAllCombos(list.Skip(1).ToList())
    tailCombos.ForEach(Sub(combo)
                           result.Add(New List(Of T)(combo))
                           combo.Add(list(0))
                           result.Add(New List(Of T)(combo))
                       End Sub)
    Return result
    
    End Function
    

Problems

Get the axception "System.OutOfMemoryException" in both cases. How can I avoid this problem, any solutions? Maybe someone had the same task. I cannot disable limit for large objects - system .NET Framework 4.0 32bit

  • 3
    The complexity of the function you're trying to do is a factorial of the amount of elements in your array, so for 5 elements it's 5!=120 combinations, for 10 elements it's already 10!=3628800 combinations. How many elements are actually in your array? – Longoon12000 Nov 11 '19 at 16:19
  • For now it works for <=25 items, but I need more, it can be 100 items – Denis Lopatin Nov 11 '19 at 16:21
  • 4
    Assuming a list only takes 10 bytes of RAM (hint: it's more) then you would need more megabytes of RAM than there are atoms in the universe. It's not possible. (100!=9.332622e+157, that's a 9 with 157 zeros of possible permutations) – Longoon12000 Nov 11 '19 at 16:22
  • I really don't think that problem in RAM, I have a lot. Problem in limit for objects. – Denis Lopatin Nov 11 '19 at 16:23
  • However you can happily enumerate the combinations all day [eternity] long if you use a lazy iterator... Take a step back, WHY do you think you want ALL the combinations? – tolanj Nov 11 '19 at 16:23
  • You right, for now I will go to split items into groups and work with groups. But it is not the best solution. I need combinations because I colculate for each one possible result(delta value), after that I select only linel with the lowest delta - so I need indexes of lines for selecting it. – Denis Lopatin Nov 11 '19 at 16:28
  • Based on your example (result looks like) I have a hard time figuring out if you actually want all possible combinations (eg. 1,2,3 -> {(1,2,3),(1,3,2),(2,1,3),(2,3,1),(3,1,2),(3,2,1)}) or something else. If it's all possible combinations you're looking for you absolutely have to use a different approach (eg. loop through all possibilities but only store it if the delta is less than the previously stored delta). – Longoon12000 Nov 11 '19 at 16:30
  • 1
    @Longoon12000 I _think_ he is genuinely interested in combinations not permutations, in his example thats actually ~ subsets. That means it's !ONLY! (2^n) - 1 items he has to worry about, your points still very much stand though – tolanj Nov 11 '19 at 16:31
  • @tolanj It is possible, do you know algorithm for it? I wondering because for calculation combinations the method uses prev list combinations as base. How can I do it in different way? Each number in combinations mean index of row - from the row I can calculate a delta. – Denis Lopatin Nov 11 '19 at 16:34
  • 1
    The problem remains, you _say_ you want all the combinations of elements, ie all the subsets of the array. However if there are 100 items in the array there are 2^100 subsets. This is more than a 64 bit address space, if you calculated each of these at one millisec per calc it would take ~10^20 years etc etc – tolanj Nov 11 '19 at 16:49
  • This answer https://stackoverflow.com/a/10374521/2701753 shows a nice enough method for actually enumerating the subsets, combine that with a Yield statement to make a lazy iterator and, well, you wont run out of memory, _but you will run out of time_ If you say why you think you need to do this we might actually be able to help – tolanj Nov 11 '19 at 16:58
  • @tolanj Thank you for link with answer - I will try to re-implement it for my case. I added details for my task, take a look please on top of qtn. And sorry for my bad English) – Denis Lopatin Nov 11 '19 at 17:08
  • With your addition of details I get what you are trying to do. Brute force is not the answer. Do you only care about one column at a time OR do you need to optimise across several cpulums at once? – tolanj Nov 11 '19 at 17:22
  • @tolanj several columns, I calculate a delta velue for it from all 6 columns – Denis Lopatin Nov 11 '19 at 17:32
  • Okay so, implementation details aside this is a decimal version of the 0-1 knapsack problem. https://en.m.wikipedia.org/wiki/Knapsack_problem, perhaps with an added complication that the numbers can be negative? I would reask the question in those terms – tolanj Nov 11 '19 at 17:55
  • @tolanj I saw solution for knapsack. not sure that it is the same like my task. I need to get list of row indexes, delta only for comparing, (I dont need it in result) There is no negative values (always >= 0) – Denis Lopatin Nov 11 '19 at 18:41

0 Answers0