From 3c7e32370cb26098d6108292b7dbc482281e4fef Mon Sep 17 00:00:00 2001 From: Dmitry Naimark Date: Thu, 25 Apr 2019 12:37:21 +0300 Subject: [PATCH] Add test for Knapsack 0/1 problem and fix "tracing" part of this algorithm. --- .../sets/knapsack-problem/Knapsack.js | 36 +++++++------------ .../__test__/Knapsack.test.js | 20 +++++++++++ 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/algorithms/sets/knapsack-problem/Knapsack.js b/src/algorithms/sets/knapsack-problem/Knapsack.js index d93e51a3..1500f4c2 100644 --- a/src/algorithms/sets/knapsack-problem/Knapsack.js +++ b/src/algorithms/sets/knapsack-problem/Knapsack.js @@ -120,30 +120,20 @@ export default class Knapsack { let itemIndex = this.possibleItems.length - 1; let weightIndex = this.weightLimit; - while (itemIndex > 0) { - const currentItem = this.possibleItems[itemIndex]; - const prevItem = this.possibleItems[itemIndex - 1]; - + while (itemIndex >= 0) { // Check if matrix value came from top (from previous item). - // In this case this would mean that we need to include previous item - // to the list of selected items. - if ( - knapsackMatrix[itemIndex][weightIndex] - && knapsackMatrix[itemIndex][weightIndex] === knapsackMatrix[itemIndex - 1][weightIndex] - ) { - // Check if there are several items with the same weight but with the different values. - // We need to add highest item in the matrix that is possible to get the highest value. - const prevSumValue = knapsackMatrix[itemIndex - 1][weightIndex]; - const prevPrevSumValue = knapsackMatrix[itemIndex - 2][weightIndex]; - if ( - !prevSumValue - || (prevSumValue && prevPrevSumValue !== prevSumValue) - ) { - this.selectedItems.push(prevItem); - } - } else if (knapsackMatrix[itemIndex - 1][weightIndex - currentItem.weight]) { - this.selectedItems.push(prevItem); - weightIndex -= currentItem.weight; + // In this case this would mean that we need to include the topmost item with the + // same max possible value and the same weight to the list of selected items. + while (knapsackMatrix[itemIndex - 1] !== undefined + && knapsackMatrix[itemIndex][weightIndex] === knapsackMatrix[itemIndex - 1][weightIndex]) { + itemIndex -= 1; + } + + // If max possible value in the cell is not zero(and not undefined). + if (knapsackMatrix[itemIndex][weightIndex]) { + // Add item to knapsack and decrease remaining weight capacity by item's weight. + this.selectedItems.push(this.possibleItems[itemIndex]); + weightIndex -= this.possibleItems[itemIndex].weight; } itemIndex -= 1; diff --git a/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js b/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js index d322445a..9b1c7dbf 100644 --- a/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js +++ b/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js @@ -44,6 +44,26 @@ describe('Knapsack', () => { expect(knapsack.selectedItems[1].toString()).toBe('v4 w3 x 1'); }); + it('should solve 0/1 knapsack problem 2', () => { + const possibleKnapsackItems = [ + new KnapsackItem({ value: 5, weight: 3 }), + new KnapsackItem({ value: 3, weight: 2 }), + new KnapsackItem({ value: 4, weight: 1 }), + ]; + + const maxKnapsackWeight = 5; + + const knapsack = new Knapsack(possibleKnapsackItems, maxKnapsackWeight); + + knapsack.solveZeroOneKnapsackProblem(); + + expect(knapsack.totalValue).toBe(9); + expect(knapsack.totalWeight).toBe(4); + expect(knapsack.selectedItems.length).toBe(2); + expect(knapsack.selectedItems[0].toString()).toBe('v5 w3 x 1'); + expect(knapsack.selectedItems[1].toString()).toBe('v4 w1 x 1'); + }); + it('should solve 0/1 knapsack problem with impossible items set', () => { const possibleKnapsackItems = [ new KnapsackItem({ value: 5, weight: 40 }),