COMP 202 - Foundations of Programming

Hello, if you have any need, please feel free to consult us, this is my wechat: wx91due

COMP 202 - Foundations of Programming

Assignment 4
McGill University, Fall 2024
Due: 6 December, 11:59 pm on Ed Lessons
Late Penalty: 10% per day and up to 2 late days
Vivian Li, Xuanpu Zhang, Faten M’hiri

Important notice

You will need to write three files for this assignment. Make sure that all file names and method names are spelled exactly as described in this document. Otherwise, a 50% penalty per question will be applied. You may make as many submissions as you like prior to the deadline, but we will only grade your final submission (all prior ones are automatically deleted). The following instructions are important:

• Please read the entire assignment guidelines and this PDF before starting. You must do this assignment individually.

• The work submitted for this assessment is expected to be your own. The use of technologies such as ChatGPT is prohibited and will be considered a violation of the Code of Student Conduct.
• Do not use functions that we didn’t mention in class.
• Do not use break and continue statements.

• Make sure to follow all the programming standards and to add docstrings with three examples for each method in the assignment (you may use only one example from thisdocument and you should think of another two examples of your own).

The main learning objectives for this assignment are:

• Object-oriented programming: Defining classes, creating objects, and applying methods to them;
• Nested lists;
• Dictionaries;
• Files: Working with files through Python built-in functions;


Figure 1: The file qrcode binary.txt opened in a text editor.

QR Code

A QR code (short for Quick Response Code) is a two-dimensional barcode that can storeinformation, which can be quickly accessed by scanning it with a device like a smartphone,tablet, or dedicated QR code reader. Unlike traditional barcodes, which store data in a linear fashion, QR codes use both horizontal and vertical dimensions to encode data, allowingthem to hold much more information.

A QR code consists of black and white squares arranged in a grid. The black squares represent the binary ”1” and the white squares represent the binary ”0”. The information isencoded in a format that is easily readable by devices with cameras.

In this assignment, binary representations of QR codes are stored in Txt files1. We will firstimplement some helper functions. Then we will create a TxtData class, which representsthe data stored in the Txt files. Fianlly, we will implement a QR code class that represents a QR code (the data itself + other information and functionalities).

Figure 2: The file small data.txt opened in a text editor.

1 Question 1: Helper functions [25 points]

Define two functions and write your functions in a file called helper.py:

1.1 convert date [10 points]

A function that takes in an input date str (string) and returns a dictionary with ”Day”, ”Month”, and ”Year” as keys and strings as values. The input date str should have the format ”dd/mm/yyyy” (2 digits/2 digits/4 digits) and this function should convert the string to the desired dictionary.

In your code, check that the input string has the right format. More specifically, checkthat it can be split into three parts by the ”/” character and that each part has the right length. You can assume that the input string has the correct format if it meets these requirements. Raise a ValueError if any of these requirements are not met.

>>> convert_date("09/01/2024")
{’Day’: ’09’, ’Month’: ’01’, ’Year’: ’2024’}
>>> convert_date("00/00")
Traceback (most recent call last):
ValueError: Input format incorrect!
>>> convert_date("9/1/2024")
Traceback (most recent call last):
ValueError: Input format incorrect!

1.2 get data [15 points]

A function that takes one input file path (string) and returns a nested list of integers ,representing the data in the file. The method should read the file located at file path. You can assume that the file exists.

The file should only contain ”0”s and ”1”s. Otherwise, raise a ValueError.

See below for an example. You can find the files small data and small data error can be found in figure 2 and 3.

Figure 3: The file small data error.txt opened in a text editor.

>>> get_data("small_data.txt")
[[0, 1], [1, 0]]
>>> get_data("small_data_error.txt")
Traceback (most recent call last):
ValueError: File should contain only 0s and 1s!

2 Question 2: Class TxtData [45 points]

Define a class TxtData that has three instance attributes:
• data: a nested list of integer representing the data;
• rows: an integer indicating the number of rows in data;
• cols: an integer indicating the number of columns in data;
Include the following instance methods and write your class in a file called txtdata.py. This file should import the helper.py file that you created in Question 1.

2.1 init [5 points]

A constructor that takes in data (2-D nested list) as explicit input. Make sure to make a deep copy of the input list with the help of the deepcopy function in the copy module. The data attribute should be initialized using the data input. The rows and cols attributesrepresent the number of rows and columns of data. You can assume that the input list hasat least one row and one column, and that all nested lists (if there are more than one) have the same length.

Figure 1 shows you how qrcode binary.txt looks like.

>>> my_list_simple= [[1,2,3],[4,5,6]]
>>> my_txt_simple = TxtData(my_list_simple)
>>> my_txt_simple.rows
2
>>> my_txt_simple.cols
3
>>> my_list = get_data("qrcode_binary.txt")
>>> my_txt = TxtData(my_list)
>>> my_txt.rows
33

>>> my_txt.cols

33

2.2 _ _str_ _ [5 points]

A _ _str_ _ method that returns a string of the format ”This TxtData object has ROWS rows and COLS columns.” where ROWS and COLS refer to the appropriate instance attributes.
>>> my_list_simple = [[1,2,3],[4,5,6]]
>>> my_txt_simple = TxtData(my_list_simple)
>>> print(my_list_simple)
This TxtData object has 2 rows and 3 columns.
>>> my_list = get_data("qrcode_binary.txt")
>>> my_txt = TxtData(my_list)
>>> print(my_txt)
This TxtData object has 33 rows and 33 columns.

2.3 get pixels [5 points]

An instance method that takes in no explicit input and returns an integer indicating the total number of pixels in data - number of rows × number of columns.
>>> my_list_simple = [[1,2,3],[4,5,6]]
>>> my_txt_simple = TxtData(my_list_simple)
>>> my_txt_simple.get_pixels()
6
>>> my_list = get_data("qrcode_binary.txt")
>>> my_txt = TxtData(my_list)
>>> my_txt.get_pixels()
1089

2.4 get data at [5 points]

An instance method that takes in two explicit inputs row (integer) and col (integer) indicating the position and returns an integer indicating the value in data at that position.A ValueError should be raised if row or col is out of bound.
>>> my_list_simple = [[1,2,3],[4,5,6]]
>>> my_txt_simple = TxtData(my_list_simple)
>>> my_txt_simple.get_data_at(0,0)
1
5>>> my_txt_simple.get_data_at(3,0)
Traceback (most recent call last):
ValueError: Index out of bound!
>>> my_list = get_data("qrcode_binary.txt")
>>> my_txt = TxtData(my_list)
>>> my_txt.get_data_at(0,0)
0
>>> my_txt.get_data_at(6,8)
1

2.5 pretty save [10 points]

An instance method that takes one explicit input file name (string) and returns nothing.It converts the data to a prettier form so that it can be scanned by our cameras as a QRcode.

”1”s are changed into ” ” (two blocks) and ”0”s and changed into ” ” (two spaces). It then saves the prettier QR code into a new file named file name. You can assume that there is no file with the name file name that exists beforehand.

The block character has the Unicode U+2588. To get the character in Python, you can use either ”\u2588” or chr(0x2588). See figure 4 for an example of a file saved from this method.

Note: do not use the replace() method.
>>> my_list = get_data("qrcode_binary.txt")
>>> my_txt = TxtData(my_list)
>>> my_txt.pretty_save("qrcode_pretty.txt")

2.6 equals [5 points]

An instance method that takes in one explicit input another data (TxtData) and returns a boolean indicating if the two TxtData objects are equal.

Two TxtData objects are considered equal if the data attributes are the same. In the example below, file qrcode binary copy.txt is an exact copy of file qrcode binary.txt, while qrcode binary 1.txt has exactly one different value than qrcode binary.txt.

>>> my_list_simple = [[1,2,3],[4,5,6]]
>>> my_txt_simple_1 = TxtData(my_list_simple)
>>> my_txt_simple_2 = TxtData(my_list_simple)
>>> my_txt_simple_1.equals(my_txt_simple_2)
True
>>> my_txt = TxtData("qrcode_binary.txt")
>>> my_list = get_data("qrcode_binary.txt")
>>> my_txt = TxtData(my_list)
>>> my_txt_copy = TxtData("qrcode_binary_copy.txt")


Figure 4: The file saved from pretty save method opened in a text editor.

>>> my_txt.equals(my_txt_copy)
True
>>> my_list_1 = get_data("qrcode_binary_1.txt")
>>> my_txt_1 = TxtData(my_list_1)
>>> my_txt.equals(my_txt_1)
False

2.7 approximately equals [10 points]

An instance method that takes in two explicit inputs another data (TxtData) and precision (non-negative float) and returns a boolean indicating if the two TxtData objects are approx

imately equal.

Two TxtData objects are considered approximately equal if the inconsistent rate of the two data attributes is not greater than the input precision. The inconsistent rate can be cal culated by getting the number of inconsistent values and dividing that by the total number of values (number of pixels).

In the examples below, qrcode binary 1.txt has exactly one different value than qrcode binary.txt and qrcode binary 2.txt has two different values.

>>> my_list_simple_1 = [[1,2,3],[4,5,6]]
>>> my_list_simple_2 = [[1,2,3],[7,8,9]]
>>> my_txt_simple_1 = TxtData(my_list_simple_1)
>>> my_txt_simple_2 = TxtData(my_list_simple_2)
>>> my_txt_simple_1.equals(my_txt_simple_2)
False
>>> my_txt_simple_1.approximately_equals(my_txt_simple_2, 0.5)
True
>>> my_txt = TxtData("qrcode_binary.txt")
>>> my_txt_1 = TxtData("qrcode_binary_1.txt")
>>> my_txt.equals(my_txt_1)
False
>>> my_txt.approximately_equals(my_txt_1, 1/my_txt.get_pixels())
True
>>> my_txt_2 = TxtData("qrcode_binary_2.txt")
>>> my_txt.approximately_equals(my_txt_2, 1/my_txt.get_pixels())
False

3 Question 3: Class QRCode [30 points]

Define a class QRCode that has four instance attributes:
  • last update date: a dictionary with ”Day”, ”Month”, and ”Year” as keys and strings representing the last update date of the QR code as values.
  • owner: a string representing the owner of the QR code.
  • data: a TxtData object representing the QR code itself.
  • error correction: a float indicating the error correction capability of the QR code. QR codes have built-in error correction capabilities, which enable them to still be readable even if part of the code is damaged or obscured. This attribute indicates the max value of the damage rate before the QR code is unreadable. A QR code is considered to be corrupted if it is no longer readable.

Include the following instance methods and write your QRCode class in a file called qrcode.py. This file should import the helper.py file that you created in Question 1 and the txtdata.py file that you created in Question 2.

3.1 _ _init _ _ [10 points]

A constructor that takes in four explicit inputs file path (string), last update date (string, optional), owner (string, optional), error correction (float, optional).

It should construct a TxtData object with the file path input to get the data attribute.

You can assume that the last update date input has the format ”dd/mm/yyyy”. This constructor should call a helper method and convert the string to the desired dictionary for the last update date attribute. If no input is given, the default value is ”00/00/0000”.

If no input is given for owner, the default value is ”Default Owner”.

If no input is given for error correction, the default value is 0.0.

>>> my_qrcode = QRCode("qrcode_binary.txt", "01/09/2024", "Vivian", 0.1)
>>> my_qrcode.last_update_date[’Day’]
’01’
>>> my_qrcode.last_update_date[’Month’]
’09’
>>> my_qrcode.last_update_date[’Year’]
’2024’
>>> my_qrcode.owner
’Vivian’
>>> my_qrcode.error_correction
0.1

3.2_ _str_ _  [10 points]

A _ _str_ _ method that returns a string of the format:

”The QR code was created by OWNER and last updated in LAST UPDATE YEAR.

The details regarding the QR code file are as follows:

This TxtData object has ROWS rows and COLS columns.”

where OWNER, LAST UPDATE YEAR, ROWS, and COLS refer to the appropriate values. Notice how we only want the year of the last modified date.
>>> my_qrcode = QRCode("qrcode_binary.txt", "01/09/2024", "Vivian", 0.1)
>>> print(my_qrcode)
The QR code was created by Vivian and last updated in 2024.
The details regarding the QR code file are as follows:
This TxtData object has 33 rows and 33 columns.

3.3 equals [5 points]

An instance method that takes in one explicit input another qrcode (QRCode) and returns a boolean indicating whether the two QRCodes are the same. Two QRCodes are considered equal if the data and the error correction attributes are the same. Notice how we don’t take the owner and the last modified date into consideration.
>>> my_qrcode = QRCode("qrcode_binary.txt", "01/09/2024", "Vivian", 0.1)
>>> my_qrcode_copy = QRCode("qrcode_binary_copy.txt", "01/09/2022",
"Xuanpu", 0.1)
>>> my_qrcode.equals(my_qrcode_copy)
True

3.4 is corrupted [5 points]

An instance method that takes in one explicit input precise qrcode (QRCode) and returns whether the self object is corrupted. To know if a QR code is corrupted, you first compare it with a precise QR code. A QR code is considered corrupted if it’s not approximately equal with the precise QR code with the error correction as the precision.

In the example below, almost half of the data inside the file qrcode binary c.txt is different from the data inside the file qrcode binary.txt.

>>> my_qrcode = QRCode("qrcode_binary.txt", "01/09/2024", "Vivian", 0.1)
>>> my_c_qrcode = QRCode("qrcode_binary_c.txt", "01/09/2000", "Vivian",
0.1)
>>> my_c_qrcode.is_corrupted(my_qrcode)
True

发表评论

电子邮件地址不会被公开。 必填项已用*标注