JavaScript Mini-Max Sum - Challenge from HackerRank website - javascript

Here is the Challenge:
https://www.hackerrank.com/challenges/mini-max-sum/problem
Despite my answer is returning the same number that matches the expected result, I have done something wrong because my answer has been rejected.
How can I solve it?
Here is the solution I had tried:
function miniMaxSum(arr) {
var arrClone1 = arr.slice()
var arrClone2 = arr.slice()
var arrMinor = arrClone1.sort(function(a, b){return a - b;})
arrMinor.pop()
var arrMajor = arrClone2.sort(function(a, b){return b - a;})
arrMajor.pop()
function getSum(a, b) {
return a + b;
}
var result1 = arrMinor.reduce(getSum)
var result2 = arrMajor.reduce(getSum)
console.log(`${result1} ${result2}`) // it is returning: 10 14

I think the solution should be easier:
function miniMaxSum(arr) {
let sum = arr.reduce((a, b) => a + b);
let maxVal = Math.max(...arr);
let minVal = Math.min(...arr);
console.log((sum - maxVal) + ' ' + (sum - minVal));
}

function miniMaxSum(arr) {
// Write your code here
let sum=arr.reduce((a,b)=>{
return a+b;
});
const min=sum-Math.max(...arr);
const max=sum-Math.min(...arr);
console.log(min+" "+max);
}

I found the answer. I noticed that it was mandatory to name the function argument as 'input' instead of 'arr'. That's why the answer was rejected by the HackerRank platform despite the code returned the right result in my editor, NOT in the HackerRank platform. If you do this simply adjustment, it works in the HackerRank platform too.
Just like that:
function miniMaxSum(input) { //'input' NOT 'arr'
var arrClone1 = input.slice() //'input' NOT 'arr'
var arrClone2 = input.slice() //'input' NOT 'arr'
//... rest of the code omitted

my solution:
let sumValue = arr.reduce((a, b) => {
return a + b;
});
const min = sumValue - Math.max(...arr);
const max = sumValue - Math.min(...arr);
const result = `${min} ${max}`
console.log(result);

Here's a more procedural solution to the problem.
function miniMaxSum(arr) {
let sum_min = 0
let sum_max = 0
let min_val = arr[0]
let max_val = arr[0]
let sum = 0
for(let index = 0; index < arr.length; index += 1){
if(arr[index] > max_val) {
max_val = arr[index]
}
if(arr[index] < min_val){
min_val = arr[index]
}
sum = sum + arr[index]
}
sum_min = sum - max_val
sum_max = sum - min_val
console.log(sum_min, sum_max)
}

This is my solution, I hope it works for you
function miniMaxSum(arr) {
// Write your code here
const max = arr.sort((a,b) => b-a).slice(0,4).reduce((a,b)=> a+b,0)
const min = arr.sort((a,b) => b-a).reverse().slice(0,4).reduce((a,b)=> a+b,0)
console.log(min,max)
}

You've got it right. The only "problem" is, that you're doing a Java or C++ coding challenge. (That's why they're mentioning the 32 bit integer).
The input shouldn't be an array but "A single line of five space-separated integers."

Here is another solution...
function miniMaxSum(arr) {
let minValue = 0, maxValue = 0, minIndex = 0, maxIndex = 0, minSum = 0, maxSum = 0;
minValue = Math.min(...arr);
maxValue = Math.max(...arr);
minIndex = arr.indexOf(minValue);
maxIndex = arr.indexOf(maxValue);
for (let i = 0; i < arr.length; i++){
if (minIndex != i) {
maxSum += arr[i];
}
if (maxIndex != i) {
minSum += arr[i];
}
}
console.log(minSum, maxSum);
}
miniMaxSum([1,2,3,4,5]);
Click Here to RUN

Using .reduce:
const arr = [1, 2, 3, 4, 5];
function miniMaxSum(arr) {
const res = arr.sort((a,b) => a-b).reduce((prev, cur, i) => {
if(i!=0) ( prev.max=prev.max+cur || cur);
if(i!=arr.length-1) ( prev.min=prev.min+cur || cur);
return prev;
}, [{max:0},{min:0}]);
console.log(res.min || 0, res.max || 0);
}
miniMaxSum(arr) // 10 14

Try this, it works for all cases:
function miniMaxSum(arr) {
let c = arr.sort();
let a = c.slice(0,4)
let b = c.slice(1,5)
console.log(a.reduce((p,n)=>p+n,0),b.reduce((p,n)=>p+n,0))
}

Another solution !
const numbers = arr.slice('').sort();
let min = 0;
let max = 0;
for (let i = 0; i < numbers.length; i++) {
if (i < 4) {
min = min + numbers[i];
}
if (i > 0 && i < 5) {
max += numbers[i];
}
}
console.log(`${min} ${max}`);

let numbers = arr.slice('').sort();
let maxScore = 0;
let minScore = 0;
for(let i = 0; i < numbers.length - 1; i++) {
minScore += numbers[i];
};
for(let j = 1; j < numbers.length; j++) {
maxScore += numbers[j];
};
console.log(`${minScore} ${maxScore}`);

function miniMaxSum(input) {
let minElem = 0, maxElem = 0, sum = 0;
minElem = input[0];
maxElem = minElem;
sum = minElem;
for (let i = 1; i < input.length; i++) {
sum += input[i];
if (input[i] < minElem) {
minElem = input[i];
}
if (input[i] > maxElem) {
maxElem = input[i];
}
}
let minresult = sum - maxElem;
let maxresult = sum - minElem;
console.log(minresult + " " + maxresult);
}

function miniMaxSum(arr) {
let sortarr = arr.sort();
let maxSum = 0;
let minSum = 0;
for (let i=0 ; i < arr.length - 1; i++ ){
minSum += sortarr[i];
}
for (let j=arr.length - 1; j > 0; j-- ){
maxSum += sortarr[j];
}
console.log(minSum + ' ' + maxSum);
}

guys. Just sharing my solution!
function miniMaxSum(input) {
input.sort((a,b) => a-b)
let min = 0, max = 0;
for(let i=0; i < input.length; i++)
{
min += input[i]
max += input[i]
}
console.log((min - input[input.length -1]) + ' ' + (max - input[0]))
}

Here is my solution --> This will handle duplicate and float values as well
Check the live demo below:
function miniMaxSum(arr) {
let tempArr=[];
var sum = arr.reduce((acc,cur)=>acc+cur);
arr.map((val)=>{
tempArr.push(Number(sum-val));
});
// unique values only
tempArr = [...new Set(tempArr)];
console.log(`${Math.min.apply(null,tempArr)} ${Math.max.apply(null,tempArr)}`);
}
miniMaxSum([7,69,2,203,894]);

this is my solution
function miniMaxSum(arr) {
// Write your code here
var sums = [];
for (var i=0; i<arr.length; i++) {
var num = arr.shift();
var sum = arr.reduce(function(acc, val) { return acc + val; }, 0);
sums.push(sum);
arr.push(num)
}
console.log(Math.min(...sums) + " " + Math.max(...sums));
}

function miniMaxSum(arr) {
let arrayMin = arr.slice() //new array for minimum
let arrayMax = arr.slice() //new array for maximum
let small = arrayMin.sort((a,b) => {return a - b}) //sort number small to big
let big = arrayMax.sort((a,b) => {return a - b}) //sort number small to big
function maxsum (a,b){return a + b} // that's function for calculate all numbers
let min = small.pop() //remove last element
let max = big.shift() //remove first element
let mins = arrayMin.reduce(maxsum) //apply maxsum function to array
let maxs = arrayMax.reduce(maxsum) //apply maxsum function to array
console.log(`${mins} ${maxs}`)
}

code worked for me is as below:
function miniMaxSum(arr) {
// Write your code here
let min = Math.min(...arr);
let max = Math.max(...arr);
let arrExceptMin, arrExceptMax;
let allEqual = arr.every(val => val === arr[0]);
if(allEqual) {
return console.log(sum(arr.slice(1)) + ' ' + sum(arr.slice(1)));
}
if(min) {
arrExceptMin = arr.filter(val => val !== min);
}
if(max) {
arrExceptMax = arr.filter(val => val !== max);
}
return console.log(sum(arrExceptMax) + ' ' + sum(arrExceptMin));
}

Simple Solution (I hope), there was not any problem with 'arr' argument with me.
function miniMaxSum(arr) {
// Write your code here
let a=0, b=0;
arr.sort();
for(let i=0; i<4; i++) {
a+=arr[i];
b+=arr[i+1];
}
console.log(a,b)
}

you can shorten the code
function miniMaxSum(arr) {
// Write your code here
arr.sort((a,b) => a-b)
let min= 0, max = 0;
for(let i = 0; i < arr.length-1 ; i++){
min += arr[i];
}
for(let j = 1; j < arr.length; j++){
max += arr[j];
}
console.log(min,max);
}

Here's a single loop variant.
function miniMaxSum(arr) {
let min = 0
let max = 0
let sum = 0
for (const n of arr) {
sum += n
if (!min || min > n) {
min = n
continue
}
if (max < n) {
max = n
}
}
console.log(sum - max, sum - min)
}

function miniMaxSum(arr) {
let arrMin = [].concat(arr).sort()
let arrMax = [].concat(arr).sort()
arrMin.pop();
arrMax.shift();
let arrMinReduced = arrMin.reduce((prev, curr) => prev + curr)
let arrMaxReduced = arrMax.reduce((prev, curr) => prev + curr)
console.log(arrMinReduced, arrMaxReduced)
}
miniMaxSum([1,2,3,4,5])

This solution uses only single loop and also no utility functions.
code is pretty much self-explanatory.
function miniMaxSum(arr) {
// Write your code here
const total = arr[0] + arr[1] + arr[2] + arr[3] + arr[4];
let max, min;
for (let i = 0; i < arr.length; i++) {
// Add all elements and subtract one element so that we sum of 4 items only
let sum = total - arr[i];
// Sets min & max both equal to sum on first iteration
if (max === undefined && min === undefined) {
max = sum;
min = sum; `enter code here`
} else if (max < sum) {
max = sum
} else if (min > sum) {
min = sum
}
}
console.log(min, max)
}

const arr = [1, 2, 3, 4, 5];
let len = arr.length;
let smallest = arr[0];
let largest = arr[0];
let minSum = 0;
let maxSum = 0;
function minMax(arr, len){
for(let i = 0; i<len; i++){
if(arr[i] >= largest){
largest = arr[i];
}
if(arr[i] <= smallest){
smallest = arr[i];
}
}
for(let i = 0; i < len; i++){
if(arr[i] > smallest){
maxSum += arr[i];
}
if(arr[i] < largest){
minSum += arr[i];
}
}
return console.log(minSum, maxSum)
}
minMax(arr, len)

solution in fewest possible lines, i think
'function miniMaxSum(arr) {
arr.sort((a,b)=>a-b);
let fSum=0, lSum=0;
for(let x=0; x<arr.length-1; x++){
fSum+=arr[x]
}
for(let x=1; x<arr.length; x++){
lSum+=arr[x]
}
console.log(fSum+" "+lSum);
}'

Related

How to iterate to 100 using a for or while loop and show the sum of each iteration with javascript?

Just doing a small homework. I need to iterate to 100, but also console.log the result of each previous example.
Example of the series: (1)+(1+2)+(1+2+3)+…+(1+2+3+…+n)<=100
Iteracion1=1
Iteracion2= 1+2 = 3
iteracion 3: 1+2+3 = 6
iteracion 4: 1+2+3+4 = 10
I have this:
for (i = 0; i <= 100; i++) {
if(i < 100) {
console.log(`${i}+${1}`);
}};
But I don't know how to add the sum of it on each iteration. I you have any references for this it would be great! thank you.
You can efficiently achieve the result using a single loop.
For demo purposes, I've printed up to 20. You can add any number of your choice.
let lastTotal = 0;
let lastStr = "";
for (let i = 1; i <= 10; ++i) {
const total = (lastTotal ?? 0) + i;
const str = lastStr ? lastStr + " + " + i : i;
console.log(`Iteration ${i}: ${str}${total === 1 ? "" : " = " + total}`);
lastTotal = total;
lastStr = str;
}
/* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use variables outside of for to achieve this
let sum = 0;
const previousSums = [];
for (i = 0; i < 100; i++) {
previousSums.push(sum);
sum += i;
console.log(`${previousSums}`);
}
Create an array you can add indexes to.
Create a function that calculates the sum of the numbers in the array. I've used reduce here.
Create a string, and then log it.
const arr = [];
function sum(arr) {
return arr.reduce((acc, c) => acc + c, 0);
}
// On each iteration push the index in to the
// array. Create a string that joins up the array
// elements and logs the result of the sum
for (let i = 1; i <= 10; i++) {
arr.push(i);
const str = `Iteration ${i}: ${arr.join('+')} = ${sum(arr)}`;
console.log(str);
};
This should do fine.
I created a new Array for the length of iteration of i and use Array#reduce to sum it all up to a number.
const max = 10;
for (let i = 1; i <= max; i++) {
const arr = new Array(i).fill().map((_, i) => i + 1);
console.log(`Iteration ${i}: ${arr.join('+')} = ${arr.reduce((acc, b) => acc + b, 0)}`);
}
var total = 0;
var res = 0;
var upto = 6;
for(i=1;i<=upto;i++){
total = total+i;
res = res+total;
}
console.log(res);

How to Make Consecutive Numbers from an Array

I have an array like this
[-2,4,5,6,7,8,10,11,15,16,17,18,21]
Is anyone know, how to make the output from that array become integer like this
-2,4-8,10-11,15-18,21
The output will take the consecutive number become one number
This things is new for me, any help would be appreciated, thanks
Below I created function for replacing a sequence in an array with a string containing its range. There are three functions.
getConsectiveCount will take array and index as arguments and will get the count of consecutive numbers after that.
replaceFirstConsective will take array and will replace only first sequence in the array.
replaceAllConsectives will replace all the sequences in an array.
const arr = [-2,4,5,6,7,8,10,11,15,16,17,18,21];
const getConsectiveCount = (arr, index) => {
let count = 0;
for(let i = index; i < arr.length; i++){
if(arr[i + 1] === arr[index] + (i - index) + 1){
count++;
}
}
return count;
}
console.log(getConsectiveCount(arr, 1));
const replaceFirstConsective = (arr) => {
for(let i = 0; i < arr.length; i++){
let count = getConsectiveCount(arr,i);
if(count){
return [...arr.slice(0, i), `${arr[i]}-${arr[i + count]}`, ...arr.slice(i + count + 1)]
}
}
return arr;
}
const replaceAllConsectives = (arr) => {
for(let i = 0; i < arr.length;i++){
arr = replaceFirstConsective(arr)
}
return arr;
}
console.log(JSON.stringify(replaceAllConsectives(arr)))
const inp = [-2,4,5,6,7,8,10,11,15,16,17,18,21];
let res = [];
for(let i=0;i<inp.length;i++){
let b = inp[i];
let j = i+1;
while(j<inp.length){
if(b+1 == inp[j]){
b = inp[j++];
continue;
}
break;
}
if(i == j-1){
res.push(inp[i]);
}
else{
res.push(inp[i]+"-"+inp[j-1]);
i=j-1;
}
}
console.log(res);
Check this if it helps.
I have done that :
const arr1 = [-2,4,5,6,7,8,10,11,15,16,17,18,21]
const arr2 = arr1.reduce((a,c,i,{[i+1]:nxt})=>
{
if (!a.s1) a.s1 = c.toString(10)
if ( (c+1) !== nxt )
{
a.s1 += a.s2 ? `_${a.s2}` : ''
a.r.push(a.s1)
a.s1 = a.s2 = ''
}
else a.s2 = nxt.toString(10)
return (nxt===undefined) ? a.r : a
},{r:[],s1:'',s2:''})
console.log(JSON.stringify( arr2 ))
.as-console-wrapper { max-height: 100% !important; top: 0; }
It's an interesting problem. The way I solved it was to iterate over the array and then find the index of the last consecutive number from the current one. We can either write the single number into the result array or write the range string in there and continue from the next number after the range.
function lastConsecutive(arr, start)
{
let ind = start;
while(ind < arr.length && (arr[ind] + 1) == arr[ind + 1])
{
ind++;
}
return ind;
}
function consecCollapse(nums)
{
let i = 0;
const result = [];
while (i < nums.length)
{
let n = lastConsecutive(nums, i);
result.push((n == i) ? nums[n]+"" : nums[i]+"-"+nums[n]);
i = n + 1;
}
return result;
}
console.log(consecCollapse([-2,4,5,6,7,8,10,11,15,16,17,18,21]));
const arr = [-2,4,5,6,7,8,10,11,15,16,17,18,21];
const _newArray = [];
let start = arr[0];
let end = start;
for(let i=1; i<=arr.length; i++) {
let elem = arr[i];
if (elem === end+1) {
end = elem; // update the end value (range)
}else {
if (end !== start) {
_newArray.push(`${start}-${end}`);
} else {
_newArray.push(start);
}
start = elem;
end = start;
}
}
console.log(_newArray.join(','))
If a sorted array with unique numbers, this is how I find the range of numbers with dash:
function findRange(arr) {
const results = []
for (let i = 0; i < arr.length; i++) {
// only more than 2 consecutive numbers can be form a range
if (arr[i + 1] === arr[i] + 1 && arr[i + 2] === arr[i] + 2) {
// store the first number of a range
results.push(arr[i])
// loop until meet the next one is not consecutive
while (arr[i] + 1 === arr[i + 1]) {
i++
}
// store the last number of a range with '-' in between
results[results.length - 1] = results[results.length - 1] + '-' + arr[i]
} else {
// if only 2 consecutive number or not consecutive at all
results.push(arr[i])
}
}
return results
}
console.log(findRange([1, 2, 3, 4, 6, 7, 8, 9]))
console.log(findRange([1, 2, 4, 6, 7, 8, 9]))
console.log(findRange([-2,4,5,6,7,8,10,11,15,16,17,18,21]))

Array Processing logic correction

I have an array [1,2,4,5,1,7,8,9,2,3]
and i would like it to generate all subset which sum of values are less than 10
current result [[1,2,4],[5,1],[7],[8],[9],[2,3]]
expected result [[4,5,1],[9,1],[8,2],[3,7],[1,2]]
that is what i did
var a = [1,2,4,5,1,7,8,9,2,3], tempArr = []; tempSum = 0, result = [];
for (var i = 0;i< a.length; i += 1 ) {
tempSum+=a[i];
tempArr.push(a[i]);
if((tempSum+a[i+1])>10) {
result.push(tempArr);
tempSum = 0;
tempArr = [];
} else if (i == a.length-1 && tempArr.length > 0) { // if array is [1,2,3]
result.push(tempArr);
}
}
but it gives me [[1,2,4],[5,1],[7],[8],[9],[2,3]] and it has 6 subset, but i expect to get [[4,5,1],[9,1],[8,2],[3,7],[1,2]] which has 5 subset.
Below logic is in JavaScript :-
var limit = 10;
var arr = [1,2,4,5,1,7,8,9,2,3];
arr.sort();
var ans = new Array ( );
while(arr.length >0){
var ts = arr[arr.length-1];
arr.splice(arr.length-1 , 1);
var ta= new Array ( );
ta.push(ts);
var x = arr.length-1;
while(x>=0){
if(ts + arr[x] <= limit){
ts = ts + arr[x];
ta.push(arr[x]);
arr.splice(x , 1);
}
x= x-1;
}
ans.push(JSON.stringify(ta));
}
alert(ans);
It is Giving Output as required .
[9,1],[8,2],[7,3],[5,4,1],[2]
I have removed duplicates then added maxSum parameter to combine function to generate all subset which have those conditions and then sorted subsets by sum of the values and sliced them.
You could change parameters to fit it for your problem.
var arr = [1,2,4,5,1,7,8,9,2,3]
MAX_SUM = 10,
MIN_SUBSET_LEN = 2,
RESULT_LEN = 5;
//remove duplicates
var uniqeSet = arr.filter(function(value, index){
return this.indexOf(value) == index
},arr);
// a function to get all subset which
// their length are greater than minLength and
// sum of values are little than maxSum
var combine = function(sourceArr, minLength, maxSum) {
var fn = function(n, src, got, all, sum) {
if(sum <= maxSum){
if (n == 0) {
if (got.length > 0) {
all.push({arr:got,sum:sum});
}
return;
}
for (var j = 0; j < src.length; j++) {
var tempSum = sum
fn(n - 1, src.slice(j + 1), got.concat([src[j]]), all, sum + src[j]);
}
}
return;
}
var all = [];
for (var i = minLength; i < sourceArr.length; i++) {
fn(i, sourceArr, [], all, 0);
}
return all;
}
var result = combine(uniqeSet, MIN_SUBSET_LEN, MAX_SUM);
var sortedSliced = result.sort(function(a1, a2){
return a2.sum - a1.sum;
}).slice(0, RESULT_LEN).map(function(m){return m.arr;});
console.log(JSON.stringify(sortedSliced));

show most frequently occuring input value [duplicate]

var store = ['1','2','2','3','4'];
I want to find out that 2 appear the most in the array. How do I go about doing that?
I would do something like:
var store = ['1','2','2','3','4'];
var frequency = {}; // array of frequency.
var max = 0; // holds the max frequency.
var result; // holds the max frequency element.
for(var v in store) {
frequency[store[v]]=(frequency[store[v]] || 0)+1; // increment frequency.
if(frequency[store[v]] > max) { // is this frequency > max so far ?
max = frequency[store[v]]; // update max.
result = store[v]; // update result.
}
}
Solution with emphasis to Array.prototype.forEach and the problem of getting more than one key if the max count is shared among more items.
Edit: Proposal with one loop, only.
var store = ['1', '2', '2', '3', '4', '5', '5'],
distribution = {},
max = 0,
result = [];
store.forEach(function (a) {
distribution[a] = (distribution[a] || 0) + 1;
if (distribution[a] > max) {
max = distribution[a];
result = [a];
return;
}
if (distribution[a] === max) {
result.push(a);
}
});
console.log('max: ' + max);
console.log('key/s with max count: ' + JSON.stringify(result));
console.log(distribution);
arr.sort();
var max=0,result,freq = 0;
for(var i=0; i < arr.length; i++){
if(arr[i]===arr[i+1]){
freq++;
}
else {
freq=0;
}
if(freq>max){
result = arr[i];
max = freq;
}
}
return result;
Make a histogram, find the key for the maximum number in the histogram.
var hist = [];
for (var i = 0; i < store.length; i++) {
var n = store[i];
if (hist[n] === undefined) hist[n] = 0;
else hist[n]++;
}
var best_count = hist[store[0]];
var best = store[0];
for (var i = 0; i < store.length; i++) {
if (hist[store[i]] > best_count) {
best_count = hist[store[i]];
best = store[i];
}
}
alert(best + ' occurs the most at ' + best_count + ' occurrences');
This assumes either there are no ties, or you don't care which is selected.
Another ES6 option. Works with strings or numbers.
function mode(arr) {
const store = {}
arr.forEach((num) => store[num] ? store[num] += 1 : store[num] = 1)
return Object.keys(store).sort((a, b) => store[b] - store[a])[0]
}
If the array is sorted this should work:
function popular(array) {
if (array.length == 0) return [null, 0];
var n = max = 1, maxNum = array[0], pv, cv;
for(var i = 0; i < array.length; i++, pv = array[i-1], cv = array[i]) {
if (pv == cv) {
if (++n >= max) {
max = n; maxNum = cv;
}
} else n = 1;
}
return [maxNum, max];
};
popular([1,2,2,3,4,9,9,9,9,1,1])
[9, 4]
popular([1,2,2,3,4,9,9,9,9,1,1,10,10,10,10,10])
[10, 5]
This version will quit looking when the count exceeds the number of items not yet counted.
It works without sorting the array.
Array.prototype.most= function(){
var L= this.length, freq= [], unique= [],
tem, max= 1, index, count;
while(L>= max){
tem= this[--L];
if(unique.indexOf(tem)== -1){
unique.push(tem);
index= -1, count= 0;
while((index= this.indexOf(tem, index+1))!= -1){
++count;
}
if(count> max){
freq= [tem];
max= count;
}
else if(count== max) freq.push(tem);
}
}
return [freq, max];
}
//test
var A= ["apples","oranges","oranges","oranges","bananas",
"bananas","oranges","bananas"];
alert(A.most()) // [oranges,4]
A.push("bananas");
alert(A.most()) // [bananas,oranges,4]
I solved it this way for finding the most common integer
function mostCommon(arr) {
// finds the first most common integer, doesn't account for 2 equally common integers (a tie)
freq = [];
// set all frequency counts to 0
for(i = 0; i < arr[arr.length-1]; i++) {
freq[i] = 0;
}
// use index in freq to represent the number, and the value at the index represent the frequency count
for(i = 0; i < arr.length; i++) {
freq[arr[i]]++;
}
// find biggest number's index, that's the most frequent integer
mostCommon = freq[0];
for(i = 0; i < freq.length; i++) {
if(freq[i] > mostCommon) {
mostCommon = i;
}
}
return mostCommon;
}
This is my solution.
var max_frequent_elements = function(arr){
var a = [], b = [], prev;
arr.sort();
for ( var i = 0; i < arr.length; i++ ) {
if ( arr[i] !== prev ) {
a.push(arr[i]);
b.push(1);
} else {
b[b.length-1]++;
}
prev = arr[i];
}
var max = b[0]
for(var p=1;p<b.length;p++){
if(b[p]>max)max=b[p]
}
var indices = []
for(var q=0;q<a.length;q++){
if(b[q]==max){indices.push(a[q])}
}
return indices;
};
All the solutions above are iterative.
Here's a ES6 functional mutation-less version:
Array.prototype.mostRepresented = function() {
const indexedElements = this.reduce((result, element) => {
return result.map(el => {
return {
value: el.value,
count: el.count + (el.value === element ? 1 : 0),
};
}).concat(result.some(el => el.value === element) ? [] : {value: element, count: 1});
}, []);
return (indexedElements.slice(1).reduce(
(result, indexedElement) => (indexedElement.count > result.count ? indexedElement : result),
indexedElements[0]) || {}).value;
};
It could be optimized in specific situations where performance is the bottleneck, but it has a great advantage of working with any kind of array elements.
The last line could be replaced with:
return (indexedElements.maxBy(el => el.count) || {}).value;
With:
Array.prototype.maxBy = function(fn) {
return this.slice(1).reduce((result, element) => (fn(element) > fn(result) ? element : result), this[0]);
};
for clarity
If the array contains strings try this solution
function GetMaxFrequency (array) {
var store = array;
var frequency = []; // array of frequency.
var result; // holds the max frequency element.
for(var v in store) {
var target = store[v];
var numOccurences = $.grep(store, function (elem) {
return elem === target;
}).length;
frequency.push(numOccurences);
}
maxValue = Math.max.apply(this, frequency);
result = store[$.inArray(maxValue,frequency)];
return result;
}
var store = ['ff','cc','cc','ff','ff','ff','ff','ff','ff','yahya','yahya','cc','yahya'];
alert(GetMaxFrequency(store));
A fairly short solution.
function mostCommon(list) {
var keyCounts = {};
var topCount = 0;
var topKey = {};
list.forEach(function(item, val) {
keyCounts[item] = keyCounts[item] + 1 || 1;
if (keyCounts[item] > topCount) {
topKey = item;
topCount = keyCounts[item];
}
});
return topKey;
}
document.write(mostCommon(['AA', 'AA', 'AB', 'AC']))
This solution returns an array of the most appearing numbers in an array, in case multiple numbers appear at the "max" times.
function mode(numbers) {
var counterObj = {};
var max = 0;
var result = [];
for(let num in numbers) {
counterObj[numbers[num]] = (counterObj[numbers[num]] || 0) + 1;
if(counterObj[numbers[num]] >= max) {
max = counterObj[numbers[num]];
}
}
for (let num in counterObj) {
if(counterObj[num] == max) {
result.push(parseInt(num));
}
}
return result;
}

Get the item that appears the most times in an array

var store = ['1','2','2','3','4'];
I want to find out that 2 appear the most in the array. How do I go about doing that?
I would do something like:
var store = ['1','2','2','3','4'];
var frequency = {}; // array of frequency.
var max = 0; // holds the max frequency.
var result; // holds the max frequency element.
for(var v in store) {
frequency[store[v]]=(frequency[store[v]] || 0)+1; // increment frequency.
if(frequency[store[v]] > max) { // is this frequency > max so far ?
max = frequency[store[v]]; // update max.
result = store[v]; // update result.
}
}
Solution with emphasis to Array.prototype.forEach and the problem of getting more than one key if the max count is shared among more items.
Edit: Proposal with one loop, only.
var store = ['1', '2', '2', '3', '4', '5', '5'],
distribution = {},
max = 0,
result = [];
store.forEach(function (a) {
distribution[a] = (distribution[a] || 0) + 1;
if (distribution[a] > max) {
max = distribution[a];
result = [a];
return;
}
if (distribution[a] === max) {
result.push(a);
}
});
console.log('max: ' + max);
console.log('key/s with max count: ' + JSON.stringify(result));
console.log(distribution);
arr.sort();
var max=0,result,freq = 0;
for(var i=0; i < arr.length; i++){
if(arr[i]===arr[i+1]){
freq++;
}
else {
freq=0;
}
if(freq>max){
result = arr[i];
max = freq;
}
}
return result;
Make a histogram, find the key for the maximum number in the histogram.
var hist = [];
for (var i = 0; i < store.length; i++) {
var n = store[i];
if (hist[n] === undefined) hist[n] = 0;
else hist[n]++;
}
var best_count = hist[store[0]];
var best = store[0];
for (var i = 0; i < store.length; i++) {
if (hist[store[i]] > best_count) {
best_count = hist[store[i]];
best = store[i];
}
}
alert(best + ' occurs the most at ' + best_count + ' occurrences');
This assumes either there are no ties, or you don't care which is selected.
Another ES6 option. Works with strings or numbers.
function mode(arr) {
const store = {}
arr.forEach((num) => store[num] ? store[num] += 1 : store[num] = 1)
return Object.keys(store).sort((a, b) => store[b] - store[a])[0]
}
If the array is sorted this should work:
function popular(array) {
if (array.length == 0) return [null, 0];
var n = max = 1, maxNum = array[0], pv, cv;
for(var i = 0; i < array.length; i++, pv = array[i-1], cv = array[i]) {
if (pv == cv) {
if (++n >= max) {
max = n; maxNum = cv;
}
} else n = 1;
}
return [maxNum, max];
};
popular([1,2,2,3,4,9,9,9,9,1,1])
[9, 4]
popular([1,2,2,3,4,9,9,9,9,1,1,10,10,10,10,10])
[10, 5]
This version will quit looking when the count exceeds the number of items not yet counted.
It works without sorting the array.
Array.prototype.most= function(){
var L= this.length, freq= [], unique= [],
tem, max= 1, index, count;
while(L>= max){
tem= this[--L];
if(unique.indexOf(tem)== -1){
unique.push(tem);
index= -1, count= 0;
while((index= this.indexOf(tem, index+1))!= -1){
++count;
}
if(count> max){
freq= [tem];
max= count;
}
else if(count== max) freq.push(tem);
}
}
return [freq, max];
}
//test
var A= ["apples","oranges","oranges","oranges","bananas",
"bananas","oranges","bananas"];
alert(A.most()) // [oranges,4]
A.push("bananas");
alert(A.most()) // [bananas,oranges,4]
I solved it this way for finding the most common integer
function mostCommon(arr) {
// finds the first most common integer, doesn't account for 2 equally common integers (a tie)
freq = [];
// set all frequency counts to 0
for(i = 0; i < arr[arr.length-1]; i++) {
freq[i] = 0;
}
// use index in freq to represent the number, and the value at the index represent the frequency count
for(i = 0; i < arr.length; i++) {
freq[arr[i]]++;
}
// find biggest number's index, that's the most frequent integer
mostCommon = freq[0];
for(i = 0; i < freq.length; i++) {
if(freq[i] > mostCommon) {
mostCommon = i;
}
}
return mostCommon;
}
This is my solution.
var max_frequent_elements = function(arr){
var a = [], b = [], prev;
arr.sort();
for ( var i = 0; i < arr.length; i++ ) {
if ( arr[i] !== prev ) {
a.push(arr[i]);
b.push(1);
} else {
b[b.length-1]++;
}
prev = arr[i];
}
var max = b[0]
for(var p=1;p<b.length;p++){
if(b[p]>max)max=b[p]
}
var indices = []
for(var q=0;q<a.length;q++){
if(b[q]==max){indices.push(a[q])}
}
return indices;
};
All the solutions above are iterative.
Here's a ES6 functional mutation-less version:
Array.prototype.mostRepresented = function() {
const indexedElements = this.reduce((result, element) => {
return result.map(el => {
return {
value: el.value,
count: el.count + (el.value === element ? 1 : 0),
};
}).concat(result.some(el => el.value === element) ? [] : {value: element, count: 1});
}, []);
return (indexedElements.slice(1).reduce(
(result, indexedElement) => (indexedElement.count > result.count ? indexedElement : result),
indexedElements[0]) || {}).value;
};
It could be optimized in specific situations where performance is the bottleneck, but it has a great advantage of working with any kind of array elements.
The last line could be replaced with:
return (indexedElements.maxBy(el => el.count) || {}).value;
With:
Array.prototype.maxBy = function(fn) {
return this.slice(1).reduce((result, element) => (fn(element) > fn(result) ? element : result), this[0]);
};
for clarity
If the array contains strings try this solution
function GetMaxFrequency (array) {
var store = array;
var frequency = []; // array of frequency.
var result; // holds the max frequency element.
for(var v in store) {
var target = store[v];
var numOccurences = $.grep(store, function (elem) {
return elem === target;
}).length;
frequency.push(numOccurences);
}
maxValue = Math.max.apply(this, frequency);
result = store[$.inArray(maxValue,frequency)];
return result;
}
var store = ['ff','cc','cc','ff','ff','ff','ff','ff','ff','yahya','yahya','cc','yahya'];
alert(GetMaxFrequency(store));
A fairly short solution.
function mostCommon(list) {
var keyCounts = {};
var topCount = 0;
var topKey = {};
list.forEach(function(item, val) {
keyCounts[item] = keyCounts[item] + 1 || 1;
if (keyCounts[item] > topCount) {
topKey = item;
topCount = keyCounts[item];
}
});
return topKey;
}
document.write(mostCommon(['AA', 'AA', 'AB', 'AC']))
This solution returns an array of the most appearing numbers in an array, in case multiple numbers appear at the "max" times.
function mode(numbers) {
var counterObj = {};
var max = 0;
var result = [];
for(let num in numbers) {
counterObj[numbers[num]] = (counterObj[numbers[num]] || 0) + 1;
if(counterObj[numbers[num]] >= max) {
max = counterObj[numbers[num]];
}
}
for (let num in counterObj) {
if(counterObj[num] == max) {
result.push(parseInt(num));
}
}
return result;
}

Categories