I have a stepped array of elements that is filled as follows:
class Funnel{
constructor() {
this.funnelContents = [];
this.layer = 0;
}
get content() {
return this.funnelContents;
}
fill(...nums) {
let index, startIndex = 0;
for(let i = 0; i < this.funnelContents.length; i++){
while ((index = this.funnelContents[i].indexOf(' ', startIndex)) > -1 && nums.length > 0) {
this.funnelContents[i][index] = nums.shift();
startIndex = index + 1;
}
}
return nums
.splice(0, 15 - this.funnelContents.reduce((count, row) => count + row.length, 0))
.filter(num => num < 10)
.reduce((arr, num) => {
if (this.funnelContents.length) {
this.funnelContents[this.funnelContents.length - 1] = this.funnelContents[this.funnelContents.length - 1].filter(char => char !== ' ');
if ((this.funnelContents[this.layer] || []).length !== this.funnelContents[this.layer - 1].length + 1) {
this.funnelContents[this.layer] = [...(this.funnelContents[this.layer] || []), num];
} else {
this.layer++;
this.funnelContents[this.layer] = [num];
}
}
else {
this.layer++;
this.funnelContents = [...this.funnelContents, [num]];
}
}, []);
}
toString() {
let str = '', nums = '', spacesCount = 1;
for(let i = 5; i > 0; i--){
str += '\\';
for(let j = 0; j < i; j++) {
if (this.funnelContents[i - 1] !== undefined) {
if (this.funnelContents[i - 1][j] !== undefined) {
nums += this.funnelContents[i - 1][j];
} else {
nums += ' ';
}
} else {
nums += ' ';
}
}
str += nums.split('').join(' ') + '\/\n' + ' '.repeat(spacesCount);
nums = '';
spacesCount++;
}
return str.substring(0, str.length - 6);
}
}
let funnel1 = new Funnel();
let funnel2 = new Funnel();
let funnel3 = new Funnel();
let funnel4 = new Funnel();
let funnel5 = new Funnel();
let funnel6 = new Funnel();
let funnel7 = new Funnel();
funnel1.fill(5,4,3,4,5,6,7,8,9,3,2,4,5,6,7,5,6,7,8); //15 elements will be added, the rest are ignored
funnel2.fill(5,4,3,4,5,6,7,8);
funnel2.fill(9,3,2,4,5,6,7);
funnel3.fill(' ');
funnel3.fill(1,5,7);
funnel4.fill(1,2,3);
funnel4.fill(' ');
funnel4.fill(3,4,5);
funnel5.fill(1);
funnel5.fill(' ', ' ', ' ');
funnel5.fill(8,2,1);
funnel6.fill(' ',' ');
funnel6.fill(1,8,2,1);
funnel7.fill(' ',' ',' ',' ',' ');
funnel7.fill(1,8,2,1);
console.log(funnel1.toString()); // the output is as expected.
console.log(funnel2.toString()); // the same result
console.log(funnel3.toString()); // expected [ [1], [5,7] ] and it really is
console.log(funnel4.toString()); // expected [ [1], [2,3], [3,4,5] ] and it really is
console.log(funnel5.toString()); // expected [ [1], [8,2], [1] ] and it really is
console.log(funnel6.toString()); // expected [ [1], [8,2], [1] ] but got [ [], [1,8], [2], [1] ]
console.log(funnel7.toString()); // nothing is changed
Here you can see that at the very beginning of the function fill
a cycle was written to insert elements that came to the input instead of spaces. I added spaces artificially, in fact, there is another function that adds them. But:
1) For some reason this does not always work, for an array in the example it does not work. With a simpler space search algorithm, it also does not work properly:
for (let i = 0; i < this.funnelContents.length; i++) {
for (let j = 0; j < this.funnelContents[i].length; j++) {
if(this.funnelContents[i][j] === ' '){
this.funnelContents[i][j] = nums.shift();
}
}
}
2) It looks very cumbersome and I would like to do something similar more elegantly. I was thinking of two for
loops to find elements I need, but I still hope that I can implement insertion instead of spaces inside reduce
function.