Create a Christmas Tree ASCII art with Python
Learn Python Basics by Creating an ASCII art
ASCII (American Standard Code for Information Interchange) is a set of symbols that in digital texts used in computer systems. And ASCII Arts are the arrangements of ASCII symbols into interesting shapes of any kind.
Creating an ASCII art with a simple Python command
Creating ASCII arts is fun. Just like creating any art piece, we need to become an artist briming with imagination and creativity to create a piece of ASCII art. However, we all have to start off somewhere simple.
For simple, symmetrical shapes like a Christmas Tree, it is simple enough to create manually. With Python, we can write the following code:
print('''
#
###
#####
#######
#########
###########
#############
###############
H
H
H
''')
and get the following ASCII art:
Not bad at all for a start! We can generate a handsome Christmas Tree ASCII art with unique leaves and trunks patterns with only Python’s print() command.
However, if we want a good-looking Christmas Tree, there are things to keep in mind:
- We need to align the top and the trunk on the same spot (column)
- We need layers with increasing leaves from top to bottom of the tree
With those two points alone, we need to make sure to add appropriate number of blank spaces to each line of text. And, for aesthetic purpose, we should also make sure that the trunk is right in the middle of the lowest leaf layer.
Because of this, we need to use the triple quotes to wrap around the ASCII symbols in the print command. The triple quotation marks allow us to print out multiple-line texts and provides us with more convenience than using multiple print() commands. It is also easier to keep track of spaces in each leaf layer this way.
Yet, questions remain: What if…?
- What if we want a bigger (or smaller) Christmas Tree with unique Christmas Star?
- What if we want a Christmas Tree with unique leaf and trunk patterns?
What if we want another tree like the following:
Writing an algorithm to create a Christmas Tree ASCII art with Python
We want to be flexible with our Christmas Tree ASCII art. We want to create our Christmas Trees of different sizes with unique Christmas Stars, leaf, and trunk structures. This sounds very subjective, yet there are rules like a principal blueprint that govern our next-generation Christmas Trees: the star and the trunk must align, the leaves must keep expanding from top to bottom.
Because of these rules, we can write an algorithm for it with Python. But there are things we should consider first:
- We want to be able to change the shape of the star, the tree size, leaf and trunk pattern
From this consideration, we can list variables for our algorithm as the following:
- star_shape : stores the shape of the star
- leaf_shape : stores the shape of the leaves
- trunk_shape : stores the shape of the trunk
- leaf_layer : stores the number of leaf layers
- trunk_height : stores the height of the trunk
The explanation of the algorithm is simple:
The algorithm takes all the values from the variables above, and create a Chrismas Tree with leaf_layer layers of leaves, and with the trunk height of trunk_height. The shape of the star and the pattern of the leaves and the trunk are determined by star_shape, leaf_shape, and trunk_shape, respectively.
For example, if we assign values to the variables as the following code:
#Get star shape
star_shape = "≛"
#Get leaf shape
leaf_shape = "$"
#Get trunk shape
trunk_shape = "▓"
#Get leaf layers
leaf_layer = 8
#Get trunk height
trunk_height = 3
We get:
Notice that the result of the Christmas Tree above is according to the values we assigned to the variables. We have a Christmas Tree with ≛ as a star, $ as leaves, and ▓ as a trunk. There are 8 layers of leaves (including the star) and 3 units of trunk height.
Here is a good time to add a little more detailed explanation of the algorithm. It involves using loops (both for and while loops) and a string method to generate each layer of the leaves, and each section of the trunk.
It also uses logical blocks (if-elif-else) to distinguish the parts of the tree into the star (top), the leaves (middle), and the trunk (bottom). Each layer comprises of odd-number leaves. This is because we need each layer, especially the star at the top and the bottom, to align with the trunk where the trunk and the star will be in the center of all leaf layers.
Ready to see the full code now? Here we go:
#SECTION 1: value assignments
#Get star shape
star_shape = "≛"
#Get leaf shape
leaf_shape = "$"
#Get trunk shape
trunk_shape = "▓"
#Get leaf layers
leaf_layers = 8
#Get trunk height
trunk_height = 3
#SECTION 2: create a list of odd-numbers for each leaf layers
#Each number in this list represents number of leaves in each leaf layer
start_leaf = 1
leaf_list=[]
while start_leaf <= leaf_layers:
leaf_list.append(start_leaf+(start_leaf-1))
start_leaf+=1
#SECTION 3: loops and logical blocks for creating different parts of the trees
for i in range(leaf_layers+trunk_height):
str_l="" #This variable contains leaves in each layer
if i < leaf_layers and i ==0: #Check if the position is at the top
str_sp="" #This variable contains the number of blank spaces to be used in each layer
bsp=0 # This is the iterator controlling the number of blank spaces in each layer
while bsp <(max(leaf_list)-leaf_list[i])/2:
str_sp+=" "
bsp+= 1
for i in range(leaf_list[i]):
str_l+=star_shape
print(str_sp+str_l)
elif i < leaf_layers: #Check if we are still building up leaf layers
str_sp=""
bsp=0
while bsp < (max(leaf_list) - leaf_list[i])/2:
str_sp+=" "
bsp+=1
for i in range(leaf_list[i]):
str_l+=leaf_shape
print(str_sp+str_l)
else: #If the position is lower than the bottom leaf layers, start to build up the trunk
bsp=0
str_sp=""
while bsp < (max(leaf_list)-leaf_list[0])/2:
str_sp+=" "
bsp+=1
print(str_sp+trunk_shape)
SECTION 2
From the code above, pay attention to #SECTION 2. This section is crucial for our aesthetic purpose. A list of odd numbers is created in this section. Each member of this list represents the number of leaves in each layer of our Christmas Tree. For example, if we want to have a Christmas Tree of 8 leaf layers, the leaf_list will contain 8 odd-number members: [1, 3, 5, 7, 9 ,11, 13, 15].
Here, we use a while loop to generate each odd-number. The loop starts with the start_leaf = 1 and end when the value of start_leaf is equal to the number of the assigned leaf_layers which is 8 in this case. We can get an odd number by the expression start_leaf+(start_leaf-1). In this case, if start_leaf =1 (the first iteration), the number will be 1 + (1–1) = 0. After the expression start_leaf+=1, the next odd number will be 2 + (2–1) = 3, and so on.
SECTION 3
In #SECTION 3, we use both for and while loops, including if-elif-else logical blocks.
Although the code in this section looks complex and long, the logic is simple:
- We iterate through each layer of the Christmas Tree from top to bottom (bottom trunk), determine how many leaves and how many blank spaces to add before the leaves in each layer
- then create a line of text completed with the correct number of blank spaces and leaves for each layer, then print those line one by one.
The expression for i in range(leaf_layers+trunk_height): in the main (outer most) for loop tells the code to finish each layer step-by-step, starting from top to bottom. This include all leaf layers and trunk sections as the value in the range() function is the sum of the number of leaf layers and trunk height.
The main for loop’s iterator i controls the number of leaf layers and the number of leaves in each layer, too, since it is also used as the index that
The first if i < leaf_layers and i ==0: conditional statement checks if the code is working on the top most layer (the star) . If yes (True), then use the assigned star symbol to show at the top.
Another set of while and for loop inside the if statement determines the correct number of blank spaces and number of leaves in that layer, whose values are stored as string type in the variables str_sp and str_l, respectively.
Ending each layer, the leaves and spaces are printed out by the command print(str_sp+str_l). The two strings of blank spaces and leaves are simply combined with the + operator.
The expression while bsp <(max(leaf_list)-leaf_list[i])/2: is used to find the right number of blank spaces for each layer of leaves, where leaf_ist[i] is the number of leaves in layer i whose values in this case range from 0–7, representing 8 layers of leaves.
At the last part of #SECTION 3, the else statement block tells the code that now the main iterator i has the value of ≥ the number of leaf layers. This mean we are starting to construct the trunk. So, instead of printing str_sp+str_l, we print str_sp+trunk_shape.
Why don’t we go for either for or while in the loops in this algorithm?
This is the question you may have been asking. It’s a good question! Let’s clear it up.
We use the for loop for fixed number of iterations where we can also utilize its iterator for something else. For example, we use the for loops in this algorithm to iterate through each leaf layers which are 8 in total. The number is already determined via assignment to the variable leaf_layers.
The while loop, on the other hand, is used for conditional iteration where the number of iterations may or may not change based on the conditions of interest. For example, we use the while loop in this case to create a string variable containing the correct number of blank spaces for each leaf layer. The starting statement while bsp < (max(leaf_list) — leaf_list[i])/2: means that keep iterating until the value of bsp ≥ the value of max(leaf_list) — leaf_list[i])/2, where leaf_list[i] is the number of leaves in layer i.
Run the code!
You can copy the code above and paste it in your Jupyter Notebook or any IDE that supports Python and try to run it and see the result for yourself. Read the comments so that you can get a clearer picture of the inner-workings of the code. Try to change the values assigned to the variables to grasp more understanding and adapt the code to create your own version.
Alternatively, you can also download the Jupyter Notebook file and the finished text file from my GitHub repository.
Summary
One can learn a few basic concepts of the Python programming language simply by creating simple symmetrical ASCII art such as the Christmas Tree.
Here, we learn variable assignments, printing, concatenating strings, conditional statements, and both for and while loops. That’s actually quie a lot. There’s actually one additional important technique we learn here, and that is code commenting. Commenting the code allows us to take notes and give short explanations inside the code itself.
Commenting is a very useful technique when we have to change or perform code maintenance in the future, or when we have to work with the other people and they have to understand our codes, or vice versa.
And the most fun of all: we’ve learned how to create a basic form of ASCII art. From now on, the only limits are only our own imaginations!