Skip to content

Instantly share code, notes, and snippets.

@soswow
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save soswow/9450568 to your computer and use it in GitHub Desktop.
Save soswow/9450568 to your computer and use it in GitHub Desktop.
You have 3 slots. You MUST fill each slot with one number. Each slot has list of possible numbers. Find best combination(s) that have total sum equal or closest to curtain limit.
_ = require 'underscore'
class BlackMagic
dp: null
dpMax: null
maxTotalWeight: 0
minTotalWeight: 0
minWeight: Number.MAX_VALUE
constructor: (@items) ->
@bucketsNum = @items.length
_setProperties: ->
for bi in [0...@bucketsNum]
weights = _.map @items[bi], (obj) -> obj.weight
min = _.min weights
@maxTotalWeight += _.max weights
@minTotalWeight += min
@minWeight = Math.min @minWeight, min
console.log """
maxTotalWeight: #{@maxTotalWeight}
minTotalWeight: #{@minTotalWeight}
minWeight: #{@minWeight}
"""
_calcDPTable: ->
@_setProperties()
@dp = []
@dpMax = []
for bi in [0...@bucketsNum]
@dp.push []
@dpMax.push []
for j in [@minWeight..@maxTotalWeight]
# console.log bi, j
rowMax = [-Number.MAX_VALUE, []] #Max value, and all ITEM ids have it
for id, {value, weight} of @items[bi]
@dp[bi][j] = [] unless @dp[bi][j]
nextValue =
if bi is 0
if weight <= j
value
else
0
else
if (j - weight) < @minWeight or @dpMax[bi - 1][j - weight][0] is 0
0
else
value + @dpMax[bi - 1][j - weight][0]
@dp[bi][j].push nextValue
if nextValue > rowMax[0]
rowMax[0] = nextValue
if nextValue > 0
rowMax[1] = [id]
else
rowMax[1] = []
else if nextValue is rowMax[0] and nextValue > 0
rowMax[1].push id
@dpMax[bi][j] = [Math.max(rowMax[0], 0), rowMax[1]]
print: ->
for j in [@minWeight..@maxTotalWeight]
row =
for bi in [0...items.length]
' [' + @dpMax[bi][j][1].join(',') + ']' + @dpMax[bi][j][0]
console.log j + ':\t' + row.join '\t\t'
for j in [@minWeight..@maxTotalWeight]
row =
for bi in [0...items.length]
# console.log(@dp[bi][j-@minWeight])
@dp[bi][j]?.join('\t') + '[' + @dpMax[bi][j][0] + ']'
console.log j + ':\t' + row.join '\t'
findSolutions: (limit, howManyMax=10) ->
@_calcDPTable() unless @dp
if limit < @minTotalWeight
throw "No solution"
# @print()
solutions = for i in [1..howManyMax]
w = if limit > @maxTotalWeight then @maxTotalWeight else limit
ids = for bi in [@dpMax.length - 1..0]
_ids = @dpMax[bi][w][1]
id = _ids[Math.floor(Math.random() * _ids.length)] + ""
w -= @items[bi][id].weight
id
ids.reverse()
_.uniq solutions, (item) -> item.join('')
items = [
{
0: value: 1, weight: 1
1: value: 2, weight: 2
}
{
2: value: 2, weight: 2
3: value: 4, weight: 4
}
{
4: value: 3, weight: 3
5: value: 1, weight: 1
6: value: 5, weight: 5
}
]
items =
for i in [0...3]
obj = {}
for j in [i * 100...i * 100 + 100]
value = 100 + Math.floor(Math.random() * 99) + 1
obj[j] =
value: value, weight: value
obj
bw = new BlackMagic(items)
console.log bw.findSolutions(400)
#console.log bw.findSolution(11)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment