Starting from:

$30

CS 201 Data Structures 2 Homework 1 -Solved

This write-up has 3 parts. The first part provides an explanation of your implementation tasks. It refers 
to code that is provided in the appendices in the third part. The second part lists the tasks for you to do. 
It contains space for you to enter your solutions to some of the problems. The third part lists code which is 
referred to in the first part. 
You have to fill in the solutions in the second part, and complete the code files in the accompanying src/ 
folder as described in Part 1. Please work in this file, hw1.tex, and not in a copy. When submitting, please 
remove the first and third parts from this file. 
Part I 
Explanation 
In this assignment, we will implement an ArrayList to represent a List. We will use the List to implement 
an image and will write operations for the image. 
1 Image Operations 
We will work with RGB images and perform four operations on them–channel suppression, rotations, mask 
application, and resize. None of these operations is destructive. That is, the operations do not alter the 
original image, rather they return a new image containing the result of the operation. 
1.1 Channel Suppression 
An image is said to contain color values in different channels. In an RGB image, the channels are Red, Blue, 
and Green. Each channel contains the intensities for that color for every pixel in the image. The values from 
all three channels at a pixel yield the RGB value at the pixel. A channel suppression operation switches off 
a specific channel. That is, all intensities in that channel are turned to zero, or turned off. Figure 1 shows 
an original image and two modifications, one with the blue channel turned off, and the other with only the 
blue channel turned on, i.e. the red and green channels turned off. 
1.2 Rotation 
Given a square image, i.e. one whose width is equal to its height, this operation generates a new image that 
contains rotations of the original image. Figure 2 shows an example of applying the operation. The resulting 
image has twice the dimensions of the original image, i.e. twice the width and twice the height. It contains 
4 appropriately placed sub-images which, going anti-clockwise are the original image rotated anti-clockwise 
by increments of 90◦. 
1CS 201 Data Structures II Homework 1: Lists Spring 2023 
(a) An RGB image of a swimming 
pool. 
(b) The image with the blue chan
nel turned off. 
(c) The original image with only 
the blue channel turned on. 
Figure 1: Example of channel suppression. 
(a) A square image. 
(b) The image obtained as a result of ap
plying rotations to the original image. 
Figure 2: Example of rotation. 
1.3 Applying a Mask 
A mask specifies certain weights and applying the mask to an image entails replacing the value at each pixel 
in the image with a weighted sum or weighted average of the values of its neighbors. The weights and the 
neighbors to consider for the average are specified by the mask. 
A mask is an n × n array of integers representing weights. For our purposes, n must be odd. This 
means that the n × n array has a well defined center–the origin. The weights in the mask can be arbitrary 
integers–positive, negative, or zero. 
For each pixel in the input image, think of the mask as being placed on top of the image so its origin 
is on the pixel we wish to examine. The intensity value of each pixel under the mask is multiplied by the 
corresponding value in the mask that covers it. These products are added together. Always use the original 
values for each pixel for each mask calculation, not the new values that you compute as you process the 
image. 
For example, refer to Figure 3a, which shows the 3 × 3 mask, 

 
1 3 1 
3 5 3 
1 3 1 

 
and an image on which we want to perform the mask computation. Suppose we want to compute the result 
of the mask computation for pixel e. This result would be: 
a + 3b + c + 3d + 5e + 3f + g + 3h + i 
Some masks require a weighted average instead of a weighted sum. The weighted average in the case of 
Figure 3a for pixel e would be: 
a + 3b + c + 3d + 5e + 3f + g + 3h + i 
1 + 3 + 1 + 3 + 5 + 3 + 1 + 3 + 1 
Page 2 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 
(a) Overlay the 3×3 mask over the image so it is centered 
on pixel e to compute the new value for pixel e. 
(b) If the mask hangs over the edge of the image, use only 
those mask values that cover the image in the weighted 
sum. 
Figure 3: Applying a mask to an image. 
Instead of doing this calculation for each channel individually at a pixel, for the purpose of this calculation, 
replace the value of each channel at the pixel with the average channel value at the pixel. For example, if the 
pixel is given by (r, g, b) = (107, 9, 218), then apply the mask to the average value (107 + 9 + 218)//3 = 111 
(integer division) and copy the result to each channel of the corresponding pixel in the output image. This 
effectively converts the output image to grayscale. 
Note that sometimes when you center the mask over a pixel, the mask will hang over the edge of the 
image. In this case, compute the weighted sum of only those pixels that the mask covers. For the example 
shown in Figure 3b, the weighted sum for the pixel e is given by: 
3b + c + 5e + 3f + 3h + i 
and the weighted average is as follows. 
3b + c + 5e + 3f + 3h + i 
3 + 1 + 5 + 3 + 3 + 1 
Integer division is used when computing averages in order to ensure that pixel intensities are integers. 
1.3.1 Applications of Masks 
Applying different masks leads to different properties. For example, applying the following mask leads to 
blurring of the image. Figures 4a and 4b show the blurring effect of this mask. Note that color information 
is lost as mentioned above. 





 
2 4 5 4 2 
4 9 12 9 4 
5 12 15 12 5 
4 9 12 9 4 
2 4 5 4 2 





 

Another application we use is an implementation of Canny Edge Detection using Sobel Operators. Once 
the image has been blurred as above, two more filters, or masks, (the Sobel operators) are applied in 
succession to the blurred image. These filters determine the change in intensity, which approximates the 

(a) An image with sharp details and 
several lines. 
(b) Result of applying the blur mask 
to the original image. 
(c) Result of applying the Sobel fil
ters to the blurred image. 
Figure 4: Blurring and detection of edges in an image using masks. 
horizontal and vertical derivatives. 
Gx = 
 

1 0 1 
−2 0 2 
−1 0 1 

 
, Gy = 
 

1 −2 
−1 
0 0 0 
1 2 1 

 

After these operations are applied one after the other to the blurred image, the values obtained are used to 
search for edges based on the magnitude and direction of the change in intensity. An example of the final 
result is shown in Figure 4c. 
1.4 Resize 
Given an image, this operation generates a new image that has twice the dimensions of the original image 
i.e, twice the width and twice the height. Figure 5 shows a 4x3 image which is resized to twice its size. The 
resized image has 4 times as many pixels and some of them take on the values from the original image as 
shown. For the pixels shown to be blank, color values are not known and have to be computed from the 
known values. Consider the labeled pixels in the resized image below. One way to fill in the missing color 
information is as follows. 
P = 
1
2
(A + B), T = 
1
2
(C + D), Q = 
1
2
(A + C), S = 
1
2
(B + D) 
Page 4 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 
Figure 5: Bilinear Interpolation 
There are various ways to compute R, all of which are ultimately equivalent. 
R = 
1
2
(P + T) = 
1
2
(S + Q) = 
1
4
(A + B + C + D) = 
1
4
(P + Q + S + T) = 
1
8
(A + B + C + D + P + Q + S + T) 
The boundary pixels pose a problem as some of the neighboring pixels required for the average do not exist. 
In such cases, only the existing neighbors are used for the average. 
Notice how all the above expressions are affine combinations. Furthermore, the colors for P, Q, S, and T 
are linearly interpolated from their horizontal or vertical neighbors. The color for R is a bilinear interpolation: 
it is a linear interpolation of P and T, or Q and S, which are themselves linear interpolations. 
Note: All divisions in the above expressions are integer divisions. 
2 Image 
We treat an image as a grid of pixels where each pixel is represented as an RGB value indicating the red, 
green, and blue intensities of the pixel. An image has dimensions, namely width and height, which determine 
the number of rows and columns in the image. Every pixel in the image is at a unique combination of row 
and column numbers which can therefore be used as a coordinate system in the image. An image with width 
w and height h is said to be of size w × h. Figure 6a shows the column and row numbers in a w × h image 
along with the resulting pixel coordinates. Note that the coordinate is just a means to locate a pixel in the 
image, it is not the value stored at the pixel. The value stored at a pixel is a triplet denoting the red, green, 
and blue intensities respectively. 
We will work with a flattened representation of an image. That is, we will store the pixel values in a 
1-dimensional list structure as opposed to a 2-dimensional structure (programming languages generally store 
multi-dimensional arrays in their flattened form) . The list stores pixel values as they appear in the image 
from left to right and top to bottom. Figure 6b shows a 5 × 5 image with some supposed RGB values. 
Note that each value would be a triplet of integers, each integer between 0 and 255 inclusive. Using our 
representation, the image in Figure 6b will be represented as the list: 
[a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y] 
Page 5 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 
Columns 
0 1 2 . . . (w − 1) 

(0, 0) 
(0, 1) 
(0, 2) 
. . . 
(0, w − 1) 

(1, 0) 
(1, 1) 
(1, 2) 
. . . 
(1, w − 1) 

(2, 0) 
(2, 1) 
(2, 2) 
. . . 
(2, w − 1) 
.
.

(h − 1) 
(h − 1, 0) 
(h − 1, 1) 
(h − 1, 2) 
. . . 
(h − 1, w − 1) 
(a) Row and column numbers of an image with width w and height h. Pixel 
coordinates are also shown. 

























(b) A 5 × 5 image with supposed 
pixel values. 
Figure 6: Image dimensions and pixel coordinates. 
3 Implementation Details and Tasks 
We will be working with a MyImage class as shown in Listing 1 on Page 9, also included in the accompanying 
file src/myimage.py. Its implementation is complete but requires a concrete implementation of MyList which 
is our implementation of the List interface. The implementation to be used is specified in the constructor of 
MyImage. 
An implementation of MyList is shown in Listing 2 on Page 12, also included in the accompanying file 
src/mylist.py. The implementation is mostly complete except for the segments marked as pass. These 
are to be implemented appropriately in the subclasses of MyList which are indicated at the end of the listing 
and whose implementation is completely missing. Writing their implementations is one of your tasks in this 
assignment. 
Once you are done implementing MyList subclasses, the MyImage class is ready to be operated on. 
Functions corresponding to the operations described in Section 1 are shown in Listing 3 on Page 16 and 
included in the accompanying file src/image operations.py. None of the operations is destructive. That 
is, each operates on a MyImage instance and returns the result as a new MyImage instance. The functions 
are missing implementations. Writing their implementations is another of your tasks in this assignment. 
3.1 Tasks 
❼ Go over the provided files thoroughly in order to understand what they do or are expected to do. 
❼ Provide implementations for unimplemented methods, i.e. those that have pass in their body. 
❼ Derive ArrayList class from MyList and provide its implementation in the same file. ArrayList 
implements the list using python arrays. 
3.2 Requirement 
You will need to install Pillow which will prove the PIL module used in the provided code. 
3.3 Tips 
Below are some tips to avoid the errors that have previously caused tests to fail. Following these may save 
you many frustrating hours of debugging! 
❼ Delay division as much as possible and perform int division wherever needed. 
❼ When writing gray values to file, make sure to clamp them to [0,255]. 
❼ Take care about imagine indexing. 
❼ Be careful when creating a copy of the image. Use the copy where needed and the original where 
needed. 
Page 6 of 20 
RowsCS 201 Data Structures II Homework 1: Lists Spring 2023 
❼ Do not forget to average the RGB values when the corresponding flag in apply_mask is enabled. 
❼ Take care about efficiency. Some structures are slow. If, on top, your code is inefficient, the automated 
tests may fail due to time out. 
3.4 Testing 
Once you have successfully implemented the subclasses and image operations, you can test your code by 
creating an image and performing operations on it. Your submission will be tested automatically by GitHub 
using the accompnaying pytest file, test image.py. 
4 Credits 
This homework is adapted from Homework 3 of the Fall 2014 offering of 15-122: Principles of Imperative 
Computation at Carnegie Mellon University (CMU). 
Part II 
Problems 
The grading is defined in the accompanying rubric file. 
1. Implementation 
Complete the tasks listed in Section 3.1 by providing the implementations in the indicated files. 
2. Amortized Analysis 
Consider an ArrayStack implementation of the List interface with a slightly altered resize() operation. 
Instead of reserving space for 2n elements in the new array, it reserves space for n+⌈ n
4 ⌉ elements. Prove 
that the append() operation still takes O(1) time in the amortized sense. 
Solution: 
Traditional resize() where the length of the array doubles when the array is full works by allocating 
an array b of size 2n, and copies the n elements of the original array a into the new array b and then 
sets a to b. Therefore, a has length of 2n now. This takes O(n) time where the append() operation 
takes O(1) time. 
If the new resize() operation reserves space for n + [ n
4 ] elements, then the append() operation 
would still take O(1) time in the amortized sense. 
This can be undertood better by first understanding the cost of append() for when resize() reserves 
space for 2n elements; 
Resize of 2n: 
Consider an array of size 1. The cost of appending an element would be O(1) [n = 1]. 
Now for the second append(), resize would be called, and then the total cost of appending the 
second element would be O(2)[n = 2]. 
For the third append(), resize() would again be called and the total cost would be O(3)[n = 3]. 
For the fourth append(), resize() won’t be called as the array is not full, and only the cost of 
append() is taken into account, therefore the total cost is O(4), however, this takes into account 
traversal cost as well, and the cost of append() remains O(1). 
Page 7 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 
With the next append() operation[n = 5], a new array will be created with space reserved for 8 
elements. Then the total cost of appending all elements into the new array is O(5), however, the 
individual cost of append() remains O(1). 
Then using the above, we can make a series such that: 
Series = 1 + (1 + 1) + (1 + 2) + 1 + (1 + 4) + 1 + 1 + 1 + (1 + 8) + · · · 
Therefore, the total cost becomes: 
Cost = 1 + 2 + 4 + 8 + · · · [for resize()] +1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 · · · [for append()] 
The above series for resize can be written as a geometric series where resize() = 2log2(n)−i + 1. 
Hence the total cost of resize() comes out to be O(1) with each append() operation having a cost 
of O(1). 
Resize of n + n
4 : 
Then we can prove that the append() operation has a cost of O(1) in the amortized sense. 
The new size increase is of n + n
4 =⇒ 54n . So space is reserved in the new array for 54n elements(we 
will consider ceil value for decimal numbers). 
Now consider an array of size 1. The cost of appending just one element would be O(1) [n = 1]. 
For another append() operation [n = 2], the total cost would be considering the cost of resize, and 
the cost of append. The resize() function would give us 14 = 0.25. Ceil(0.25) = 1. Therefore, the 
total cost becomes 1 + ceil( n
4 ) = 1 + 1 = O(2). 
For the third append() [n = 3] operation, the total cost would be considering the cost of resize, 
and the cost of append. The resize() function would give us 
2

= 0.5. Ceil of this is equal to 1. 
Therefore the total cost would be 1 + 1 + 1 = O(3). 
For the fourth append() operation, the same takes place. 
For the fifth append() operation, resize() reserves space for 2 elements, as resize() gives us 
5
4 = 1.25, and the ceil of this is 2. Therefore, space is reserved for two elements. Therefore, the 
following append() operation would cost O(1). 
Then using the above, we can make a series such that: 
Series = 1 + (1 + 1) + (1 + 2) + (1 + 3) + (1 + 4) + (1 + 5) + 1 + (1 + 7) + · · · 
Therefore, the total cost becomes: 
Cost = 1 + 2 + 3 + 4 + 5 + 7 + · · · [for resize()] +1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + · · · [for append()] 
Then the series can be written as a geometric series where resize() = n + 
5 log 54n +1 

=⇒ O(n) as 
n gets larger. 
Then the cost of appending one element is O
(n) 

= O(1). Hence proved that the append() operation 
still takes O(1) time in the amortized sense. 
Page 8 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 
Part III 
Appendices 

MyImage 
1 from PIL 
import 
Image 
2 from 
src . mylist 
import ArrayList 
3
4
5 class MyImage : 

""" Holds a flattened RGB 
image and its dimensions . Also implements Iterator 

methods to allow iteration 
over 
this image . 

""" 

10 
def __init__ ( self , size : (int , int )) -> None : 
11 
""" Initializes a black 
image of the given 
size . 
12 
13 
Parameters : 
14 
- self : mandatory 
reference to this object 
15 
- size : ( width , height ) specifies the dimensions to create . 
16 
17 
Returns : 
18 
none 
19 
""" 
20 
# Save size , create a list of the desired size with black pixels . 
21 
width , height = self . size = size 
22 
self . pixels : ArrayList = ArrayList ( width * height , 
23 
value =(0 , 0 , 0)) 
24 
25 
def __iter__ ( self ) -> ✬MyImage ✬: 
26 
✬✬✬ Iterator function to return an iterator 
( self ) that allows iteration over 
27 
this image . 
28 
29 
Parameters : 
30 
- self : mandatory reference to this object 
31 
32 
Returns : 
33 
an iterator 
( self ) that allows iteration over this image . 
34 
✬✬✬ 
35 
# Initialize iteration indexes . 
36 
self . _iter_r : int = 0 
37 
self . _iter_c : int = 0 
38 
return self 
39 
40 
def __next__ ( self ): 
41 
✬✬✬✬ Iterator function to return the next value from this list . 
42 
43 
Image pixels are iterated over in a left -to - right , top -to - bottom order . 
44 
45 
Parameters : 
46 
- self : mandatory reference to this object 
47 
48 
Returns : 
49 
the next value in this image since the last iteration . 
50 
51 
✬✬✬ 
52 
if self . _iter_r < self . size [1]: 
# Iteration within image bounds . 
53 
# Save current value as per iteration variables . Update the 
54 
# variables for the next iteration as per the iteration 
55 
# order . Return saved value . 
56 
value = self . get ( self . _iter_r , self . _iter_c ) 
57 
self . _iter_c += 1 
58 
if self . _iter_c == self . size [0]: 
Page 9 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 
59 
self . _iter_c = 0 
60 
self . _iter_r += 1 
61 
return value 
62 
else : 
# Image bounds exceeded , end of iteration . 
63 
# Reset iteration variables , end iteration . 
64 
self . _iter_r = self . _iter_c = 0 
65 
raise StopIteration 
66 
67 
def _get_index ( self , r: int , c: int) -> int : 
68 
""" Returns the list index for the given row , column 
coordinates . 
69 
70 
This is an internal function for use in class methods only . It should 
71 
not be used or called from outside the class . 
72 
73 
Parameters : 
74 
- self : mandatory reference to this object 
75 
- r: the row coordinate 
76 
- c: the column 
coordinate 
77 
78 
Returns : 
79 
the list index co rr es po nd in g to the given row and column 
coordinates 
80 
""" 
81 
# Confirm bounds , compute and return list index . 
82 
width , height = self . size 
83 
assert 0 <= r < height and 0 <= c < width , " Bad image coordinates : "\ 
84 
f"(r, c): ({r}, {c}) for image of size : { self . size }" 
85 
return r* width + c 
86 
87 
def open ( path : str ) -> ✬MyImage ✬: 
88 
""" Creates and returns an image containing from the information at file path . 
89 
90 
The image format is inferred from the file name . The read image is 
91 
converted to RGB as our type only stores RGB . 
92 
93 
Parameters : 
94 
- path : path to the file containing image information 
95 
96 
Returns : 
97 
the image created using the information from file path . 
98 
""" 
99 
# Use PIL to read the image information and store it in our instance . 
100 
img : Image = Image . open ( path ) 
101 
myimg : MyImage = MyImage ( img . size ) 
102 
# Covert image to RGB . https :// s ta ck ove rf lo w . com /a/ 11064935 / 1382487 
103 
img : Image = img . convert (✬RGB ✬) 
104 
# Get list of pixel values 
( https :// st ac ko ve rf low . com /a/ 1109747 / 1382487 ), 
105 
# copy to our instance and return it . 
106 
for i , rgb in enumerate ( list ( img . getdata () )): 
107 
myimg . pixels . set (i , rgb ) 
108 
return myimg 
109 
110 
def save ( self , path : str ) -> None : 
111 
""" Saves the image to the given file path . 
112 
113 
The image format is inferred from the file name . 
114 
115 
Parameters : 
116 
- self : mandatory reference to this object 
117 
- path : the image has to be saved here . 
118 
119 
Returns : 
120 
none 
121 
""" 
122 
# Use PIL to write the image . 
123 
img : Image = Image . new (" RGB ", self . size ) 
124 
img . putdata ([ rgb for rgb in self . pixels ]) 
Page 10 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 
125 
img . save ( path ) 
126 
127 
def get ( self , r: int , c: int ) -> (int , int , int ): 
128 
""" Returns the value of the pixel at the given row and column 
coordinates . 
129 
130 
Parameters : 
131 
- self : mandatory reference to this object 
132 
- r: the row coordinate 
133 
- c: the column 
coordinate 
134 
135 
Returns : 
136 
the stored RGB value of the pixel at the given row and column 
coordinates . 
137 
""" 
138 
return self . pixels [ self . _get_index (r , c)] 
139 
140 
def set( self , r: int , c: int , rgb: (int , int , int )) -> None : 
141 
""" Write the rgb value at the pixel at the given row and column 
coordinates . 
142 
143 
Parameters : 
144 
- self : mandatory reference to this object 
145 
- r: the row coordinate 
146 
- c: the column 
coordinate 
147 
- rgb : the rgb value to write 
148 
149 
Returns : 
150 
none 
151 
""" 
152 
self . pixels [ self . _get_index (r , c)] = rgb 
153 
154 
def show ( self ) -> None : 
155 
""" Display the image in a GUI window . 
156 
157 
Parameters : 
158 
159 
Returns : 
160 
none 
161 
""" 
162 
# Use PIL to display the image . 
163 
img : Image = Image . new (" RGB ", self . size ) 
164 
img . putdata ([ rgb for rgb in self . pixels ]) 
165 
img . show () 
Code Listing 1: Image Type 
Page 11 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 

MyList 
1 import array as arr 
2
3 class MyList : 

✬✬✬A list interface . Also implements Iterator functions in order to support 

iteration over this list . 

✬✬✬ 
7

def __init__ ( self , size : int , value = None ) -> None : 

""" Creates a list of the given size , optionally intializing elements to value . 
10 
11 
The list is static . It only has space for size elements . 
12 
13 
Parameters : 
14 
- self : mandatory reference to this object 
15 
- size : size of the list ; space is reserved for these many elements . 
16 
- value : the optional initial value of the created elements . 
17 
18 
Returns : 
19 
none 
20 
""" 
21 
self . lst_arr = 
[ value ] * size 
22 
23 
def __len__ ( self ) -> int : 
24 
✬✬✬ Returns the size of the list . Allows len () to be called on it. 
25 
26 
Ref : https :// st ac ko ve rf lo w . com /q/ 7642434 / 1382487 
27 
28 
Parameters : 
29 
- self : mandatory reference to this object 
30 
31 
Returns : 
32 
the size of the list . 
33 
✬✬✬ 
34 
return len ( self . lst_arr ) 
35 
36 
def __getitem__ ( self , i: int): 
37 
✬✬✬ Returns the value at index , i. Allows indexing syntax . 
38 
39 
Ref : https :// st ac ko ve rf lo w . com /a/ 33882066 / 1382487 
40 
41 
Parameters : 
42 
- self : mandatory reference to this object 
43 
- i: the index from which to retrieve the value . 
44 
45 
Returns : 
46 
the value at index i. 
47 
✬✬✬ 
48 
# Ensure bounds . 
49 
assert 0 <= i < len ( self ) ,\ 
50 
f✬Getting invalid list index {i} from list of size { len ( self )} ✬ 
51 
return self . lst_arr [i] 
52 
53 
def __setitem__ ( self , i: int , value ) -> None : 
54 
✬✬✬ Sets the element at index , i , to value . Allows indexing syntax . 
55 
56 
Ref : https :// st ac ko ve rf lo w . com /a/ 33882066 / 1382487 
57 
58 
Parameters : 
59 
- self : mandatory reference to this object 
60 
- i: the index of the elemnent to be set 
61 
- value : the value to be set 
62 
63 
Returns : 
64 
none 
Page 12 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 
65 
✬✬✬ 
66 
# Ensure bounds . 
67 
assert 0 <= i < len ( self ) ,\ 
68 
f✬Setting invalid list index {i} in list of size { len ( self )} ✬ 
69 
self . lst_arr [i] = value 
70 
71 
def __iter__ ( self ) -> ✬MyList ✬: 
72 
✬✬✬ Iterator function to return an iterator 
( self ) that allows iteration over 
73 
this list . 
74 
75 
Parameters : 
76 
- self : mandatory reference to this object 
77 
78 
Returns : 
79 
an iterator 
( self ) that allows iteration over this list . 
80 
✬✬✬ 
81 
# Initialize iteration index . 
82 
self . _iter_index : int = 0 
83 
return self 
84 
85 
def __next__ ( self ): 
86 
✬✬✬✬ Iterator function to return the next value from this list . 
87 
88 
Parameters : 
89 
- self : mandatory reference to this object 
90 
91 
Returns : 
92 
the next value in this list since the last iteration . 
93 
✬✬✬ 
94 
if self . _iter_index < len ( self ): 
95 
value = self . get ( self . _iter_index ) 
96 
self . _iter_index += 1 
97 
return value 
98 
else : 
99 
# End of Iteration 
100 
self . _index = 0 
101 
raise StopIteration 
102 
103 
def get ( self , i: int ): 
104 
✬✬✬ Returns the value at index , i. 
105 
106 
Alternate to use of indexing syntax . 
107 
108 
Parameters : 
109 
- self : mandatory reference to this object 
110 
- i: the index from which to retrieve the value . 
111 
112 
Returns : 
113 
the value at index i. 
114 
✬✬✬ 
115 
return self [i] 
116 
117 
def set( self , i: int , value ) -> None : 
118 
✬✬✬ Sets the element at index , i , to value . 
119 
120 
Alternate to use of indexing syntax . 
121 
122 
Parameters : 
123 
- self : mandatory reference to this object 
124 
- i: the index of the elemnent to be set 
125 
- value : the value to be set 
126 
127 
Returns : 
128 
none 
129 
✬✬✬ 
130 
self [i] = value 
Page 13 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 
131 
132 
133 class ArrayList ( MyList ): 
134 
✬✬✬A list interface . Also implements Iterator functions in order to support 
135 
iteration over this list . 
136 
✬✬✬ 
137 
138 
def __init__ ( self , size : int , value = None ) -> None : 
139 
""" Creates a list of the given size , optionally intializing elements to value . 
140 
141 
The list is static . It only has space for size elements . 
142 
143 
Parameters : 
144 
- self : mandatory reference to this object 
145 
- size : size of the list ; space is reserved for these many elements . 
146 
- value : the optional initial value of the created elements . 
147 
148 
Returns : 
149 
none 
150 
""" 
151 
self . arr_red = arr . array (✬i✬, [ value [0] for i in range ( size )]) 
152 
self . arr_green = arr . array (✬i✬, [ value [1] for i in range ( size )]) 
153 
self . arr_blue = arr . array (✬i✬, [ value [2] for i in range ( size )]) 
154 
155 
def __len__ ( self ) -> int : 
156 
✬✬✬ Returns the size of the list . Allows len () to be called on it. 
157 
158 
Ref : https :// st ac ko ve rf lo w . com /q/ 7642434 / 1382487 
159 
160 
Parameters : 
161 
- self : mandatory reference to this object 
162 
163 
Returns : 
164 
the size of the list . 
165 
✬✬✬ 
166 
return len ( self . arr_blue ) 
167 
168 
def __getitem__ ( self , i: int): 
169 
✬✬✬ Returns the value at index , i. Allows indexing syntax . 
170 
171 
Ref : https :// st ac ko ve rf lo w . com /a/ 33882066 / 1382487 
172 
173 
Parameters : 
174 
- self : mandatory reference to this object 
175 
- i: the index from which to retrieve the value . 
176 
177 
Returns : 
178 
the value at index i. 
179 
✬✬✬ 
180 
# Ensure bounds . 
181 
assert 0 <= i < len ( self ) ,\ 
182 
f✬Getting invalid list index {i} from list of size { len ( self )} ✬ 
183 
return 
(( self . arr_red [i], self . arr_green [i], self . arr_blue [i])) 
184 
185 
def __setitem__ ( self , i: int , value ) -> None : 
186 
✬✬✬ Sets the element at index , i , to value . Allows indexing syntax . 
187 
188 
Ref : https :// st ac ko ve rf lo w . com /a/ 33882066 / 1382487 
189 
190 
Parameters : 
191 
- self : mandatory reference to this object 
192 
- i: the index of the elemnent to be set 
193 
- value : the value to be set 
194 
195 
Returns : 
196 
none 
Page 14 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 
197 
✬✬✬ 
198 
# Ensure bounds . 
199 
assert 0 <= i < len ( self ) ,\ 
200 
f✬Setting invalid list index {i} in list of size { len ( self )} ✬ 
201 
self . arr_red [i] = value [0]; self . arr_green [i] = value [1]; self . arr_blue [i] = value [2 

Code Listing 2: List Type 
Page 15 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 
C Image Operations 
1 from src . myimage import MyImage 
2
3 def remove_channel ( src: MyImage , red : bool = False , green : bool = False , 

blue : bool = False ) -> MyImage : 

""" Returns a copy of src in which the indicated channels are suppressed . 
6

Suppresses the red channel if no channel is indicated . src is not modified . 
8

Args : 
10 
- src : the image whose copy the indicated channels have to be suppressed . 
11 
- red : suppress the red channel if this is True . 
12 
- green : suppress the green channel if this is True . 
13 
- blue : suppress the blue channel if this is True . 
14 
15 
Returns : 
16 
a copy of src with the indicated channels suppressed . 
17 
""" 
18 
src_copy = MyImage ( src . size ) 
19 
rows = src . size [1] 
20 
cols = src . size [0] 
21 
for row in range ( rows ): 
22 
for col in range ( cols ): 
23 
src_copy . set( row , col , src . get ( row , col )) 
24 
25 
if red == False and green == False and blue == False : 
26 
for row in range ( rows ): 
27 
for col in range ( cols ): 
28 
temp = list ( src_copy . get ( row , col )) ; temp [0] = 0 
29 
src_copy . set ( row , col , tuple ( temp ) ) 
30 
else : 
31 
for row in range ( rows ): 
32 
for col in range ( cols ): 
33 
temp = list ( src_copy . get ( row , col )) 
34 
if red == True : temp [0] = 0 
35 
if green == True : temp [1] = 0 
36 
if blue == True : temp [2] = 0 
37 
src_copy . set ( row , col , tuple ( temp ) ) 
38 
return src_copy 
39 
40 def convert_to_matrix ( lst , m , n): # converts a flattened r e p r e s e n t a t i o n into an mxn matrix 
such that m and n are known 
41 
mat = 
[] 
42 
for i in range (0 , len ( lst ) , n): 
43 
mat . append ( lst[i:i+n]) 
44 
return mat[:m] 
45 
46 def rotate_90 ( matrix ): # Rotates a given m x n matrix 90 degress clockwise 
47 
res = 
[] 
48 
for i in range ( len ( matrix [0]) ): 
49 
lst = 
[] 
50 
for j in range ( len ( matrix )): 
51 
lst . append ( matrix [j][i]) 
52 
# Reversing the matrix for 90 degree 
53 
lst . reverse () 
54 
res . append ( lst ) 
55 
return res 
56 
57 def rotations ( src: MyImage ) -> MyImage : 
58 
""" Returns an image containing the 4 rotations of src . 
59 
60 
The new image has twice the dimensions of src . src is not modified . 
61 
62 
Args : 
63 
- src : the image whose rotations have to be stored and returned . 
Page 16 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 
64 
65 
Returns : 
66 
an image twice the size of src and containing the 4 rotations of src . 
67 
""" 
68 
rows = src . size [1] 
69 
cols = src . size [0] 
70 
src_copy = MyImage (( cols * 2 , rows * 2)) 
71 
rot_90_lst = 
[] 
72 
rot_180_lst = 
[] 
73 
rot_270_lst = 
[] 
74 
rot_360_lst = 
[] 
75 
temp = 
[] 
76 
77 
for row in range ( rows ): 
78 
for col in range ( cols ): 
79 
temp . append ( src . get ( row , col ) ) 
80 
rot_360_lst = convert_to_matrix ( temp , rows , cols ) #Og image 
81 
# 90 degree clockwise rotation 
82 
rot_90_lst = rotate_90 ( rot_360_lst ) 
83 
# Image - 180 
84 
rot_180_lst = rotate_90 ( rot_90_lst ) 
85 
# Image - 90 a nt ic lo ck wi se 
86 
rot_270_lst = rotate_90 ( rot_180_lst ) 
87 
src_copy_lst = 
[] 
88 
for i in range ( rows * 2): 
89 
if i < rows : 
90 
for x in range ( len ( rot_270_lst [i]) ): 
91 
src_copy_lst . append ( rot_270_lst [i][x]) 
92 
for x in range ( len ( rot_360_lst [i]) ): 
93 
src_copy_lst . append ( rot_360_lst [i][x]) 
94 
else : 
95 
for x in range ( len ( rot_180_lst [i % rows ]) ): 
96 
src_copy_lst . append ( rot_180_lst [i % rows ][x]) 
97 
for x in range ( len ( rot_90_lst [i % rows ])): 
98 
src_copy_lst . append ( rot_90_lst [i % rows ][x]) 
99 
lst1 = convert_to_matrix ( src_copy_lst , rows *2 , cols *2 ) 
100 
for row in range ( rows *2): 
101 
for col in range ( cols *2): 
102 
src_copy . set( row , col , lst1 [ row ][ col ]) 
103 
return src_copy 
104 
105 def resize ( src : MyImage ) -> MyImage : 
106 
""" Returns an image which has twice the dimensions of src . 
107 
108 
The new image has twice the dimensions of src . src is not modified . 
109 
110 
Args : 
111 
- src : the image which needs to be resized . 
112 
113 
Returns : 
114 
an image twice the size of src . 
115 
""" 
116 
rows = src . size [1] 
117 
cols = src . size [0] 
118 
src_copy = MyImage (( cols * 2 , rows * 2)) 
119 
for row in range ( rows ): 
120 
for col in range ( cols ): 
121 
src_copy . set( row *2 , col *2 , src . get ( row , col )) 
122 
for row in range ( cols *2): 
123 
for col in range ( rows * 2): 
124 
if row % 2 == 0: # All even rows - not black rows 
125 
if col % 2 == 1: 
126 
if col == ( cols * 2) - 1: # The last column - edge case 
127 
pix = src_copy . get ( row , col - 1 ) 
128 
src_copy . set ( row , col , pix ) 
129 
else : 
Page 17 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 
130 
pix1 = src_copy . get ( row , col -1) 
131 
pix2 = src_copy . get ( row , col +1) 
132 
pix = (( pix1 [0] + pix2 [0]) // 2 , ( pix1 [1] + pix2 [1]) // 2 , ( pix1 [2] + 
pix2 [2]) // 2 ) 
133 
src_copy . set ( row , col , pix ) 
134 
else : pass 
135 
if row % 2 == 1: # Black rows 
136 
if col % 2 == 0: # Not completely black columns 
137 
if row == ( rows * 2) - 1: # Last row - edge case 
138 
pix = src_copy . get ( row - 1 , col ) 
139 
src_copy . set ( row , col , pix ) 
140 
else : 
141 
pix1 = src_copy . get ( row - 1 , col ) 
142 
pix2 = src_copy . get ( row + 1 , col ) 
143 
pix = (( pix1 [0] + pix2 [0]) // 2 , ( pix1 [1] + pix2 [1]) // 2 , ( pix1 [2] 
+ pix2 [2]) // 2) 
144 
src_copy . set ( row , col , pix ) 
145 
if col % 2 == 1: 
146 
if col == ( cols * 2) - 1: 
147 
pix = src_copy . get ( row , col - 1 ) 
148 
src_copy . set ( row , col , pix ) 
149 
else : 
150 
if row 
!= ( rows * 2) - 1: 
151 
pix1 = src_copy . get (( row - 1) , ( col - 1 )) 
152 
pix2 = src_copy . get (( row - 1) , ( col + 1 )) 
153 
pix3 = src_copy . get (( row + 1) , ( col + 1 )) 
154 
pix4 = src_copy . get (( row + 1) , ( col - 1 )) 
155 
pix = (( pix1 [0] + pix2 [0] + pix3 [0] + pix4 [0]) // 4 , ( pix1 [1] + 
pix2 [1] + pix3 [1] 
+ pix4 [1]) // 4 , ( 
pix1 [2] + pix2 [2] 
+ pix3 [2] + pix4 [2 
]) // 4) 
156 
src_copy . set( row , col , pix ) 
157 
158 
for row in range ( rows * 2): 
159 
for col in range ( cols * 2): 
160 
if row % 2 == 1 and col % 2 == 1: 
161 
if col == ( cols * 2) - 1: # Edge case - last col 
162 
pix = src_copy . get ( row , col - 1 ) 
163 
src_copy . set ( row , col , pix ) 
164 
elif row == ( row * 2) - 1: # Edge case - last row 
165 
pix = src_copy . get ( row - 1 , col ) 
166 
src_copy . set ( row , col , pix ) 
167 
else : 
168 
if row 
!= ( rows * 2) - 1: 
169 
pix1 = src_copy . get (( row - 1) , ( col - 1 )) 
170 
pix2 = src_copy . get (( row - 1) , ( col + 1 )) 
171 
pix3 = src_copy . get (( row + 1) , ( col + 1 )) 
172 
pix4 = src_copy . get (( row + 1) , ( col - 1 )) 
173 
pix = (( pix1 [0] + pix2 [0] + pix3 [0] + pix4 [0]) // 4 , ( pix1 [1] + pix2 [1 
] + pix3 [1] + pix4 [1]) 
// 4 , ( pix1 [2] + pix2 
[2] + pix3 [2] + pix4 [2 
]) // 4) 
174 
src_copy . set ( row , col , pix ) 
175 
else : 
176 
pix1 = src_copy . get ( row , col - 1) 
177 
pix2 = src_copy . get ( row , col + 1) 
178 
pix = (( pix1 [0] + pix2 [0]) // 2 , ( pix1 [1] + pix2 [1]) // 2 , ( pix1 [2] 
+ pix2 [2]) // 2) 
179 
src_copy . set ( row , col , pix ) 
180 
return src_copy 
181 
182 def maskreader ( maskfile ): # Reads the maskfile and returns a list with values of maskfile 
183 
✬✬✬ 
Page 18 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 
184 
Returns a tuple of mask list and length . 
185 
This is a helper function that is used in apply_mask function to read 
186 
the mask file and return a list of n by n. 
187 
188 
maskfile is a text file containing n by n mask . 
189 
190 
Args : 
191 
- maskfile : path to file specifying mask 
192 
193 
Returns : 
194 
Tuple of lst of n by n and length 
195 
✬✬✬ 
196 
f = open ( maskfile , ✬r✬); 
197 
lst = 
[] 
198 
for i in f: 
199 
lst . append (int( i)) 
200 
mat_len = lst [0]; mask_lst = lst [1::] 
201 
f. close () 
202 
return 
( mask_lst , mat_len ) 
203 
204 def apply_mask ( src : MyImage , maskfile : str , average : bool = True ) -> MyImage : 
205 
""" Returns an copy of src with the mask from maskfile applied to it. 
206 
207 
maskfile specifies a text file which contains an n by n mask . It has the 
208 
following format : 
209 
- the first line contains n 
210 
- the next n^2 lines contain 1 element each of the flattened mask 
211 
212 
Args : 
213 
- src : the image on which the mask is to be applied 
214 
- maskfile : path to a file specifying the mask to be applied 
215 
- average : if True , averaging should to done when applying the mask 
216 
217 
Returns : 
218 
an image which the result of applying the specified mask to src . 
219 
""" 
220 
rows = src . size [1]; cols = src . size [0] 
221 
src_copy = MyImage ( src . size ) 
222 
# for row in range ( rows ): 
223 

for col in range ( cols ): 
224 

src_copy . set (row , col , src . get (row , col )) 
225 
vals = maskreader ( maskfile ) 
226 
mask_lst = vals [0]; n = vals [1] 
227 
# print (f" Mask list : { mask_lst } \n length = {n} \n center at { center } with value { 
mask_lst [ center ]}") 
228 
for i , pixels in enumerate ( src ): 
229 
row , col = divmod (i , cols ) # gives row index with co rre sp on di ng 
column index to 
iterate over 
230 
# print (row , col ) 
231 
val = 0; total = 0 
232 
for x in range ( n): 
233 
for y in range ( n): 
234 
mask_row = x - (n // 2) # Computing row mask 
235 
mask_col = y - (n // 2) # Computing col mask 
236 
if row + mask_row >= 0 and row + mask_row < rows and col + mask_col >= 0 and 
col + mask_col < cols : 
237 
total += mask_lst [n * x + y] 
238 
pix = src . get ( row + mask_row , col + mask_col ) 
239 
# print (f" Row { row } 
Col { col } 
RowMask { mask_row } 
ColMask { mask_col } 
pixel { pix }") 
240 
val += (( pix [0] + pix [1] + pix [2]) ) // 3 * mask_lst [n * x + y] 
241 
if average == True : val = val // total 
242 
if val > 255 : val = 255 
243 
if val < 0: val = 0 
244 
src_copy . set ( row , col , ( val , val , val )) 
245 
return src_copy 
Page 19 of 20CS 201 Data Structures II Homework 1: Lists Spring 2023 
Code Listing 3: Image Operations 
Page 20 of 20

More products