2
votes

Comment parcourir un tableau de nombres pour voir quels nombres sont pertinents pour un autre nombre?

J'essaye d'écrire un programme simple en JavaScript vanille pour l'haltérophilie. L'utilisateur entre une certaine quantité de poids et il renvoie les plaques de poids spécifiques à mettre de chaque côté de la barre.

Je prends ensuite ce nombre dans une fonction qui en soustrait 45 pour tenir compte du poids de la barre, puis divise ce nombre par 2 qui est le poids à mettre de chaque côté de la barre.

let plates = [44, 33, 22, 11, 5.5, 2.75];

J'ai un tableau avec chaque plaque de poids:

const num = document.getElementById("weightAmount").value;

function getWeightAmount (num) {
const newNum = num - 45;
const halfNum = newNum / 2;
return getWeights(halfNum);
}

J'ai du mal à boucler correctement le tableau pour obtenir ce que je veux. Si j'ai besoin, disons, de 60,5 livres de chaque côté, il devrait renvoyer 44, 11, 5,5. J'ai donc besoin de savoir quels nombres du tableau plaque correspondent au nombre renvoyé par ma première fonction.

J'ai un tableau vide appelé poids dans lequel je veux pousser les nombres du tableau plaques dans ce travail avec le poids qui est ensuite retourné.

Ma question est de savoir comment puis-je parcourir le tableau plaques pour déterminer quels poids sont nécessaires?


5 commentaires

Trouvez le poids qui ne se divise qu'une fois en votre poids cible, ajoutez-le à la barre et soustrayez-le du poids cible. Répétez jusqu'à ce que le poids cible soit égal à zéro.


Vous parcourez un tableau avec plates.forEach (function (plate) {}} pour for (let plate of plates) {}


Peut-être pertinent: Problème de sac à dos


Eh bien, comme mentionné par @ FK82, c'est Knapsack, mais légèrement modifié. Il s’agit en fait d’une version modifiée d’un problème de changement [

3 Réponses :


1
votes

Voici une solution. Dans le cas où les plaques disponibles ne correspondent pas au poids cible, il renverra la combinaison de plaques disponibles qui s'additionnent le plus près de la cible. Adapté de cette réponse .

function createSubsets(numbers, target) {
    // filter out all items larger than target
    numbers = numbers.filter(function (value) {
        return value <= target;
    });

    // sort from largest to smallest
    numbers.sort(function (a, b) {
        return b - a;
    });

    var i;
    var sum = 0;
    var addedIndices = [];

    // go from the largest to the smallest number and
    // add as many of them as long as the sum isn't above target
    for (i = 0; i < numbers.length; i++) {
        if (sum + numbers[i] <= target) {
            sum += numbers[i];
            addedIndices.push(i);
        }
    }

    return addedIndices.map(n => numbers[n]);
}


0 commentaires

1
votes

J'ai une solution simple ci-dessous si la valeur du poids cible sera toujours la somme des plaques disponibles. En supposant que le tableau de pondérations est trié dans un ordre décroissant. J'ai pensé à tous les poids disponibles et je ne passerai au poids suivant que si le total dépasse le poids total dont vous avez besoin.

function getWeights(targeWeight) {

    let plates = [44, 33, 22, 11, 5.5, 2.75];

    let totalWeight = 0;

    let neededPlates = [];

    let i = 0;

    while(i < plates.length){

        var pweight = totalWeight + plates[i];

        if (pweight > targeWeight) {
            i++;
            continue;
        }

        totalWeight += plates[i];
        neededPlates.push(plates[i]);
    }

    return neededPlates;
}

console.log(getWeights(60.5)); // [44, 11, 5.5]
console.log(getWeights(104.5)); //[44, 44, 11, 5.5]


1 commentaires

A parfaitement fonctionné! Merci!



2
votes

Une solution possible à ce problème consiste à répéter indéfiniment jusqu'à ce que

  • vous avez une solution
  • le problème devient insoluble étant donné l'ensemble des pondérations

À chaque étape d'itération, vous soustrayez le poids le plus élevé possible multiplié par le facteur le plus élevé possible, stockez les deux dans une structure de données appropriée (mon implémentation utilise simplement un Object ) et continuez. p>

const plates = [44, 33, 22, 11, 5.5, 2.75];

// We assume that plates is always sorted
const determineWeights = (totalWeight) => {
  let factor = 0;
  let weights = {};

  while (totalWeight > 0) {
    weight = plates.find(weight => Math.floor(totalWeight / weight) > 0);

    // There is no weight we can subtract from the total weight to solve the problem
    // Hence, the problem is unsolvable and we return null to indicate that no solution exists
    if (!weight) { return null; }

    // Determine the factor with which to multiply the weight before we subtract from the total weight an subtract the product
    factor = Math.floor(totalWeight / weight);
    totalWeight = totalWeight - factor * weight;

    // Store weight and factor
    weights[weight] = factor;
  }
  
  return weights;
}


console.log(determineWeights(104.5)); // { "11": 1, "44": 2, "5.5": 1 }
console.log(determineWeights(60.5)); // { "11": 1, "44": 1, "5.5": 1 }
console.log(determineWeights(5.0)); // null

Le problème est essentiellement une instance du problème Knapsack . p>

Notez que nous supposons que les plaques sont triées. Sinon, Array.find ne récupérera pas nécessairement le poids maximum qui peut être soustrait du poids total.


0 commentaires