Solution to challenge #10 of AdventJS 2023
Solution to the previous challenge
Solution to the next challenge
Challenge Description
What an idea Sam Elfman has had! He wants to offer a service that creates a customized Christmas tree ๐ in a matter of seconds.
To create it, we are given a string to form the tree and a number that indicates its height.
Each character of the string represents an ornament of the tree, and we use them cyclically until we reach the indicated height. At least, they will always pass us one.
We must return a multiline string with the Christmas tree made with the ornaments, the indicated height plus a final line with the trunk formed by the character 
in the center and, finally, a new line \n
.
For example, if we receive the string "123" and the number 4
as height, we would have to build this tree:
1
2 3
1 2 3
1 2 3 1

If we receive the string *@o
and the number 3
, the tree we should return is:
*
@ o
* @ o

Note:
The tree should always be centered, for that reason add blank spaces to the left of each line.
Create spaces only to the left of each line of the tree. Do not leave blank spaces to the right.
The ornaments have a white space between them for separation.
Analysis
And we're back to drawing! This time it's Christmas trees, which we must draw using the strings passed as parameters and sizing them as indicated.
Input
Ornaments (
ornaments
): A string containing the character sequence that will fill the tree.Height (
height
): The height and maximum width of the tree.
Output
 A string with the tree's drawing.
Considerations
We must add spaces at the beginning to give it the shape of a Christmas tree.
At the end, we must insert a line break.
Solution
A simple way to complete the challenge is to calculate the total number of characters required, for which we can use mathematics. Once we have this, we can iterate and fill each row of the tree.
Code
function createChristmasTree(ornaments, height) {
let tree = "";
const totalOrnaments = (height * (height + 1)) / 2;
const allOrnaments = ornaments.repeat(totalOrnaments);
let lastIndex = 0;
for (let i = 1; i <= height; i += 1) {
const spaces = " ".repeat(height  i);
const ornamentRow = allOrnaments
.slice(lastIndex, lastIndex + i)
.split("")
.join(" ");
tree += spaces + ornamentRow + "\n";
lastIndex += i;
}
tree += "".padStart(height, " ") + "\n";
return tree;
}
Community Solutions
Solution by iswilljr:
function createChristmasTree(ornaments, height) {
let result = ''
const spaces = ' '.repeat(height  1)
const ornamentsArray = [...ornaments.repeat(height)].join(' ')
let currentPosition = 0
for (const index of new Array(height).keys()) {
const length = index + 1
const total = currentPosition + length
result +=
spaces.slice(index) +
ornamentsArray.slice(currentPosition * 2, total * 2  1) +
'\n'
currentPosition = total % ornaments.length
}
return result + spaces + '\n'
}
Solution by yasai:
function createChristmasTree(ornaments, height) {
let tree = "";
let count = 0;
// pyramid
for (let i = 0; i < height; i++) {
let line = "";
// spaces
line += " ".repeat(height  i  1);
// ornaments
for (let j = 0; j < i + 1; j++) {
let dec = ornaments[count];
count++;
if (count == ornaments.length) count = 0;
if (j == i) {
line += `${dec}`;
break;
}
line += `${dec} `;
}
// add to the tree
tree += line + "\n";
}
// trunk
tree += " ".repeat(height  1) + "\n";
return tree;
}
And that was the challenge for December 10th and its solutions. Give it a like if you enjoyed the challenge or the solution! Do you have an alternative solution? Leave it in the comments!