Reputation: 1165
Inputs: array = [0,0,0,1,1,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0]
and mid_space = 5
Expected Output: array = [0,0,0,0,1,1,0,0,0,0,0,1,1,0,0,0,0,0,1,1,0,0,0,0,0,1,1,0,0,0,0]
Essentially I want to "respace" the ones such that there are mid_space
number of zeroes between them and the remaining zeroes are equally spaced at the front and back.
My existing approach is:
I'm looking for a simpler and more efficient approach without using so much code as I would need to do here.
Any advice?
edit:
To calculate the expected_spacing I first calculate the total number of spaces (23 here), then the remaining spaces after allocating a group of 5 to each set of ones 23 - (5 * 3[which is the number of sets of "11"])
= 8.
Then This means that 8/2 = 4 on each of the start and end of the array.
Upvotes: 1
Views: 89
Reputation: 350760
I would go with a solution that does not perform conversion to string, which comes with a performance impact:
function spread(array, midSpace) {
let splitCount = 0, i = -2;
while ((i = array.indexOf(1, i+2)) != -1) splitCount++;
// Fill the result array with only zeroes
let result = Array(array.length).fill(0);
// Then populate the 1-values at the right spots
for (let i = (array.length - splitCount * (midSpace + 2) + midSpace) >> 1; splitCount; splitCount--, i += midSpace) {
result[i++] = 1;
result[i++] = 1;
}
return result;
}
let input = [0,0,0,1,1,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0];
console.log(String(spread(input, 5)));
In my tests this performed a couple of times faster than the solution that manipulates strings. The script I used for benchmarking is attached.
function spreadTrincot(array, midSpace) {
let splitCount = 0, i = -2;
while ((i = array.indexOf(1, i+2)) != -1) splitCount++;
// Fill the result array with only zeroes
let result = Array(array.length).fill(0);
// Then populate the 1-values at the right spots
for (let i = (array.length - splitCount * (midSpace + 2) + midSpace) >> 1; splitCount; splitCount--, i += midSpace) {
result[i++] = 1;
result[i++] = 1;
}
return result;
}
function spreadGrodzi(v, midSpace) {
const s =
v.join('')
.replace(/0/g,' ').trim() // skip leading/trailing zeros
.replace(/ +/g, '0'.repeat(midSpace)); // replace any groups of zeros
const n = Math.floor((v.length - s.length) / 2); // we assume there is at least one zero to be added, otherwise check for negativeness
const v2 = ('0'.repeat(n) + s + '0'.repeat(v.length - s.length - n)
).split('').map(x => parseInt(x));
return v2;
}
const delay = (ms=10) => new Promise(resolve => setTimeout(resolve, ms));
const asyncLog = msg => Promise.resolve(console.log(msg)).then(delay);
(async () => {
let times = 50000;
let input = [0,0,0,1,1,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0];
input = input.concat(input);
input = input.concat(input);
input = input.concat(input);
input = input.concat(input);
input = input.concat(input); // make input longer.
let result, result2, start, delay;
await asyncLog("input size is " + input.length);
await asyncLog("calling trincot's function...");
start = performance.now();
for (let i = 0; i < times; i++) result = spreadTrincot(input, 5);
delay = performance.now() - start;
await asyncLog("trincot's function finishes in " + delay + "ms");
await asyncLog("calling grodzi's function...");
start = performance.now();
for (let i = 0; i < times; i++) result2 = spreadGrodzi(input, 5);
delay = performance.now() - start;
await asyncLog("grodzi's function finishes in " + delay + "ms");
await asyncLog("Check that outputs are same: " + (result+"" == result2+""));
})();
Upvotes: 2
Reputation: 5703
If it is not about efficiency in terms of perf but in terms of sweating
You can simply manipulate strings
const v = [0,0,0,1,1,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0]
const s =
v.join('')
.replace(/0/g,' ').trim() // skip leading/trailing zeros
.replace(/ +/g, '00000') // replace any groups of zeros
const n = Math.floor((v.length - s.length) / 2) // we assume there is at least one zero to be added, otherwise check for negativeness
const v2 = ('0'.repeat(n) + s + '0'.repeat(v.length - s.length - n)
).split('').map(x => parseInt(x))
console.log('bef', v.join(''))
console.log('aft', v2.join(''))
edit: floored n as spotted by @trincot, thx
Upvotes: 1