master
  1<<-DOC
  2You have a collection of coins, and you know the values of the coins and the quantity of each type of coin in it.
  3You want to know how many distinct sums you can make from non-empty groupings of these coins.
  4
  5Example
  6
  7For coins = [10, 50, 100] and quantity = [1, 2, 1], the output should be
  8possibleSums(coins, quantity) = 9.
  9
 10Here are all the possible sums:
 11
 1250 = 50;
 1310 + 50 = 60;
 1450 + 100 = 150;
 1510 + 50 + 100 = 160;
 1650 + 50 = 100;
 1710 + 50 + 50 = 110;
 1850 + 50 + 100 = 200;
 1910 + 50 + 50 + 100 = 210;
 2010 = 10;
 21100 = 100;
 2210 + 100 = 110.
 23As you can see, there are 9 distinct sums that can be created from non-empty groupings of your coins.
 24
 25Input/Output
 26
 27[time limit] 4000ms (rb)
 28[input] array.integer coins
 29
 30An array containing the values of the coins in your collection.
 31
 32Guaranteed constraints:
 331  coins.length  20,
 341  coins[i]  104.
 35
 36[input] array.integer quantity
 37
 38An array containing the quantity of each type of coin in your collection. quantity[i] indicates the number of coins that have a value of coins[i].
 39
 40Guaranteed constraints:
 41quantity.length = coins.length,
 421  quantity[i]  105.
 43
 44It is guaranteed that (quantity[0] + 1) * (quantity[1] + 1) * ... * (quantity[quantity.length - 1] + 1) <= 106.
 45
 46[output] integer
 47
 48The number of different possible sums that can be created from non-empty groupings of your coins.
 49DOC
 50
 51describe "#possible_sums" do
 52  def possible_sums(coins, quantity)
 53    maximum = coins.zip(quantity).map { |(x, y)| x * y }.sum
 54
 55    dp = [false] * (maximum + 1)
 56    dp[0] = true
 57
 58    coins.zip(quantity).each do |(coin, q)|
 59      (0...coin).each do |b|
 60        num = -1
 61        (b..maximum + 1).step(coin).each do |i|
 62          if dp[i]
 63            num = 0
 64          elsif num >= 0
 65            num += 1
 66          end
 67          dp[i] = (0 <= num && num <= q)
 68        end
 69      end
 70    end
 71    dp.map { |x| x ? 1 : 0 }.sum - 1
 72  end
 73
 74  def possible_sums(coins, quantity)
 75    results = { 0 => true }
 76    coins.zip(quantity).each do |coin, number_of_coins|
 77      results.keys.each do |key|
 78        1.upto(number_of_coins) do |n|
 79          results[key + (coin * n)] = true
 80        end
 81      end
 82    end
 83    results.size - 1
 84  end
 85
 86  [
 87    { coins: [10, 50, 100], quantity: [1, 2, 1], x: 9 },
 88    { coins: [10, 50, 100, 500], quantity: [5, 3, 2, 2], x: 122 },
 89    { coins: [1], quantity: [5], x: 5 },
 90    { coins: [1, 1], quantity: [2, 3], x: 5 },
 91    { coins: [1, 2], quantity: [50000, 2], x: 50004 },
 92    { coins: [1, 2, 3], quantity: [2, 3, 10000], x: 30008 },
 93    { coins: [3, 1, 1], quantity: [111, 84, 104], x: 521 },
 94    { coins: [1, 1, 1, 1, 1], quantity: [9, 19, 18, 12, 19], x: 77 },
 95  ].each do |x|
 96    it do
 97      expect(possible_sums(x[:coins], x[:quantity])).to eql(x[:x])
 98    end
 99  end
100end