This assignment will be closed on February 13, 2026 (23:59:59).
You must be authenticated to submit your files

Practical Exam 1 CSC_1F001, Groups 1-5, 10:15-12:15

N. Aubrun & G. Pogudin

Objectives

What we will evaluate today: Everything!

Setup: Before You Start

Launch Spyder (open a terminal, then type spyder and press Enter). If you see a “Spyder update” message, just click OK and ignore it.

Before you start: create a new project, called PracticalExam_1 (using “New Project” from the “Projects” menu). This will ensure that files from previous and future weeks do not get mixed up together.

Now create a new file named pixel_art.py. This is the file in which you will be writing your code today.

Introduction

In today’s practical exam, you will learn to manipulate minimalist ASCII pictures — simple images made only of spaces ' ' and hashes '#'.
These pictures are stored in plain text files, where each line represents a single horizontal row of pixels.

Data files

Before you start, you need to download the following data files from Moodle: integers1.txt, integers2.txt, invader.txt, pac_man.txt, frog.txt, small_art.txt, cat.txt, and pumpkin.txt. Save them to in your PracticalExam_1 project directory.

Check and make sure that all files have appeared in your PracticalExam_1 project in Spyder.

Part 1: Run-length encoding

We first consider simple images made only of spaces ' ' and hashes '#'. In this part your main task will be to encode and decode such pictures by converting them between:

  • a visual representation with ' ' and '#', and
  • a numerical representation with integers.

We want to encode a picture line by line, so that every line is coded as a sequence of integers obtained by gathering blocks of identical consecutive symbols starting with spaces. For instance the line ' # # ### ' will be coded by the integers 3 1 2 1 4 3 1. If the string starts with #, the first integer will be 0. The remaining integers will always be positive. For example '## #' will be encoded by 0 2 3 1.

This process is known as run-length encoding — a simple and efficient compression method that represents consecutive identical symbols by their count rather than by repetition. It is often used in image compression (for example in some bitmap or fax file formats) because it significantly reduces the size of images that contain large uniform regions.

Upload form is only available when connected

Exercise 1: Converting a string of digits into a list

To begin we define a function to convert a string of digital characters separated by spaces into a list of numbers. Write a new function run_length_line which takes as input a string representing a series of numerical values, separated by spaces, and returns the list of these numerical values as integers.

Copy the following function stub into your file and complete it:

def run_length_line(string):
    """
    Converts a space-separated string of integers into a list of integers.
    """
    pass # remove this line and replace with your own code

Testing

Now test your code by doing this in the console:

In [1]: run_length_line("3 2 1")
Out[1]: [3, 2, 1]

In [2]: run_length_line("   20 1 1    2")
Out[2]: [20, 1, 1, 2]

Note: It is important to test your function in the console as there is no grader feedback.

Now take a moment to upload your pixel_art.py file to the moodle assignment corresponding to this exam.

(You can upload pixel_art.py several times, but only your final upload will be graded - don’t wait until the last moment to upload a preliminary version, in case you miss the cut-off!)

Exercise 2: Decoding a run-length line

Implement and test the function decoding_run_length, that converts a list of non-negative integers into a string of alternating blocks (spaces then hashes). Note that, if the list starts with 0, the string should start with a hash.

Copy the following function stub into your file and complete it:

def decoding_run_length(integers_list):
    """
    Converts a list of integers into a string made of alternating
    blocks of spaces and hashes, starting with spaces.
    """
    pass # remove this line and replace with your own code

Testing

Now test your code by doing this in the console:

In [3]: decoding_run_length([3, 1, 2, 1, 4, 3, 1])
Out[3]: '   #  #    ### '

In [4]: decoding_run_length([0, 2, 1])
Out[4]: '## '

Hint: you can concatenate strings in Python using the + operator. For example:

In [5]: 'a' + 'b'
Out[5]: 'ab'

We also remind that you can check if a number is even or odd by computing the remainder of its division by 2 with a % 2.

Now take a moment to upload your pixel_art.py file to the moodle assignment corresponding to this exam.

(You can upload pixel_art.py several times, but only your final upload will be graded - don’t wait until the last moment to upload a preliminary version, in case you miss the cut-off!)

Exercise 3: From file of digits to pixel art!

Implement and test the function integers_to_pixel_art, that given a file of integer lines, write the corresponding picture into the target file.

Copy the following function stub into your file and complete it:

def integers_to_pixel_art(infilename, outfilename):
    """
    Reads a file with space-separated integers and 
    writes the corresponding pixel art using 
    alternating blocks of spaces and hashes.
    """
    pass # remove this line and replace with your own code

Using the functions you have written for the two previous exercises may be a very good idea.

Testing

Now test your code by doing this in the console:

In [6]: integers_to_pixel_art("integers1.txt", "pixel_art1.txt")

In [7]: integers_to_pixel_art("integers2.txt", "pixel_art2.txt")

You can open the produced files pixel_art1.txt and pixel_art2.txt directly in Spyder. The file pixel_art1.txt should contain this:

               
    #     #    
     #   #     
    #######    
   ## ### ##   
  ###########  
  # ####### #  
  # #     # #  
     ## ##     
               

while pixel_art2.txt should contain that:

              # # # # #                                              
          # #           # #                                          
        #                   #                                        
      #             #         #                                      
      #                       #                                      
    #                     # #                                        
    #               # # #                 # # #     # # #     # # #  
    #         # # #                       #   #     #   #     #   #  
    #               # # #                 # # #     # # #     # # #  
    #                     # #                                        
      #                       #                                      
      #                       #                                      
        #                   #                                        
          # #           # #                                          
              # # # # #                                              

Now take a moment to upload your pixel_art.py file to the moodle assignment corresponding to this exam.

(You can upload pixel_art.py several times, but only your final upload will be graded - don’t wait until the last moment to upload a preliminary version, in case you miss the cut-off!)

Exercise 4: Converting a line of symbols into a list of integers

Implement and test the function pattern_to_run_length, that converts a string of alternating blocks (spaces then hashes) into the corresponding list of integers where the first integer is allowed to be zero (if the string starts with #) and all others must be positive.

Copy the following function stub into your file and complete it:

def pattern_to_run_length(line):
    """
    Converts a string made of alternating blocks of 
    spaces and hashes, starting with spaces,
    into a list of integers representing 
    the lengths of these consecutive blocks.
    """
    pass # remove this line and replace with your own code

Testing

Now test your code by doing this in the console:

In [8]: pattern_to_run_length('   #  #    ### ')
Out[8]: [3, 1, 2, 1, 4, 3, 1]

In [9]: pattern_to_run_length(' ##')
Out[9]: [1, 2]

In [10]: pattern_to_run_length('### ##')
Out[10]: [0, 3, 1, 2]

Now take a moment to upload your pixel_art.py file to the moodle assignment corresponding to this exam.

(You can upload pixel_art.py several times, but only your final upload will be graded - don’t wait until the last moment to upload a preliminary version, in case you miss the cut-off!)

Exercise 5: Integer representation of a pixel art

Implement and test the function pixel_art_to_run_length, that converts a picture made of spaces and hashes into its run-length encoded integer representation.

Copy the following function stub into your file and complete it:

def pixel_art_to_run_length(infilename, outfilename):
    """
    Reads a picture file made of spaces ' ' and hashes '#' and 
    converts each line of that picture into a line of integers 
    representing the run lengths of consecutive blocks of characters. 
    Then writes those integer sequences into an output file.
    """
    pass # remove this line and replace with your own code

Hint: The lines you read from file will contain the endline caracter '\n' at the end. You can remove it by s.strip('\n').

Testing

Now test your code by doing this in the console:

In [11]: pixel_art_to_run_length("pixel_art1.txt", "runlength1.txt")

In [12]: pixel_art_to_run_length("pixel_art2.txt", "runlength2.txt")

Alternatively, if you did not succeed in producing the files picture1.txt and picture2.txt you can use invader.txt and pac_man.txt as follows:

In [13]: pixel_art_to_run_length("invader.txt", "runlength1.txt")

In [14]: pixel_art_to_run_length("pac_man.txt", "runlength2.txt")

You can open the produced files runlength1.txt and runlength2.txt directly in Spyder. As expected they should be the same as integers1.txt and integers2.txt. In details the file runlength1.txt should contain this:

15
4 1 5 1 4
5 1 3 1 5
4 7 4
3 2 1 3 1 2 3
2 11 2
2 1 1 7 1 1 2
2 1 1 1 5 1 1 1 2
5 2 1 2 5
15

while runlength2.txt should contain that:

14 1 1 1 1 1 1 1 1 1 46
10 1 1 1 11 1 1 1 42
8 1 19 1 40
6 1 13 1 9 1 38
6 1 23 1 38
4 1 21 1 1 1 40
4 1 15 1 1 1 1 1 17 1 1 1 1 1 5 1 1 1 1 1 5 1 1 1 1 1 2
4 1 9 1 1 1 1 1 23 1 3 1 5 1 3 1 5 1 3 1 2
4 1 15 1 1 1 1 1 17 1 1 1 1 1 5 1 1 1 1 1 5 1 1 1 1 1 2
4 1 21 1 1 1 40
6 1 23 1 38
6 1 23 1 38
8 1 19 1 40
10 1 1 1 11 1 1 1 42
14 1 1 1 1 1 1 1 1 1 46

You can also test your code on two larger pictures: cat.txt and pumpkin.txt.

Now take a moment to upload your pixel_art.py file to the moodle assignment corresponding to this exam.

(You can upload pixel_art.py several times, but only your final upload will be graded - don’t wait until the last moment to upload a preliminary version, in case you miss the cut-off!)

Part 2: Transformations

In this second part we implement basic transformations on our 2D pictures:

Exercise 6: Horizontal mirror

Write a function horizontal_mirror that produces the horizontal mirror (symmetry with respect to a horizontal axis) of a pixel art.
In other words, the image must be flipped upside down: the top line becomes the bottom line, and vice versa.

Your function should open infilename for reading and outfilename for writing.
Then, read all the lines of the input file, reverse their order, and write them back (unchanged) to the output file.

Copy the following function stub into your file and complete it:

def horizontal_mirror(infilename, outfilename):
    """
    Read a pixel-art file (spaces and '#') and write its horizontal mirror.
    The image is flipped upside down (top <-> bottom).
    """
    pass  # remove this line and replace with your own code

Testing

Now test your code in the console:

In [15]: horizontal_mirror("invader.txt", "invader2.txt")

In [16]: horizontal_mirror("pac_man.txt", "pac_man2.txt")

Open the produced files invader2.txt and pac_man2.txt directly in Spyder.
You should see that the two images are flipped upside down. In details the file invader2.txt should contain this:

               
     ## ##     
  # #     # #  
  # ####### #  
  ###########  
   ## ### ##   
    #######    
     #   #     
    #     #    
               

then your mirrored file pac_man2.txt should look like this:

              # # # # #                                              
          # #           # #                                          
        #                   #                                        
      #                       #                                      
      #                       #                                      
    #                     # #                                        
    #               # # #                 # # #     # # #     # # #  
    #         # # #                       #   #     #   #     #   #  
    #               # # #                 # # #     # # #     # # #  
    #                     # #                                        
      #                       #                                      
      #             #         #                                      
        #                   #                                        
          # #           # #                                          
              # # # # #                                              

Once your code runs correctly, upload your pixel_art.py file to the Moodle assignment corresponding to this exam.

(You can upload pixel_art.py multiple times, but only your last version will be graded. Upload a preliminary version early to avoid missing the deadline.)

Exercise 7: Vertical mirror

Write a function vertical_mirror produces the vertical mirror (symmetry with respect to a vertical axis) of a pixel art : for each line, reverse the order of characters while preserving the line length and all spaces. Your function should open infilename for reading and outfilename for writing.

Copy the following function stub into your file and complete it:

def vertical_mirror(infilename, outfilename):
    """
    Read a pixel-art file (spaces and '#') and write its vertical mirror.
    Each output line is the input line reversed (excluding the newline).
    """
    pass # remove this line and replace with your own code

Hint: The lines you read from file will contain the endline caracter '\n' at the end. You can remove it by s.strip('\n').

Testing

Now test your code by doing this in the console:

In [17]: vertical_mirror("invader.txt","invader3.txt")

In [18]: vertical_mirror("pac_man.txt","pac_man3.txt")

You can open the produced files invader3.txt and pac_man3.txt directly in Spyder. As expected the file invader3.txtshould be the same as invader.txt (since the invader is vertically symmetrical) but pac_man3.txt is different from pac_man.txt. In details the file invader3.txt should contain this:

               
    #     #    
     #   #     
    #######    
   ## ### ##   
  ###########  
  # ####### #  
  # #     # #  
     ## ##     
               

while pac_man3.txt should contain that:

                                              # # # # #              
                                          # #           # #          
                                        #                   #        
                                      #         #             #      
                                      #                       #      
                                        # #                     #    
  # # #     # # #     # # #                 # # #               #    
  #   #     #   #     #   #                       # # #         #    
  # # #     # # #     # # #                 # # #               #    
                                        # #                     #    
                                      #                       #      
                                      #                       #      
                                        #                   #        
                                          # #           # #          
                                              # # # # #              

Now take a moment to upload your pixel_art.py file to the moodle assignment corresponding to this exam.

(You can upload pixel_art.py several times, but only your final upload will be graded - don’t wait until the last moment to upload a preliminary version, in case you miss the cut-off!)

Exercise 8: Converting a pixel art file into a list of lists

Write a function pixels_to_lol(infilename) that reads a text file representing a pixel-art image and converts it into a list of lists of characters.

Each line in the input file becomes a list of characters (including spaces), and the function should return a list containing all these lists.

Copy and complete the following function stub:

def pixels_to_lol(infilename):
    """
    Read a pixel-art file and return it as a list of lists of characters.
    Each line becomes a list of characters.
    """
    pass  # replace with your code

Hint: The lines you read from file will contain the endline caracter '\n' at the end. You can remove it by s.strip('\n').

Testing

Now test your code by doing this in the console:

In [19]: pixels_to_lol("small_art.txt")
Out[20]: [[' ', '#', '#', ' '], ['#', ' ', ' ', '#'], [' ', '#', '#', ' ']]

Now take a moment to upload your pixel_art.py file to the moodle assignment corresponding to this exam.

(You can upload pixel_art.py several times, but only your final upload will be graded - don’t wait until the last moment to upload a preliminary version, in case you miss the cut-off!)

Exercise 9: Rotating a list of lists

Write a function rotate_lol(lol) that takes a list of lists of equal length (a rectangular 2D grid) and returns a rotated version (90° counter clockwise).

Copy and complete the following function stub:

def rotate_lol(lol):
    """
    Rotate the list of lists 90° counter clockwise.
    """
    new_lol = [[] for l in lol[0]]
    pass

Hint: The length of the new lol will be equal to the length of any of the lists in the original lol. You can create first a list of this many empty lists (as in the code above) and then go through the original lol line by line filling the new lol column by column.

Testing

Now test your code by doing this in the console:

In [21]: lol = [['a','b','c'],['d','e','f']]
In [22]: rotate_lol(lol)
Out[23]: [['c', 'f'], ['b', 'e'], ['a', 'd']]

In [24]: rotate_lol(pixels_to_lol("small_art.txt"))
Out[113]: [[' ', '#', ' '], ['#', ' ', '#'], ['#', ' ', '#'], [' ', '#', ' ']]

Now take a moment to upload your pixel_art.py file to the moodle assignment corresponding to this exam.

(You can upload pixel_art.py several times, but only your final upload will be graded - don’t wait until the last moment to upload a preliminary version, in case you miss the cut-off!)

Exercise 10: Rotating a pixel-art file

Finally, write a function rotate(infilename, outfilename) that reads a pixel-art file, rotates it 90° counter clockwise using your previous functions, and writes the rotated image into outfilename.

Copy and complete the following function stub:

def rotate(infilename, outfilename):
    """
    Read a pixel-art file, rotate it 90° counter clockwise,
    and write the result to the output file.
    """
    pass  # replace with your code

Your function should:

  1. Use pixels_to_lol(infilename) to read the file into a list of lists.
  2. Use rotate_lol(lol) to rotate that list of lists.
  3. Join each inner list into a string and write all lines to outfilename.

Testing

You can test your program step by step in the console:

In [25]: rotate("frog.txt", "frog2.txt")

In [26]: rotate("invader.txt", "invader4.txt")

You can open the produced files frog2.txt and invader4.txt directly in Spyder, you should see your images correctly rotated 90° counter clockwise. In details the file frog2.txt should contain this:

                      
               ###    
              #   # ##
              #   ## #
      ####   #     # #
  ####    #########  #
 #     #           ###
#  ##   #     ####  ##
#  ##    #        #  #
 #       #        #  #
  #      #         ###
  #      #           #
  #      #           #
  #      #         ###
 #       #        #  #
#  ##    #        #  #
#  ##   #     ####  ##
 #     #           ###
  ####    #########  #
      ####   #     # #
              #   ## #
              #   # ##
               ###    
                      

while invader4.txt should contain that:

          
          
     ###  
    ##    
 # #####  
  ## ## # 
   #### # 
   ####   
   #### # 
  ## ## # 
 # #####  
    ##    
     ###  
          
          

You may also want to test the rotation on the Pac Man picture!

Now take a moment to upload your pixel_art.py file to the moodle assignment corresponding to this exam.

(You can upload pixel_art.py several times, but only your final upload will be graded - don’t wait until the last moment to upload a preliminary version, in case you miss the cut-off!)