I have a array where I need to divide equally into person number of chunks.
if there are 100 items in array for 10 persons, 10 chunks to be created with each 10 items
if there are 100 items in array for 9 persons, 9 chunks to be created and each would get 9 items and the extra should be given to first person, second person and so on. which means Person 1 = 10; Person 2, 3, 4 ... would have 9 items
if there are 100 items in array for 11 persons, 11 chunks are to be created with each would get 10 and the extra should be given to first person. which means
Person 1 is 10
Person 2 is 9
Person 3 is 9
Person 4 is 9
Person 5 is 9
Person 6 is 9
Person 7 is 9
Person 8 is 9
Person 9 is 9
Person 10 is 9
Person 11 is 9
I have tried with
Object.defineProperty(Array.prototype, 'chunk', {
value: function(chunkSize) {
var array = this;
return [].concat.apply([],
array.map(function(elem, i) {
return i % chunkSize ? [] : [array.slice(i, i + chunkSize)];
})
);
}
});
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ..., 150, 151].chunk(Math.floor(151 / 31))
but that would gives me an incorrect allocation.
Use the remainder of the division to get the number of slices that need an extra element. Then use the index in the new (chunked) array to determine whether it needs that extra element (i.e. when that index is less than the remainder).
NB: I would not alter the Array prototype. Just make this a plain function.
Implementation:
function partition(arr, length) {
let rest = arr.length % length;
let size = Math.floor(arr.length / length);
let j = 0;
return Array.from({length}, (_, i) => arr.slice(j, j += size + (i < rest)));
}
let data = Array.from({length: 151}, (_,i) => i+1);
let result = partition(data, 31);
console.log(result);
You can use generators to split an array in chunk:
function* chunks(arr, n) {
for (let i = 0; i < arr.length; i += n) {
yield arr.slice(i, i + n);
}
}
let a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ..., 150, 151];
console.log([...chunks(a, Math.floor(151 / 31))]);
Then you can adapt this code to move the last element in first place (if you want first person to be the most empty).
As a side note, you can replace this:
let a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ..., 150, 151];
with this:
let a = [...Array(151).keys()];
Related
What i need to do:
// Return an array containing the second half of an array
// Exclude middle index on odd length arr
My code:
function secondHalf(arr) {
let newArr = [];
for (let i = Math.floor(arr.length / 2); i >= 0; i--) {
newArr.push(arr[i]);
} return newArr;
}
secondHalf([1, 2]);
secondHalf([1]);
The output i'm getting:
1) Problems
secondHalf
should return only the second half the array:
AssertionError: expected [ 2, 1 ] to deeply equal [ 2 ]
+ expected - actual
[
2
- 1
]
at Context.<anonymous> (test/problems-specs.js:72:48)
at processImmediate (node:internal/timers:466:21)
2) Problems
secondHalf
should be the exclusive first half:
AssertionError: expected [ 1 ] to deeply equal []
+ expected - actual
-[
- 1
-]
+[]
at Context.<anonymous> (test/problems-specs.js:75:45)
at processImmediate (node:internal/timers:466:21)
I've tried so many times, and came across methods like .splice() and .slice() but didn't use them because i need to solve it using only loops. What am i doing wrong?
You can use a "normal" for loop with i set to half the length rounded up:
function secondHalf(arr) {
let newArr = [];
for (let i = Math.ceil(arr.length / 2); i < arr.length; i++) {
newArr.push(arr[i]);
}
return newArr;
}
console.log(secondHalf([1, 2, 3, 4, 5, 6, 7]));
console.log(secondHalf([1, 2, 3, 4]));
console.log(secondHalf([1, 2, 3]));
console.log(secondHalf([1, 2]));
console.log(secondHalf([1]));
EDIT: What is happening is that the for loop condition part is divided in three parts:
let i = Math.ceil(arr.length / 2);
i < arr.length;
i++
It is the first part that does all "the magic".
Instead of starting the iteration from 0 we start at half the array length rounded up, meaning if we have an array like:
[1, 2, 3, 4, 5, 6, 7]
| | | | | | |
0 1 2 3 4 5 6
|
we start from here
half the length is 3.5 (7 / 2), and rounded up: 4
Meaning we start iterating from index 4 and onwards:
// this is what is happening at each iteration of the for loop:
// i = 4
newArr.push(arr[4]); // which is the number 5
// i = 5
newArr.push(arr[5]); // which is the number 6
// i = 6
newArr.push(arr[6]); // which is the number 7
// i is not below arr.length anymore, so stop iterating
Does that help a little?
function secondHalf(arr) {
let newArr = []
for (let i = 1; i <= Math.floor(arr.length / 2); i++) {
newArr.push(arr[arr.length-i])
}
return newArr
}
secondHalf([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
Try this brother,
Here Im checking the length of the array first, if length is not divisible by 2 then removing the mid item by adding 1 and if the length is even then considering the second part by dividing the array length.
function secondHalf(array) {
var secArr = [];
let index = 0;
if(array.length % 2 !== 0) {
index = parseInt(array.length / 2) +1;
} else index = array.length /2;
for(let i= index; i<array.length; i++) {
secArr.push(array[i]);
}
return secArr;
}
secondHalf([1,2,3,4,5])
A cleaner approach:
function secondHalf(arr) {
const len = arr.length;
return arr.slice(Math.ceil(len / 2), len);
}
console.log(secondHalf([1, 2, 3, 4, 5, 6]));
console.log(secondHalf([1, 2, 3, 4, 5]));
console.log(secondHalf([1, 2, 3, 4]));
console.log(secondHalf([1]));
Create a function 'calcAverageHumanAge', which accepts an arrays of dog's
ages ('ages'), and does the following things in order:
Calculate the dog age in human years using the following formula: if the dog is
<= 2 years old, humanAge = 2 * dogAge. If the dog is > 2 years old,
humanAge = 16 + dogAge * 4
Exclude all dogs that are less than 18 human years old (which is the same as
keeping dogs that are at least 18 years old)
Calculate the average human age of all adult dogs (you should already know
from other challenges how we calculate averages )
Run the function for both test datasets
Test data:
Data 1: [5, 2, 4, 1, 15, 8, 3]
Data 2: [16, 6, 10, 5, 6, 1, 4]
My solution(idk why wont work):
const calcAverageHumanAge = function (ageList) {
const avgAge = ageList
.map(val => (val <= 2 ? 2 * val : 16 + val * 4))
.fliter(val => val >= 18)
.reduce((acc, val, i, list) => {
return acc + val / list.length;
}, 0);};
You have three issues. Your reduce doesn't return anything is the main problem, but you're also dividing by list.length in each callback which doesn't make any sense (actually it does and I'm dumb), and then you aren't returning anything from the function. You want something like this:
const calcAverageHumanAge = function (ageList) {
const filteredVals = ageList
.map(val => (val <= 2 ? 2 * val : 16 + val * 4))
.filter(val => val >= 18);
return filteredVals.reduce((acc, val) => acc + val) / filteredVals.length;
};
When run on your data:
calcAverageHumanAge([5, 2, 4, 1, 15, 8, 3]); // 44
calcAverageHumanAge([16, 6, 10, 5, 6, 1, 4]); // 47.333
I've found a lot of answers to the question "how to split an array in multiple chunks", but I can't find a way to best repartition the array. For example,
let x = [1,2,3,4,5,6,7,8,9,10,11,12,13];
//#Source https://www.w3resource.com/javascript-exercises/fundamental/javascript-fundamental-exercise-265.php
const chunk = (arr, size) =>
Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
arr.slice(i * size, i * size + size)
);
const n = 10;
console.log(chunk(x,n))
This function gives me two arrays: [1,2,3,4,5,6,7,8,9,10] and [11,12,13]. But I would prefere n to be used as a "max" to obtain [1,2,3,4,5,6,7] and [8,9,10,11,12,13]. This way I would have two arrays of the same size. If it is possible for the selected n, they should be of equal size, otherwise, two arrays with a nearly identical size.
I broke it down into 3 steps.
Compute numChunks, how many chunks you need? E.g. if you have an array of 103 elements and a max size of 10, then you'll need 11 chunks.
Compute minChunkSize, the size of the smaller chunks. E.g. in the above example, the first 7 chunks will have 10 elements, while the other 3 chunks will have 11 elements (710 + 311 = 103).
Compute numSmallChunks, how many small chunks you can have. E.g. 3 in the above example.
Then you just splice the arr accordingly.
let chunk = (arr, maxSize) => {
let numChunks = parseInt((arr.length - 1) / maxSize) + 1;
let minChunkSize = parseInt(arr.length / numChunks);
let numSmallChunks = numChunks * (minChunkSize + 1) - arr.length;
arr = [...arr]; // avoid muckking the input
let arrays = [];
for (let i = 0; i < numChunks; i++)
if (i < numSmallChunks)
arrays.push(arr.splice(0, minChunkSize));
else
arrays.push(arr.splice(0, minChunkSize + 1));
return arrays;
};
let x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
for (let i = 1; i < x.length; i++)
console.log(i, JSON.stringify(chunk(x, i), null, ''));
Note, the other answers result in an unbalanced; e.g. they produce arrays of sizes 4, 4, 4, & 1 when n is 4. Whereas my approach produces arrays of sizes 3, 3, 3, & 4. I guess it's up to the situation which you need, but this is how I interpret the question's "equal chunks".
If you need n to be max, Then calculate size as below.
let x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
const chunk = (arr, max) => {
const size = Math.min(max, Math.ceil(arr.length / 2));
return Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
arr.slice(i * size, i * size + size)
);
};
const n = 10;
console.log(chunk(x, n));
You could slice with a variable size.
1 2 3 4 5 5
6 7 8 9 10 5
11 12 13 14 4
15 16 17 18 4
const
chunk = (array, max) => {
let
length = Math.ceil(array.length / max),
size = Math.ceil(array.length / length);
return Array.from(
{ length },
(_, i) => (
array.length === size * length - length + i && size--,
array.slice(size * i, size * (i + 1))
)
);
}
console.log(chunk([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18], 5).map(a => a.join(' ')));
I am trying to solve this problem but I don't know why I can't pass all test cases. I need some help and explanation, how can I count some array (in this example: variable s) multiple times and not repeat the same elements that I already summed.
Problem description:
Lily has a chocolate bar that she wants to share it with Ron for his
birthday. Each of the squares has an integer on it. She decides to
share a contiguous segment of the bar selected such that the length of
the segment matches Ron's birth month and the sum of the integers on
the squares is equal to his birth day. You must determine how many
ways she can divide the chocolate.
Consider the chocolate bar as an array of squares, s=[2,2,1,3,2].
She wants to find segments summing to Ron's birth day, d=4 with a
length equalling his birth month, m=2. In this case, there are two
segments meeting her criteria: [2,2] and [1,3].
Function Description
Complete the birthday function in the editor below. It should return
an integer denoting the number of ways Lily can divide the chocolate
bar.
birthday has the following parameter(s):
s: an array of integers, the numbers on each of the squares of
chocolate,
d: an integer, Ron's birth day, m: an integer, Ron's birth month
My code:
function birthday(s, d, m) {
let bars = 0;
if (m !== 1) {
s.reduce((acc, val) => (acc+val) === d ? ++bars : bars)
} else {
bars = 1;
}
return bars;
}
Some cases:
s = [2, 5, 1, 3, 4, 4, 3, 5, 1, 1, 2, 1, 4, 1, 3, 3, 4, 2, 1]
d = 18
m = 7
s = [4, 5, 4, 5, 1, 2, 1, 4, 3, 2, 4, 4, 3, 5, 2, 2, 5, 4, 3, 2, 3,
5, 2, 1, 5, 2, 3, 1, 2, 3, 3, 1, 2, 5]
d = 18
m = 6
s = [4, 5, 4, 2, 4, 5, 2, 3, 2, 1, 1, 5, 4]
d = 15
m = 4
My code works with this:
s = [1, 2, 1, 3, 2]
d = 3
m = 2
This can be found on HackerRank > Practice > Algorithms > Implementation
You just have to slice the array with the sliced length of m, and then compare that to d
As slice doc:
The slice() method returns a shallow copy of a portion of an array into a new array object selected from start to end (end not included) where start and end represent the index of items in that array. The original array will not be modified.
For example:
s = [1, 2, 1, 3, 2]
m = 2
d = 3
// We loop through s with index stop at s.length - m + 1 for slice to be in correct range
// Slices:
i=0: [1, 2] -> sum=3 -> res=0+1=1
i=1: [2, 1] -> sum=3 -> res=1+1=2
i=2: [1, 3] -> sum=4 -> do nothing
i=4: [3, 2] -> sum=5 -> do nothing
Below is a worked solution
function birthday(s, d, m) {
let res = 0
const sum = (arr) => arr.reduce((acc, el) => acc + el, 0)
for (let i = 0; i < s.length - m + 1; i++) {
if (sum(s.slice(i, i + m)) === d) {
res++
}
}
return res
}
Whenever you are looping over an array to get the summation or do a mathematical equation on it and you have to remove that specific element that you already calculated, You can use one of these built in function to remove an element from an array using a specific index.
Array.prototype.slice()
&& Array.prototype.splice()
Here's an easy to understand way with nested loops:
function birthday(s, d, m) {
var matches = 0; // Total matches found
// Look at chunks starting a position 0. Last chunk can't be m spots past end of array, so last chunk starts at 1 + s.length - m:
for ( let i=0; i < 1 + s.length - m; i++ ) {
var sum = 0; // What this chunk sums to
// Sum up the values of this chunk:
for ( let j=0; j < m; j++ ) {
sum += s[i+j];
}
if ( sum === d ) { // Does this chunk sum to d?
matches++; // Yes!
}
}
return matches;
}
suppose we have this two array. in some condition, I want to return the index of a second array.
let a = [1, 2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 , 12]
let b = [0, 1, 2, 3 , 4 , 5, 6 , 7 , 8, 9, 10, 11]
if (a[2]) ? return b[2] : return null
why I need this? because I have a month number of the year that starts from 0 to 11. but I need to turn this 1 12 for storing in my database.
sry about the title of this question if someone has a better title I would be glad about changing it.
You could calculate the value by adding 11 and get the remainder value with 12.
function getZeroBasedMonth(n) {
return (n + 11) % 12;
}
console.log(getZeroBasedMonth(1));
console.log(getZeroBasedMonth(12));
For the getting the opposite, just add one.
function getMonth(n) {
return n + 1;
}
console.log(getMonth(0));
console.log(getMonth(11));
Why make this harder than it needs to be? Just add 1 to the value you get from your initial array. Here is, per your comment, 10 years worth of values for the months with a +1 value.
let years = 10;
let months = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
let allYears = [];
for(let i = 0; i < years; i++){
let year = [];
for(let x = 0; x < months.length; x++){
year[x] = months[x] + 1;
}
allYears.push(year);
}
console.log(allYears);