Search code examples
arraysrubycombinations

Show only the combinations of two permutated arrays that have a sum less than or equal to target number


I have two arrays: teams = [1,2,3] and drivers = [4,5,6]. Using permutations I have managed to show all combinations of the two arrays, but have managed to define what number of values I'd like to use from each array. So from 'Teams' I have used 1 value and 'Drivers' I have used two. I would like to only show the combinations where the sum is less than or equal to 10 and remove any duplicates.

    teams = [1,2,3]
    drivers = [4,5,6]
    team = teams.permutation(1).to_a
    driver = drivers.permutation(2).to_a
    array = team.product(driver)
    target = 11

This is successfully outputting all combinations of the two arrays using 1 number from teams and 2 from drivers as follows:

[[1], [4, 5]], [[1], [4, 6]], [[1], [5, 4]], [[1], [5, 6]], [[1], [6, 4]], [[1], [6, 5]], [[2], [4, 5]], etc...

To only show values less than or equal to 10 my expected outcome would be: [[1], [4, 5]], [[1], [5, 4]],

and then no duplicates would leave me with just: [[1], [4, 5]]

I have tried adding the below line of code but am getting an undefined method `<=' error:

@array = array[0].product(*array[1..-1]).select { |a| a.reduce(:+) <= target }

I have also tried this with no luck:

result = array.combination(1).select{|combi| combi.sum <= target}

@array = result

I'm guessing it's something to do with the permutation?


Solution

  • Here's an approach

    teams = [1, 2, 3]
    drivers = [2, 6, 5, 4]
    team = teams.permutation(1).to_a
    driver = drivers.permutation(2).to_a
    array = team.product(driver)
    
    target = 10
    
    res = array.select {|i| i.map(&:sum).sum <= target}.compact
    ==> [[[1], [2, 6]], [[1], [2, 5]], [[1], [2, 4]], [[1], [6, 2]],
         [[1], [5, 2]], [[1], [5, 4]], [[1], [4, 2]], [[1], [4, 5]],
         [[2], [2, 6]], [[2], [2, 5]], [[2], [2, 4]], [[2], [6, 2]],
         [[2], [5, 2]], [[2], [4, 2]], [[3], [2, 5]], [[3], [2, 4]],
         [[3], [5, 2]], [[3], [4, 2]]]
    

    Getting the unique items (modified to also work for values of teams > drivers)

    t1 = res.map {|i| i[0]}
    d2 = res.map {|i| i[1].flatten.sort}
    
    t1.zip(d2).uniq
    ==> [[[1], [2, 6]], [[1], [2, 5]], [[1], [2, 4]], [[1], [4, 5]],
         [[2], [2, 6]], [[2], [2, 5]], [[2], [2, 4]], [[3], [2, 5]],
         [[3], [2, 4]]]