1

In the game Team Fortress 2, weapon, metal, and keys are used as currencies. Metal is subdivided into three types: scrap, reclaimed, and refined (from now on "scrap", "rec" and "ref"), and it is the latter that is the reference for the others:

  • 1 weapon = 1/18 ref = 0.05 ref
  • 1 scrap = 1/9 ref = 0.11 ref
  • 1 rec = 1/3 ref = 0.33 ref
  • 1 key = 90 ref

Here are some examples to illustrate how prices work:

  • 1.49 ref = 1 ref + 1 rec + 1 scrap + 1 weapon
  • 2.11 ref = 2 ref + 1 scrap
  • 1.50 keys = 1 key + 45 ref

Using NodeJS, I have been trying to write code that takes a price and gives you all the possibilities to pay for it ordered from the lowest to the highest number of currency needed. For instance:

  • 0.22 ref = 2 scrap = 1 scrap + 2 weapons = 4 weapons

Then, it should check the possibilities against an "inventory" and choose the first one that can be carried out with what is in the inventory. Continuing with the previous example:

const inventory = {
  weapon: 5,
  scrap: 1,
  rec: 0,
  ref: 0,
  key: 0,
}

The answer would be 1 scrap + 2 weapons and not 4 weapons because the former is more "efficient" than the latter. Likewise, 2 scraps cannot be the answer since there are not enough in the inventory.

Having finished the contextualization, I want to emphasize that this is a personal project for which I need to ask for help because I can't find any answer in my knowledge (I am a novice) or in other forums. Using quite a bit of help, I have been able to get to this code, although it is far from ideal:

function findCombinations(price, inventory) {
  const combinations = [];

  function generateCombinations(remainingPrice, currentCombination, currentInventory) {
    if (remainingPrice === 0) {
      combinations.push(currentCombination);
      return;
    }

    for (const item in currentInventory) {
      const itemPrice = getItemPrice(item);

      if (itemPrice <= remainingPrice && currentInventory[item] > 0) {
        const updatedCombination = [...currentCombination, item];
        const updatedInventory = { ...currentInventory };
        updatedInventory[item]--;

        generateCombinations(
          remainingPrice - itemPrice,
          updatedCombination,
          updatedInventory
        );
      }
    }
  }

  function getItemPrice(item) {
    const prices = {
      weapon: 0.05, 
      scrap: 0.11, 
      rec: 0.33, 
      ref: 1, 
      key: 90.0 
    };

    return prices[item];
  }

  generateCombinations(price, [], inventory);

  return combinations;
}

// Example:

const price = 0.22;
const inventory = {
  weapon: 4,
  scrap: 5
};

const combinations = findCombinations(price, inventory);

console.log("Combinations to pay", price, "refs:");
combinations.forEach((combination, index) => {
  console.log(`Combination ${index + 1}:`, combination);
});

I would genuinely appreciate your help. Have a nice day.

Will Ness
  • 70,110
  • 9
  • 98
  • 181

1 Answers1

1

You will run into trouble with inaccurate decimal representations of your values. 1/18 is not 0.05, 1/9 is not 0.11, 1/3 is not 0.33, these are only estimations.

There's -

  • 5 pennies in a nickel
  • 2 nickels in a dime
  • 10 dimes in a dollar
  • 20 dollars in a 20-dollar bill

You can establish exact ratios like this using your counting values -

  • 2 weapons in a scrap
  • 3 scraps in a reclaimed
  • 3 reclaimed in a refined
  • 90 refined in a key

weapon is your smallest unit, so that should be the 1. In other words

  • weapon = 1
  • scrap = 2
  • reclaimed = 6
  • refined = 18
  • key = 1620

Reframe your program around weapon as the smallest unit. Next read other programs that count/make change and see if you can adapt them to use your custom units. If you get stuck, come back and let us know what you tried.

Mulan
  • 129,518
  • 31
  • 228
  • 259