cakeThief.js
· 2.3 KiB · JavaScript
Raw
class Bag {
constructor (capacity) {
this.capacity = capacity;
this.cakes = [];
this.weight = 0;
this.value = 0;
}
addCake (cake) {
this.cakes.push(cake);
this.value += cake.value;
this.weight += cake.weight;
}
getCapacityRemaining () {
return this.capacity - this.getWeight();
}
getValue () {
return this.value;
}
getWeight () {
return this.weight;
}
}
let cakeTypes = [
{weight: 7, value: 160},
{weight: 3, value: 90},
{weight: 1, value: 15}
];
// maxDuffelBagValue(cakeTypes, 20);
function maxDuffelBagValue (cakeTypes, capacity) {
let bag = new Bag(capacity),
// clean our cake types to cover out of bounds values
validCakeTypes = cleanCakeTypes(cakeTypes),
// figure out what the smallest cake is
smallestCake = getSmallestCakeType(validCakeTypes);
// until we don't have enough weight left, find the most valuable cake
for (var capacityLeft = capacity; capacityLeft >= smallestCake.weight; capacityLeft = bag.getCapacityRemaining()) {
// reduce our cakeTypes to the index of the highest value density that can fit
let bestCake = validCakeTypes.reduce((prev, next) => {
// make sure this next cake will fit
if (next.weight <= capacityLeft) {
// decide which is higher value-weight ratio
return prev.value / prev.weight > next.value / next.weight ? prev : next;
}
// this next cake doesn't fit, keep the previous
else return prev;
}, {value: 0, weight: 1});
// add the cake to our bag (adding to its weight and value)
bag.addCake(bestCake);
}
return bag.getValue();
}
/**
* reduce our cakeType collection down to one with the lowest weight
* @param {array} cakeTypes - collection of cakeType object {weight, value}
* @return {object} cakeType
*/
function getSmallestCakeType (cakeTypes) {
return cakeTypes.reduce((prev, next) => prev.weight < next.weight ? prev : next);
}
/**
* cleanCakeTypes - filters out invalid cakeTypes
* @param {array} cakeTypes - collection of cakeType object {weight, value}
* @return {array} filtered collection of cakeType objects
*/
function cleanCakeTypes (cakeTypes) {
// filter out any cake types with weight or value of 0, that's unreal!
return cakeTypes.filter((type) => type.weight > 0 && type.value > 0);
}
| 1 | class Bag { |
| 2 | constructor (capacity) { |
| 3 | this.capacity = capacity; |
| 4 | this.cakes = []; |
| 5 | this.weight = 0; |
| 6 | this.value = 0; |
| 7 | } |
| 8 | |
| 9 | addCake (cake) { |
| 10 | this.cakes.push(cake); |
| 11 | this.value += cake.value; |
| 12 | this.weight += cake.weight; |
| 13 | } |
| 14 | |
| 15 | getCapacityRemaining () { |
| 16 | return this.capacity - this.getWeight(); |
| 17 | } |
| 18 | |
| 19 | getValue () { |
| 20 | return this.value; |
| 21 | } |
| 22 | |
| 23 | getWeight () { |
| 24 | return this.weight; |
| 25 | } |
| 26 | } |
| 27 | |
| 28 | let cakeTypes = [ |
| 29 | {weight: 7, value: 160}, |
| 30 | {weight: 3, value: 90}, |
| 31 | {weight: 1, value: 15} |
| 32 | ]; |
| 33 | |
| 34 | // maxDuffelBagValue(cakeTypes, 20); |
| 35 | |
| 36 | function maxDuffelBagValue (cakeTypes, capacity) { |
| 37 | let bag = new Bag(capacity), |
| 38 | // clean our cake types to cover out of bounds values |
| 39 | validCakeTypes = cleanCakeTypes(cakeTypes), |
| 40 | // figure out what the smallest cake is |
| 41 | smallestCake = getSmallestCakeType(validCakeTypes); |
| 42 | |
| 43 | // until we don't have enough weight left, find the most valuable cake |
| 44 | for (var capacityLeft = capacity; capacityLeft >= smallestCake.weight; capacityLeft = bag.getCapacityRemaining()) { |
| 45 | // reduce our cakeTypes to the index of the highest value density that can fit |
| 46 | let bestCake = validCakeTypes.reduce((prev, next) => { |
| 47 | // make sure this next cake will fit |
| 48 | if (next.weight <= capacityLeft) { |
| 49 | // decide which is higher value-weight ratio |
| 50 | return prev.value / prev.weight > next.value / next.weight ? prev : next; |
| 51 | } |
| 52 | // this next cake doesn't fit, keep the previous |
| 53 | else return prev; |
| 54 | }, {value: 0, weight: 1}); |
| 55 | |
| 56 | // add the cake to our bag (adding to its weight and value) |
| 57 | bag.addCake(bestCake); |
| 58 | } |
| 59 | |
| 60 | return bag.getValue(); |
| 61 | } |
| 62 | |
| 63 | /** |
| 64 | * reduce our cakeType collection down to one with the lowest weight |
| 65 | * @param {array} cakeTypes - collection of cakeType object {weight, value} |
| 66 | * @return {object} cakeType |
| 67 | */ |
| 68 | function getSmallestCakeType (cakeTypes) { |
| 69 | return cakeTypes.reduce((prev, next) => prev.weight < next.weight ? prev : next); |
| 70 | } |
| 71 | |
| 72 | /** |
| 73 | * cleanCakeTypes - filters out invalid cakeTypes |
| 74 | * @param {array} cakeTypes - collection of cakeType object {weight, value} |
| 75 | * @return {array} filtered collection of cakeType objects |
| 76 | */ |
| 77 | function cleanCakeTypes (cakeTypes) { |
| 78 | // filter out any cake types with weight or value of 0, that's unreal! |
| 79 | return cakeTypes.filter((type) => type.weight > 0 && type.value > 0); |
| 80 | } |