Last week I had some problems with a simple program I am doing and somebody here helped me. Now I have run into another problem.
I currently have this code:
var findItem = function(desiredItem) {
var items = [
{ item: "rusty nail", probability: 0.25 },
{ item: "stone", probability: 0.23 },
{ item: "banana", probability: 0.20 },
{ item: "leaf", probability: 0.17 },
{ item: "mushroom", probability: 0.10 },
{ item: "diamond", probability: 0.05 }
];
var possible = items.some( ({item, probability}) =>
item === desiredItem && probability > 0 );
if (!possible) {
console.log('There is no chance you\'ll ever find a ' + desiredItem);
return;
}
var sum = items.reduce( (sum, {item, probability}) => sum+probability, 0 );
while (true) {
var value = Math.random() * sum;
var lootedItem = items.find(
({item, probability}) => (value -= probability) <= 0 ).item;
if (lootedItem === 'diamond') break;
console.log("Dang! A " + lootedItem + " was found...");
}
console.log("Lucky! A " + desiredItem + " was found!");
}
findItem('diamond');
Now I would like to expand on this by adding another value called category
to the items
array. I want the categories to have a value of either 2
, 5
or 10
. So let's say the diamond
item would belong to category: 10
, and when findItem
is executed only items that belong to the same category can be found. I have been trying for a couple of days now but can't seem to get my head around it. Maybe someone can help push me in the right direction? Thanks in advance
You could use this update to that code:
// Pass the item list and the desired category as arguments:
var findItem = function(items, category, desiredItem) {
// apply filter to items, so only those of the given category remain:
items = items.filter( item => item.category == category );
// rest of code remains the same:
var possible = items.some( ({item, probability}) =>
item === desiredItem && probability > 0 );
if (!possible) {
console.log('There is no chance you\'ll ever find a ' + desiredItem);
return;
}
var sum = items.reduce( (sum, {item, probability}) => sum+probability, 0 );
var t = 10;
while (true) {
var value = Math.random() * sum;
var lootedItem = items.find(
({item, probability}) => (value -= probability) <= 0 ).item;
if (lootedItem === desiredItem) break; // fixed this condition!
console.log("Dang! A " + lootedItem + " was found...");
t--; if (t <= 0) throw "loop";
}
console.log("Lucky! A " + desiredItem + " was found!");
}
// Define items here with their category
var items = [
{ item: "rusty nail", probability: 0.25, category: 2 },
{ item: "stone", probability: 0.23, category: 2 },
{ item: "banana", probability: 0.20, category: 2 },
{ item: "leaf", probability: 0.17, category: 5 },
{ item: "mushroom", probability: 0.10, category: 5 },
{ item: "diamond", probability: 0.05, category: 10 }
];
// Call function with extra arguments:
findItem(items, 5, 'mushroom');
console.log('second run:');
// This will obviously give a hit immediately, as there is only one possible item:
findItem(items, 10, 'diamond');
The changes are:
- Pass more arguments to your function: the items list and the desired category
- Apply a filter on the items list as first action in the function
- Fix an issue concerning the
lootedItem
test -- it had "diamond" hard-coded.
- Define the items list outside of the function and add category values to each element.
- Adapt the call of the function to pass the extra arguments.
Do you want something like this?
var items = [ { item: "rusty nail", probability: 0.25, category: 10 }
, { item: "stone", probability: 0.23, category: 5 }
, { item: "banana", probability: 0.20, category: 2 }
, { item: "leaf", probability: 0.17, category: 5 }
, { item: "mushroom", probability: 0.10, category: 2 }
, { item: "diamond", probability: 0.05, category: 10 }
];
findItem("diamond", items);
function findItem(needle, haystack) {
var item = haystack.find(thing => thing.item === needle &&
thing.probability > 0);
if (item) {
var category = item.category;
var items = haystack.filter(thing => thing.category === category);
var sum = items.reduce((sum, thing) => sum + thing.probability, 0);
var value = sum * Math.random();
var loot = items.find(thing => (value -= thing.probability) <= 0).item;
while (loot !== needle) {
value = sum * Math.random();
console.log("Dang! A " + loot + " was found...");
loot = items.find(thing => (value -= thing.probability) <= 0).item;
}
return console.log("Lucky! A " + needle + " was found!");
}
console.log("There's no chance that you'll ever find a " + needle);
}
The only major difference from your code is that I used filter
to limit the search.