Reset counter when not in range and sum progression - javascript

I have an arrays of numbers, and specified range if sequence continues (range rule was met between two numbers) then i add value to result and increase counter by one, else i reset the counter and add nothing to result on this step. Better show in an example:
const numbers = [1, 4, 5, 6, 7, 33, 44, 46]; // they are always going to be from smallest to bigger
const progress = [0, 10, 20, 30, 40, 50, 60]; // 70, 80, etc
let res = 0;
for (let i = 1, j = 0; i < numbers.length; i++) {
const range = numbers[i] - numbers[i - 1];
if (range <= 5) {
j += 1;
res += progress[j];
} else {
j = 0;
}
}
res; // 110
Is there better way to approach this problem?

Well, by looking at your code & the explanation you gave, I think you have incremented 'j' before you added progress for 'j'. that portion should be like following...
if (range <= 5) {
res += progress[j];
j += 1;
}
You have asked for a better approach. But it would help if you specified from which perspective/scenario you are looking for a better approach.

you can do the same with reduce method
const numbers = [1, 4, 5, 6, 7, 33, 44, 46]; // they are always going to be from smallest to bigger
const progress = [0, 10, 20, 30, 40, 50, 60]; // 70, 80, etc
let resp = 0;
const result = numbers.reduce((acc, rec, i, arr) => {
if (rec - arr[i - 1] <= 5) {
resp += 1;
acc = acc + progress[resp];
return acc;
}
resp = 0;
return acc;
}, 0);
result;
You can read more about reduce here
Hope it answers your question.
Happy coding!

Related

How can I sum array index values?

I am new to Javascript and at the moment I'm learning how "arrays" are used.
In my code below I have 12 numbers held by an array variable. Next, the for loop is iterating over the indexes to check which values have 2 or more digits, the while-loop then summarizes the digits (e.g. value '130' at index 8, will be 1+3+0=4).
Final step..and also where I'm stuck:
I need to sum up all the "new" index values and return the result in a variable.
With the numbers provided in the code, the result would be '50'.
Anyone have clue on how to do this? I've tried the conventional for-loop with sum += array[i], but it doesn't work.
var arrChars = [4, 2, 14, 9, 0, 8, 2, 4, 130, 65, 0, 1];
for (var i = 0; i < arrChars.length; i++) {
var digsum = 0;
while (arrChars[i] > 0) {
digsum += arrChars[i] % 10;
arrChars[i] = Math.floor(arrChars[i] / 10);
}
var sum = 0; // this last part won't work and I just get "nan", 12 times
for (var j = 0; j < arrChars.length; j++) {
sum += parseInt(digsum[j]);
}
console.log(sum); // desired output should be '50'
}
Move digsum outside and it will contain the sum of every number in it:
var arrChars = [4, 2, 14, 9, 0, 8, 2, 4, 130, 65, 0, 1];
var digsum = 0;
for (var i = 0; i < arrChars.length; i++) {
while (arrChars[i] > 0) {
digsum += arrChars[i] % 10;
arrChars[i] = Math.floor(arrChars[i] / 10);
}
}
console.log(digsum); // desired output should be '50'
I'd make this easy and just flatten the array of numbers into a string of digits, split that into an array of single digits, and add them together:
var arrChars = [4, 2, 14, 9, 0, 8, 2, 4, 130, 65, 0, 1];
console.log([...arrChars.join('')].reduce((agg, cur) => agg += +cur, 0));

JS Array Interview Question - Split Array

I was given this problem at one of my interviews and was told I have 20 minutes to solve it. This is the answer I came up with ( 2 versions ). Can you let me know which version you prefer and why, and if you have a better idea of how to solve it (less complex, less memory usage, etc.) Please share.
Problem: You have an array of random numbers that range from 0 to 100 elements.
Write a function that will split this array into several arrays, each containing elements in the following range: (0-10],(10-20],(20-30], etc up to a 100].
Write a function that outputs these arrays in a form of a simple graph, where each delimiter represents a single value in the array.
Array = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55,
65, 42, 99, 4];
Desired outcome:
5 Elements in array: ***** - 1,5,6,3,4
3 Elements in array: *** - 10,12,11
2 Elements in array: ** - 22,21
No Elements in array.
2 Elements in array: ** - 45,42
3 Elements in array: *** - 52,51,55
2 Elements in array: ** - 64,65
1 Elements in array: * - 71
No Elements in array.
2 Elements in array: ** - 95,99
// Version 1
arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];
const splitArray = (inputArray, range) => {
const newArray = [];
do {
let tempArray = [];
tempArray = inputArray.filter((item) => {
if (item >= range && item < range + 10) return item;
});
range += 10;
newArray.push(tempArray);
} while (range + 10 <= 100);
return newArray;
};
const printArrays = (array, delimiter) => {
let toPrint = "";
for (index in array) {
let stars = array[index].length;
let string = "";
for (let i = stars; i > 0; i--) {
string += delimiter;
}
toPrint += stars
? `${stars} Elements in array: ${string} - ${array[index]} \n`
: "No Elements in array. \n";
}
return toPrint;
};
console.log(printArrays(splitArray(arr, 0), "*"));
// Version 2
arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];
const getArrays = (inputArray) => {
const newArray = [];
let min = 0;
let max = 10;
do {
const tempArray = [];
for (i in arr) {
let val = arr[i];
val >= min && val < max ? tempArray.push(val) : "";
}
min += 10;
max += 10;
newArray.push(tempArray);
} while (max <= 100);
return newArray;
};
const printArrays = (array, delimiter) => {
for (index in array) {
let stars = array[index].length;
let string = "";
for (let i = stars; i > 0; i--) {
string += delimiter;
}
console.log(
stars ? `${stars} Elements in array: ${string} - ${array[index]}` : "No Elements in array."
);
}
};
printArrays(getArrays(arr), "^");
Both approaches have moderate issues.
The first approach does
let tempArray = [];
tempArray = inputArray.filter((item) => {
if (item >= range && item < range + 10) return item;
});
Better to just declare the tempArray as the filtered array to begin with.
const tempArray = inputArray.filter(...
Also, return item is suspicious inside a filter - all the filter callback cares about is whether its return value is truthy or falsey. Returning the array item when you actually want to indicate that the value should be included in the output is a common mistake. It happens not to be a problem here because 0 isn't a possibility, but it's still confusing. A better choice would be to do
const tempArray = inputArray.filter(
item => item >= range && item < range + 10
);
(and maybe rename range to startOfRange)
Both of your approaches are also iterating through the entire input array multiple times (once for each range), which seems a bit wasteful - better to iterate through the input once.
Your second approach uses for (i in arr), and both approaches are doing for (index in array). This is a bad idea, and since you don't actually care about the index you're iterating over, it'd make sense to use for..of loops instead.
I think a better looking approach that iterates through the input just once would be:
const arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];
const getArrays = (inputArray) => {
const grouped = {};
for (let i = 0; i < 100; i += 10) {
grouped[i] = [];
}
for (const item of inputArray) {
const rangeProp = Math.floor(item / 10) * 10;
grouped[rangeProp].push(item);
}
return Object.values(grouped);
};
const printArrays = (groupedArrays, delimiter) => {
for (const array of groupedArrays) {
const stars = delimiter.repeat(array.length);
console.log(
stars
? `${array.length} Elements in array: ${stars} - ${array.join(',')}`
: "No Elements in array."
);
}
};
printArrays(getArrays(arr), "*");
I will do that this way :
This approach is simple: it retrieves the values one by one and adds them to the array corresponding to their range.
const arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];
let ranges = arr.reduce((a,x)=>
{
let range = (x/10)|0 // get range start value 0 to 9
a[range] ??= [] // create the array of if it does not already exist
a[range].push(x)
return a
},{})
console.log('ranges=', ranges ) // so that noobs can visualize this result
for (let r = 0; r < 10; r++ )
{
if (!ranges[r])
document.write('No Elements in array.<br>')
else
{
let count = ranges[r].length
document.write(`${count} Elements in array: ${'*'.repeat(count)} - ${ranges[r].join(',')}<br>`)
}
}
.as-console-wrapper {max-height: 100% !important; width:20%; top: 0;
margin-left: 80%; }
.as-console-row::after {display: none !important;}
range = (x/10)|0 // get range start value 0 to 9
example in case of x = 25 -> 25/10 give 2.5 and 2.5 | 0 give 2 -> integer part value of 2.5
| is the OR boolean operator, work only on integers values so it return an interger
??= is Logical nullish assignment

I need to print out the 4 largest values and sum them up in JavaScript

My code only prints the largest one, but I need to have the 4 largest numbers displayed and to be summed up.
let sizes = [3, 6, 2, 56, 32, 5, 89, 32];
let largest = sizes[0];
for (let x = 0; x < sizes.length; x++) {
if (largest < sizes[x] ) {
largest = sizes[x];
}
}
console.log(largest);;
Please use this code.
let sizes = [3, 6, 2, 56, 32, 5, 89, 32];
sizes.sort(function(a, b) { return b - a });
console.log(sizes.slice(0, 4).join(' '));
console.log(sizes.slice(0, 4).reduce((total, num) => total + num));
One method you can use is to sort your elements first, and then simply print out the first 4 elements:
sizes(function(a, b) {
return a - b;
});
console.log(sizes[0])
console.log(sizes[1])
console.log(sizes[2])
console.log(sizes[3])
There are easy solutions (sorting the array O(n log(n))) and there are performant solutions (O(n)) like:
let sizes = [3, 6, 2, 56, 32, 5, 89, 32];
let largest = sizes.slice(0, 4).sort((lhs, rhs) => rhs - lhs);
for (let x = 4; x < sizes.length; x++) {
if (largest[3] < sizes[x]) {
largest[3] = sizes[x];
largest = largest.sort((lhs, rhs) => rhs - lhs);
}
}
console.log(largest);
you can do that...
const
sizes = [3, 6, 2, 56, 32, 5, 89, 32]
, sumLargest = sizes.reduce((lg,x)=>
{
if (lg.length < 4) lg.push(x)
else
{
let min = Math.min(...lg)
if (x>min) lg[lg.indexOf(min)] = x
}
return lg
},[]).reduce((a,b)=>a+b,0)
console.log('sumLargest = ', JSON.stringify(sumLargest ))

How many Odd and Even number are the in a array

I have created an Array with some numbers.
I want to find out how many even, and how many odd numbers it is in
this Array. I have to print it out like this: (this is just an example)
Even number: 6
Odd number: 7
I need to make a loop that count up how many it is off even and odd numbers.
This is what I have so far
<script>
window.onload = run;
var tall = [5,10,15,20,25,30,35,40,45,50];
function run() {
tall = [5,10,15,20,25,30,35,40,45,50];
liste(tall);
}
function liste(arr) {
var sumOdd = 0; // Odd 1, 3, 5 etc..
var sumPar = 0; // Even 2, 4, 6 etc..
for(var i = 0; i < arr.length; i++) {
if(arr[i] % 2 === 0) {
sumPar += arr.length;
}
else {
sumOdd += arr.length;
} // Even numbers // Odd numbers
document.getElementById("print").innerHTML = "Partall: " + sumPar + "<br />" + "Oddetall: " + sumOdd;
}
}
}
</script>
Its something that is wrong here, and I dont know what.
You could iterate with Array#reduce and count only the odds. For the rest just take the difference of the length of the array and the odds.
var tall = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50],
odd = tall.reduce(function (r, a) { return r + a % 2; }, 0),
even = tall.length - odd;
console.log('odd', odd);
console.log('even', even);
You were adding arr.length which is the array length. Instead you should simply increment the number
var tall = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50];
liste(tall);
function liste(arr) {
var sumOdd = 0;
var sumPar = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] % 2 === 0) {
sumPar++;
} else {
sumOdd++;
}
}
console.log("Odd : " + sumOdd);
console.log("Par : " + sumPar);
}
You always add the complete Length of the array to your variable
Try this instead of sumPar += arr.length;:
sumPar++;

How to push multiples of a number to array?

How would one push multiples of a number to an array? For example, if the input is (6), I want to create an array that holds [6, 12, 18, 24, 30, 36, etc...]
The most intuitive method to me does not work.
for (var i = 0; i < 10; i++) {
firstArray.push(arr[0] *= 2);
}
This multiplies the number that comes before it by 2, causing an exponential growth. [14, 28, 56, 112, 224, 448, 896, 1792, etc.]
How would one achieve this?
Problem:
The problem in the code, as commented by Pranav is the use of multiplication by two in the for loop.
Using i iterator index can solve the problem.
firstArray.push(6 * (i + 1));
As i is starting from 0, i + 1 will give the number which is 1-based.
Another Approach:
First add the number
var num = 6,
arr = [num];
Then add the number which is double of the previous in the array.
for (var i = 1; i < 10; i++) {
arr.push(arr[i - 1] + num);
}
var arr = [6];
for (var i = 1; i < 10; i++) {
arr.push(arr[i - 1] + arr[0]);
}
console.log(arr);
The same thing can also be done in single line using for loop.
var arr = [];
for (let i = 0, num = 6; i < 10; i++, num += 6) {
arr.push(num);
}
console.log(arr);
You can use map:
function multiplyArrayElement(num) {
return num * 2;
}
numbers = [6, 12, 18, 24, 30, 36];
newArray = numbers.map(multiplyArrayElement);
https://jsfiddle.net/25c4ff6y/
It's cleaner to use Array.from. Just beware of its browser support.
Array.from({length: 10},(v,i) => (i + 1) * 6)
try this one
for (var i = 0; i < 10; i++) {
firstArray.push(arr[0] * (i+1));
}
var arr = [];
var x = 6; //Your desired input number
var z;
for(var i=1;i<10;i++){
z = (x*i);
arr.push(z);
}
console.log(arr);
"One line" solution with Array.fill and Array.map functions:
var num = 6;
var arr = new Array(10).fill(0).map(function(v, k){ return num *(k + 1); });
console.log(arr); // [6, 12, 18, 24, 30, 36, 42, 48, 54, 60]

Categories