Alright, I'm gonna show you how to create a 90 deg christmas tree first and then 45 deg.
1 *
2 ***
3 *****
4 *******
5 *****
6 *******
7 *********
8 ***********
9 *************
10 ***********
11 *************
12 ***************
13 *****************
14 *******************
15 *********************
16 *******************
17 *********************
18 ***********************
19 *************************
20 ***************************
21 *****************************
22 *******************************
23 *****************************
24 *******************************
25 *********************************
26 ***********************************
27 *************************************
28 ***************************************
29 *****************************************
30 *******************************************
31 |||||
32 |||||
33 |||||
34 |||||
35 |||||
1 *
2 ***
3 *****
4 *******
5 *****
6 *******
7 *********
8 ***********
9 *************
10 ***********
11 *************
12 ***************
13 *****************
14 *******************
15 *********************
16 *******************
17 *********************
18 ***********************
19 *************************
20 ***************************
21 *****************************
22 *******************************
23 *****************************
24 *******************************
25 *********************************
26 ***********************************
27 *************************************
28 ***************************************
29 *****************************************
30 *******************************************
31 |||||
32 |||||
33 |||||
34 |||||
35 |||||
Code:
1//* Symbol used to draw the tree
2const character: string = "*";
3
4//* Tier configuration
5const tiers: number[] = [4, 5, 6, 7, 8];
6//* To track how many stars should have in each row
7let currentStars: number = 1;
8
9//* To know how many rows the tree have
10const totalRows = tiers.reduce((acc, cur) => acc + cur, 0); // 30
11//* Need to have for centering each row
12const totalWidth = (2 * totalRows) - 1;
13
14//* Draw tree tiers
15for (let t = 0; t < tiers.length; t++) {
16 const rows = tiers[t];
17
18 for (let r = 0; r < rows; r++) {
19 //* the number of stars in the current row
20 const stars = currentStars;
21 //* has to divide by 2 since there is before and after spaces
22 const spaces = " ".repeat((totalWidth - stars) / 2);
23 console.log(spaces + character.repeat(stars) + spaces);
24 //* increase start by 2 for next row
25 currentStars += 2;
26 }
27
28 //* To ensure there is overlap(tree branches)
29 currentStars -= 4;
30}
31
32//* Draw the trunk
33const trunkHeight = 5;
34const trunkWidth = 5;
35
36for (let i = 0; i < trunkHeight; i++) {
37 const trunkSpace = " ".repeat((totalWidth - trunkWidth) / 2);
38 console.log(trunkSpace + "|".repeat(trunkWidth) + trunkSpace)
39}
1//* Symbol used to draw the tree
2const character: string = "*";
3
4//* Tier configuration
5const tiers: number[] = [4, 5, 6, 7, 8];
6//* To track how many stars should have in each row
7let currentStars: number = 1;
8
9//* To know how many rows the tree have
10const totalRows = tiers.reduce((acc, cur) => acc + cur, 0); // 30
11//* Need to have for centering each row
12const totalWidth = (2 * totalRows) - 1;
13
14//* Draw tree tiers
15for (let t = 0; t < tiers.length; t++) {
16 const rows = tiers[t];
17
18 for (let r = 0; r < rows; r++) {
19 //* the number of stars in the current row
20 const stars = currentStars;
21 //* has to divide by 2 since there is before and after spaces
22 const spaces = " ".repeat((totalWidth - stars) / 2);
23 console.log(spaces + character.repeat(stars) + spaces);
24 //* increase start by 2 for next row
25 currentStars += 2;
26 }
27
28 //* To ensure there is overlap(tree branches)
29 currentStars -= 4;
30}
31
32//* Draw the trunk
33const trunkHeight = 5;
34const trunkWidth = 5;
35
36for (let i = 0; i < trunkHeight; i++) {
37 const trunkSpace = " ".repeat((totalWidth - trunkWidth) / 2);
38 console.log(trunkSpace + "|".repeat(trunkWidth) + trunkSpace)
39}
How I approach:
As you can see in the picture, the Christmas tree has 5 tiers.
- Each tier has one more row than the previous one. For example, Tier 1 has 4 rows, Tier 2 has 5 rows..
- The number of stars increases by 2 on each row.
- The first row of a new tier has 4 stars less than the last row of the previous tier. This makes to ensure there is overlap between each tier.
Implementation:
First, I choose this character *
to draw the tree.
Then, I create an array tiers which tells how many rows each tier has.
For example, the first tier has 4 rows, the second has 5 rows, etc.
I use currentStars to keep track of how many stars should be in each row.
It starts from 1 and increases by 2 for every new row.
To center all rows of the tree properly, I need to calculate how wide the bottom row will be.
That’s why I calculate totalRows, which is the total number of all rows from all tiers.
Since the number of stars grows like: 1, 3, 5, 7, …, this is an arithmetic pattern.
So the number of stars in the last row is (2 * totalRows - 1)
.
That’s how I get totalWidth. I use this width to center every row.
Draw the tree:
I loop through each tier one by one.
Inside each tier, I loop again for each row.
For each row:
- I print the correct number of stars (using currentStars)
- I also calculate the number of spaces needed to center the stars. This is done by:
(totalWidth - currentStars) / 2
- This calculates how many spaces to add before and after the stars to center them perfectly.
- The tree looks balanced and straight down, like a normal Christmas tree.
Then I print the row: spaces + stars + spaces.
After printing a row, I increase currentStars by 2.
After finishing one tier, I reduce currentStars by 4.
This small step makes the next tier connect to the previous one.
It creates the tree’s natural overlapping branch effect.
I repeat this process until all tiers are done.
Draw the trunk:
Once the tree is finished, I draw the trunk.
From the picture, I see the trunk is 5 characters wide and 5 lines tall.
I center the trunk the same way as I centered the tree rows.
I calculate the space on both sides using: (totalWidth - trunkWidth) / 2
Then I print the trunk using the pipe character |
, repeating this 5 times for height.
Diagonal:
To create a diagonal shape, we need to add extra spaces using diagonalOffset from the left to align it like /.
This gives the early rows has the most extra spaces, pushing them far to the right and the rest rows will shift to the left.
To do this, you need to add more spaces before the stars at first and decrease it each time.
diagonalOffset starts big, so early rows are more right, then gradually shift left.
We’re not adding spaces after the stars because we only care about shifting everything to the right.
Then, we decrease diagonalOffset in each row so the next row moves slightly back to the left
for the trunk we still uses diagonalOffset to match the tree’s diagonal shift. For the trunk to look good in output, i will change with \
Code:
1//* Symbol used to draw the tree
2const character: string = "*";
3
4//* Tier configuration
5const tiers: number[] = [4, 5, 6, 7, 8];
6//* To track how many stars should have in each row
7let currentStars: number = 1;
8
9//* To know how many rows the tree have
10const totalRows = tiers.reduce((acc, cur) => acc + cur, 0);
11//* Need to have for centering each row
12const totalWidth = (2 * totalRows) - 1;
13
14let diagonalOffset = totalRows
15
16//* Draw tree tiers
17for (let t = 0; t < tiers.length; t++) {
18 const rows = tiers[t];
19
20 for (let r = 0; r < rows; r++) {
21 //* the number of stars in the current row
22 const stars = currentStars;
23 //* has to divide by 2 since there is before and after spaces
24 const spaces = " ".repeat((totalWidth - stars) / 2 + diagonalOffset);
25 console.log(spaces + character.repeat(stars));
26 //* increase start by 2 for next row
27 currentStars += 2;
28 diagonalOffset--
29 }
30
31 //* To ensure there is overlap(tree branches)
32 currentStars -= 4;
33}
34
35//* Draw the trunk
36const trunkHeight = 5;
37const trunkWidth = 5;
38
39for (let i = 0; i < trunkHeight; i++) {
40 const trunkSpace = " ".repeat((totalWidth - trunkWidth) / 2 + diagonalOffset);
41 console.log(trunkSpace + "/".repeat(trunkWidth))
42 diagonalOffset--
43}
1//* Symbol used to draw the tree
2const character: string = "*";
3
4//* Tier configuration
5const tiers: number[] = [4, 5, 6, 7, 8];
6//* To track how many stars should have in each row
7let currentStars: number = 1;
8
9//* To know how many rows the tree have
10const totalRows = tiers.reduce((acc, cur) => acc + cur, 0);
11//* Need to have for centering each row
12const totalWidth = (2 * totalRows) - 1;
13
14let diagonalOffset = totalRows
15
16//* Draw tree tiers
17for (let t = 0; t < tiers.length; t++) {
18 const rows = tiers[t];
19
20 for (let r = 0; r < rows; r++) {
21 //* the number of stars in the current row
22 const stars = currentStars;
23 //* has to divide by 2 since there is before and after spaces
24 const spaces = " ".repeat((totalWidth - stars) / 2 + diagonalOffset);
25 console.log(spaces + character.repeat(stars));
26 //* increase start by 2 for next row
27 currentStars += 2;
28 diagonalOffset--
29 }
30
31 //* To ensure there is overlap(tree branches)
32 currentStars -= 4;
33}
34
35//* Draw the trunk
36const trunkHeight = 5;
37const trunkWidth = 5;
38
39for (let i = 0; i < trunkHeight; i++) {
40 const trunkSpace = " ".repeat((totalWidth - trunkWidth) / 2 + diagonalOffset);
41 console.log(trunkSpace + "/".repeat(trunkWidth))
42 diagonalOffset--
43}
Hope it helps 😊 And the output should look like this:
1 *
2 ***
3 *****
4 *******
5 *****
6 *******
7 *********
8 ***********
9 *************
10 ***********
11 *************
12 ***************
13 *****************
14 *******************
15 *********************
16 *******************
17 *********************
18 ***********************
19 *************************
20 ***************************
21 *****************************
22 *******************************
23 *****************************
24 *******************************
25 *********************************
26 ***********************************
27 *************************************
28 ***************************************
29 *****************************************
30 *******************************************
31 /////
32 /////
33 /////
34 /////
35 /////
1 *
2 ***
3 *****
4 *******
5 *****
6 *******
7 *********
8 ***********
9 *************
10 ***********
11 *************
12 ***************
13 *****************
14 *******************
15 *********************
16 *******************
17 *********************
18 ***********************
19 *************************
20 ***************************
21 *****************************
22 *******************************
23 *****************************
24 *******************************
25 *********************************
26 ***********************************
27 *************************************
28 ***************************************
29 *****************************************
30 *******************************************
31 /////
32 /////
33 /////
34 /////
35 /////