2
votes

Somme mini-max en JavaScript - Comment obtenir la somme minimale et la somme maximale de 4 éléments dans un tableau de 5 éléments

Lien au HackerRank Challenge

Mon idée est de parcourir le tableau et de faire la somme de tous les éléments du tableau sauf un à chaque fois, puis de trouver la plus petite somme et la plus grande somme.

Je sais que .splice () peut supprimer n'importe quel élément d'un tableau. Mais actuellement, avec mon code, je ne supprime qu'un seul élément du tableau une fois . C'est à dire. cela ne me donne qu'un seul morceau:

function miniMaxSum(arr) {

  let smallest = Math.min(...arr);
  let largest = Math.max(...arr);

  let smallestArray = arr.filter(element => element !== largest);
  let largestArray = arr.filter(element => element !== smallest);

  let sumOfSmallestArray = 0;
  let sumOfLargestArray = 0;

  for (let i = 0; i < smallestArray.length; i++) {
    sumOfSmallestArray += smallestArray[i];
  }

  for (let i = 0; i < largestArray.length; i++) {
    sumOfLargestArray += largestArray[i];
  }

  return ([sumOfSmallestArray, sumOfLargestArray]).toString();
}

Je dois supprimer un élément du tableau à chaque fois pendant la boucle, puis obtenir le max et min sommes de ce tableau.

Donc, pour un tableau donné de [1, 2, 3, 4, 5]

je devrais obtenir les "morceaux" possibles suivants: p >

[2, 3, 4, 5] , [1, 3, 4, 5] , [1, 2, 4, 5] , [1, 2, 3, 5] , [1, 2, 3, 4] .

Le bloc avec la somme la plus élevée est [2, 3, 4, 5]

Et le bloc avec la plus petite somme est [1 , 2, 3, 4] .

Comment puis-je ajuster mon code pour obtenir tous les tableaux à 4 chiffres possibles dans le tableau donné afin que je puisse comparer leurs sommes, toujours en utilisant une boucle for? Ou sinon avec une boucle for, que suggéreriez-vous d'autre?

EDIT : maintenant en utilisant Math.min () et Math .max () pour obtenir les éléments les plus petits et les plus grands du tableau. Puis en utilisant .filter () pour supprimer ces éléments afin de créer de nouveaux tableaux. Puis obtenir les sommes de ces tableaux.

function miniMaxSum(arr) {

  let smallestSum = 0;
  let largestSum = 0;

  for (let i = 0; i < arr.length; i++) {
    let chunk = arr.splice(1);
    console.log(chunk);
    if (chunk > largestSum) largestSum = chunk;
    if (chunk < smallestSum) smallestSum = chunk;
  }
  return (smallestSum, largestSum);
}

Mais même si cela fonctionne dans ma console, cela ne fonctionne pas dans HackerRank.


2 commentaires

Observation: le bloc avec la plus grande somme est le bloc sans le plus petit élément, et le bloc avec la plus petite somme est le bloc sans le plus grand élément. Il semble que ce problème ne soit en réalité qu'une forme différente de "trouver les éléments les plus grands et les plus petits d'un tableau".


Comme suggéré par @ p.s.w.g sur les mêmes lignes. Triez d'abord votre tableau, puis retirez simplement le premier élément et ajoutez pour la somme maximale et pour la suppression minimale le dernier nombre. Aucune boucle requise.


9 Réponses :


1
votes

Vous pouvez trier le tableau et pour min prendre les quatre premiers et les ajouter et pour max prendre les quatre derniers et les ajouter

let arr = [1, 2, 3, 4, 5]
let minAndMax = (arr) => {
  arr = arr.sort((a,b) => a - b)
  let op = {}

  op.minArr = arr.slice(0,4)
  op.min = op.minArr.reduce((a,b) => a+b, 0)
  
  op.maxArr =  arr.slice(arr.length-4,) 
  op.max = op.maxArr.reduce((a,b) => a + b ,0)
  return op
}


console.log(minAndMax(arr))


0 commentaires

3
votes

Vous pouvez obtenir les valeurs min et max du tableau et filtrer le tableau en ne prenant pas une fois la valeur min ou max.

function minMax(array) {
    var min = array[0],
        max = array[0],
        sum = array[0],
        i, v;
    
    for (i = 1; i < array.length; i++) {
        v = array[i];
        sum += v;
        if (v > max) max = v;
        if (v < min) min = v;
    }
    console.log(sum - min, sum - max);
}

minMax([1, 2, 3, 4, 5]);

Une approche plus classique

var data = [1, 2, 3, 4, 5],
    min = Math.min(...data),
    max = Math.max(...data),
    dataMin = data.filter(v => v !== min || !(min = -Infinity)),
    dataMax = data.filter(v => v !== max || !(max = Infinity));

console.log(...dataMin);
console.log(...dataMax);


5 commentaires

Je pense que cette solution a le plus de sens, mais je ne comprends pas .filter (v => v! == min ||! (Min = -Infinity)), . Pouvez-vous expliquer cela s'il vous plaît? Peut-être que la notation fléchée me dérange. Voici un JS Fiddle essayant de suivre votre logique: jsfiddle.net/hyp6m1eu


Il suffit d'apprendre à soustraire min de data pour trouver le plus grandArray , et soustraire max de data pour trouver le smallestArray .


l'affectation consiste à éviter d'exclure la valeur plus d'une fois, si vous avez une valeur plus d'une fois. la valeur affectée est la valeur minimale ou maximale possible.


Pouvez-vous jeter un œil à la modification que j'ai apportée à mon message d'origine, s'il vous plaît? Puisque je peux obtenir les éléments plus petits et plus grands du tableau en utilisant Math.min () et Math.max () , comment puis-je soustraire ces éléments du tableau pour créer deux nouveaux tableaux? smallestArray et largeArray ? Ensuite, je peux renvoyer la somme des éléments de ces deux nouveaux tableaux.


Cela fonctionne dans ma console, tout comme mon code édité ci-dessus, mais ni dans HackerRank, pour une raison quelconque.



1
votes

Cette solution parcourt les index des tranches, calcule la somme et lorsqu'un maximum est trouvé, elle est mise en résultat. Enfin le résultat est analysé:

var arr = [4, 8, 2, 6, 12];
var ln = arr.length;
var maxSum = undefined;
var result = "";
for (var splIndex = 0; splIndex < ln; splIndex++) {
    var item = arr.splice(splIndex, 1);
    var sum = 0;
    for (var it of arr) sum += it;
    if ((maxSum === undefined) || (maxSum < sum)) {
        maxSum = sum;
        result = JSON.stringify(arr);
    }
    arr.splice(splIndex, 0, item[0]);
}
console.log(JSON.parse(result));

EDIT

Une solution plus simple, bien sûr, est de trouver le minimum et de calculer la somme sans lui.


0 commentaires

2
votes

Le défi HackerRank ne demande que les sommes du, donc vous pouvez faire un passage dans le tableau pour calculer 3 faits:

  • Élément maximum ( a )
  • Élément minimum ( b )
  • Somme totale de tous les éléments ( c )

La somme du plus petit morceau sera c - a et la somme du plus grand sera c - b .

Voici une solution unique utilisant réduire :

var arr = [1, 2, 3, 4, 5];

var [a, b, c] = arr.reduce(([a, b, c], x) => [a > x ? a : x, b < x ? b : x, c + x], [NaN, NaN, 0]);
console.log(c - a, c - b);

Note: les NaN sont juste là pour forcer les conditions initiales ( a> x / b être faux)


3 commentaires

Compte tenu de votre commentaire et de votre logique d'origine, ne puis-je pas trouver l'élément le plus bas du tableau en utilisant Math.min () et l'élément le plus élevé du tableau en utilisant Math.max () ? Alors, comment puis-je soustraire le le plus bas et le le plus élevé du tableau pour obtenir le smallestArray et le greaterArray ? (voir ma modification).


@ HappyHands31 Oui, c'est exactement ce à quoi je faisais allusion dans le commentaire original. C'est ainsi que fonctionne la réponse de Nina Scholz, et c'est une solution parfaitement adaptée. Après avoir lu le défi HackerRank, j'ai réalisé qu'il n'était pas nécessaire que vous compreniez ce qu'est ce morceau, mais seulement la somme. Vous n'êtes pas obligé de calculer ces tableaux intermédiaires si vous travaillez simplement sur les sommes à la place. Ma réponse ne répond pas techniquement à la question initiale, je propose simplement une approche alternative au défi.


@ HappyHands31 considère l'entrée [1, 1, 3, 5, 5] , votre filtre exclut deux 1 et deux 5, donc l'échec.



4
votes

La clé est de trier ce tableau en premier, puis le minimum sera le premier élément et le maximum sera le dernier, donc si vous voulez obtenir l'ensemble minimum, ce sera le tableau sans la valeur la plus élevée (dernier élément ) et si vous voulez obtenir l'ensemble maximum, ce sera le tableau sans la valeur la plus basse (premier élément).

let data = [1, 3, 2, 4, 5];

// sort first
data = data.sort();
  
// to get the sets only
let maxSet = data.slice(1);
let minSet = data.slice(0, -1);

console.log(minSet, maxSet);

// to get just the max/min value
const sum = data.reduce((a, total) => a + total, 0);
console.log(sum - data[data.length - 1], sum - data[0]);


4 commentaires

Utiliser .sort () est une très bonne idée - merci. Cela fonctionne dans HackerRank lorsque console.log (minSet, maxSet); est commenté.


Heureux d'avoir pu aider.


Une chose que je remarque à propos de .sort () est que cela ne fonctionne pas pour les tableaux qui sont passés dans une fonction: codepen.io/AnonymousName/pen/LvQwJv?editors=1112 . Il semble que vous deviez soit déclarer votre tableau dans la fonction (comme vous l'avez fait dans votre réponse), soit utiliser une fonction de rappel: codepen.io/HappyHands31/pen/axqeKR?editors=1112


Ce n'est pas le problème. Le tri par défaut effectue le tri basé sur des chaînes, c'est pourquoi vous obtenez des tris erronés pour les entiers.



0
votes

La fonction suivante fonctionne:

function miniMaxSum(arr) {
    var _arr = arr.sort((a, b) = > a - b)
    var minVals = _arr.slice(0, 4)
    var maxVals = _arr.slice(1)
    const arrSum = __arr = > __arr.reduce((a, b) = > a + b, 0)
    var minSum = arrSum(minVals)
    var maxSum = arrSum(maxVals)
    console.log(minSum, maxSum)
}


0 commentaires

1
votes

let arr = [15 ,12, 33, 25, 4];
//sort array
const arrSort = arr.sort((a,b)=> a-b );
console.log(arrSort);
//get values and sum 
var max = arrSort.filter(value => value < Math.max(...arrSort)).reduce((ac,at)=>{
    ac += at;
    return ac; 
},0);
var min = arrSort.filter(value => value > Math.min(...arrSort)).reduce((ac,at)=>{
    ac += at;
    return ac; 
},0);
console.log(max);
console.log(min);


0 commentaires

1
votes

Cela a fonctionné pour moi.

let minValue, maxValue
const ascendingArray = arr.sort((a,b) => a - b)

const smallestNumber = ascendingArray[0]
const biggestNumber = ascendingArray[ascendingArray.length -1]

if(smallestNumber !== biggestNumber){

    const biggestArray = arr.filter((number) => {
        return number !== smallestNumber
     })

     const smallestArray = arr.filter((number) => {
         return number !== biggestNumber
      })

     minValue = smallestArray.reduce((a,b) => a + b, 0)
     maxValue = biggestArray.reduce((a,b) => a + b, 0)
     console.log(minValue, maxValue);
}
else{
    const arraySliced = arr.slice(0, 4)

    const value = arraySliced.reduce((a,b) => a + b, 0)
    console.log(value, value);
}    


0 commentaires

0
votes

J'obtiens une réponse de manière très simple

function miniMaxSum(arr) {
let minval=arr[0];
let maxval=0;
let totalSum=0;
for(let i=0;i<arr.length;i++){
    if (arr[i]>maxval){
        maxval=arr[i];
    }
    if (arr[i]<minval){
        minval=arr[i];
    }
    totalSum=totalSum+arr[i];
    
}

let minsum=totalSum - maxval;
let maxsum=totalSum - minval;

console.log( minsum,maxsum);

}


0 commentaires