HyperLearning AI - Introduction to Python

An introductory course to the Python 3 programming language, with a curriculum aligned to the Certified Associate in Python Programming (PCAP) examination syllabus (PCAP-31-02).
https://knowledgebase.hyperlearning.ai/courses/introduction-to-python

04. Data Aggregates Part 1

https://knowledgebase.hyperlearning.ai/courses/introduction-to-python/modules/4/data-aggregates-part-1

In this module we will cover advanced operations with strings and lists, namely:

  • Advanced Strings - immutability, encodings, escape sequences, string comparisons, multi-line strings, slicing, copying, cloning, and other common string methods and functions
  • Advanced Lists - indexing, slicing, iterating, list comprehension, copying, cloning, and other common list methods and functions
  • Matrices and Cubes - lists within lists

1. Advanced Strings

1.1. Character Encodings

In [3]:
# Include a Unicode character in a Python 3 string literal
hospital_in_french = 'hôpital'
hospital_in_japanese = '病院'
hospital_in_arabic = 'مستشفى'
print(f'The name for Hospital in French is: {hospital_in_french}')
print(f'The name for Hospital in Japanese is: {hospital_in_japanese}')
print(f'The name for Hospital in Arabic is: {hospital_in_arabic}')
The name for Hospital in French is: hôpital
The name for Hospital in Japanese is: 病院
The name for Hospital in Arabic is: مستشفى
In [5]:
# Include a Unicode character in a Python 3 identifier
日本の人口 = 126_500_000
print(f'The population of Japan is: {日本の人口}')
The population of Japan is: 126500000
In [6]:
# Usage of the encode() string method
directions = 'The name of the hospital is Charité - Universitätsmedizin Berlin'
print(directions.encode(encoding="ascii", errors="backslashreplace"))
print(directions.encode(encoding="ascii", errors="ignore"))
print(directions.encode(encoding="ascii", errors="namereplace"))
print(directions.encode(encoding="ascii", errors="replace"))
print(directions.encode(encoding="ascii", errors="xmlcharrefreplace"))
b'The name of the hospital is Charit\\xe9 - Universit\\xe4tsmedizin Berlin'
b'The name of the hospital is Charit - Universittsmedizin Berlin'
b'The name of the hospital is Charit\\N{LATIN SMALL LETTER E WITH ACUTE} - Universit\\N{LATIN SMALL LETTER A WITH DIAERESIS}tsmedizin Berlin'
b'The name of the hospital is Charit? - Universit?tsmedizin Berlin'
b'The name of the hospital is Charité - Universitätsmedizin Berlin'
In [39]:
# Usage of the ascii() function
names = ['Quddus', 'Gößmann', 'José']
print(ascii(names))
['Quddus', 'G\xf6\xdfmann', 'Jos\xe9\u611b']
In [38]:
# Usage of the ord() function
dragon = "竜"
print(f'The Unicode code point value for {dragon} is {ord(dragon)}')
The Unicode code point value for 愛 is 24859

1.2. Escape Sequences

In [41]:
# Usage of escape characters
print('Escaping a \' single quote character')
print("Escaping a \" double quote character")
print('Escaping a \\ backslash character')
print('Escaping a \
newline character')
print('Escaping an \a ASCII bell character')
print('Escaping an \b ASCII backspace character')
print('Escaping an \f ASCII formfeed character')
print('Escaping an \n ASCII linefeed character')
print('Escaping an \r ASCII carriage return character')
print('Escaping an \t ASCII horizontal tab character')
print('Escaping an \v ASCII vertical tab character')

# Usage of escape sequences
print('Escaping the \xf6 German umlaut o character')
print('Escaping the \N{MOUSE} Unicode mouse character')
print('Escaping the \u2708 Unicode airplane character')
Escaping a ' single quote character
Escaping a " double quote character
Escaping a \ backslash character
Escaping a newline character
Escaping an  ASCII bell character
Escaping an  ASCII backspace character
Escaping an  ASCII formfeed character
Escaping an 
 ASCII linefeed character
 ASCII carriage return character
Escaping an 	 ASCII horizontal tab character
Escaping an  ASCII vertical tab character
Escaping the ö German umlaut o character
Escaping the 🐁 Unicode mouse character
Escaping the ✈ Unicode airplane character

1.3. Immutable Strings

In [43]:
# Try to change a character in a string
test_string = 'Hello World'
print(test_string[6])
test_string[6] = "Q"
W
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-43-e6985690a63c> in <module>
      2 test_string = 'Hello World'
      3 print(test_string[6])
----> 4 test_string[6] = "Q"

TypeError: 'str' object does not support item assignment
In [78]:
# Apply the id() function to strings
my_first_string = 'abracadabra'
my_second_string = 'abracadabra'
print(f'id(my_first_string) = {id(my_first_string)}')
print(f'id(my_second_string) = {id(my_second_string)}')

# Apply the id() function to each character in a string
for idx in range(0, len(my_first_string)):
    print(f'{my_first_string[idx]} = {id(my_first_string[idx])}')
id(my_first_string) = 140669325644208
id(my_second_string) = 140669325644208
a = 140669646981680
b = 140669647076336
r = 140669647801520
a = 140669646981680
c = 140669647497712
a = 140669646981680
d = 140669647497456
a = 140669646981680
b = 140669647076336
r = 140669647801520
a = 140669646981680
In [59]:
# Strings are immutable, but variables can be changed to point to different things
my_string = 'I am a Data Scientist'
print(my_string)
my_string = 'I am a Software Engineer'
print(my_string)
I am a Data Scientist
I am a Software Engineer

1.4. Multi-Line Strings

In [67]:
my_multiline_string = '''Line 1\tEOL 
Line 2\t\tEOL
Line 3    EOL'''
print(my_multiline_string)
Line 1	EOL 
Line 2		EOL
Line 3    EOL

1.5. String Comparisons

In [94]:
# Represent the German umlaut using two different code point sequences
umlaut_sequence_1 = '\u00F6'
umlaut_sequence_2 = '\u006F\u0308'
print(f'{umlaut_sequence_1} has length {len(umlaut_sequence_1)}')
print(f'{umlaut_sequence_2} has length {len(umlaut_sequence_2)}')
ö has length 1
ö has length 2
In [96]:
# Compare strings that contain different code point sequences
import unicodedata
print(umlaut_sequence_1 == umlaut_sequence_2)
print(unicodedata.normalize('NFD', umlaut_sequence_1) == unicodedata.normalize('NFD', umlaut_sequence_2))
False
True

1.6. Advanced String Slicing

In [105]:
# Create a string
my_string = 'abracadabra'

# Extract characters of a string that have even indexes using the stride size argument
print(my_string[::2])

# Use a negative stride size argument to extract in reverse order
print(my_string[::-2])

# Extract a defined subset of characters with a stride size of 2 within that subset
print(my_string[4:10:2])

# Extract characters with even indexes starting from the 5th character
print(my_string[4::2])
arcdba
abdcra
cdb
cdba

1.7. Copying and Cloning Strings

In [10]:
# Create two variables to point to the same string
my_first_string = 'abracadabra'
my_second_string = 'abracadabra'
print(f'id(my_first_string) = {id(my_first_string)}')
print(f'id(my_second_string) = {id(my_second_string)}')
id(my_first_string) = 140605555739120
id(my_second_string) = 140605555739120
In [12]:
# Create a new variable bound to a subset of a string using slice notation
my_third_string = my_first_string[4:]
print(f'my_third_string = \'{my_third_string}\'')
print(f'id(my_third_string) = {id(my_third_string)}')
my_third_string = 'cadabra'
id(my_third_string) = 140605555271216

1.8. Common String Methods

In [120]:
# isupper()
print('MY NAME IS JILLUR'.isupper())

# islower()
print('my name is jillur Q'.islower())

# isalpha()
print('learning python'.isalpha())

# isalnum()
print('learning python 3'.isalnum())

# isdecimal()
print('01092020'.isdecimal())

# isspace()
print(' \t\n\t\v  '.isspace())

# istitle()
print('Jillur Quddus'.istitle())

# capitalize()
print('capitalize me'.capitalize())
True
False
False
False
True
True
True
Capitalize me

1.9. Common String Functions

In [124]:
# len()
print(len('abracadabra'))

# chr()
print(chr(9786))

# ord()
print(ord('愛'))
11
☺
24859

2. Advanced Lists

2.1. Index and Negative Indexing

In [2]:
# Create a list containing the first ten square numbers
squares = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
print(squares)

# Access elements in a list by their index numbers
print(squares[0])
print(squares[3])
print(squares[-1])
print(squares[-4])
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
1
16
100
49

2.2. Advanced List Slicing

In [13]:
# Extract elements from a list that have even indexes using the stride size argument
print(squares[::2])

# Use a negative stride size argument to extract elements in reverse order
print(squares[::-2])

# Extract a defined subset of elements with a stride size of 2 within that subset
print(squares[4:8:2])

# Extract elements with even indexes starting from the 5th element
print(squares[4::2])
[1, 9, 25, 49, 81]
[100, 64, 36, 16, 4]
[25, 49]
[25, 49, 81]

2.3. Advanced List Slice Assignment

In [29]:
# Define a list of numbers
my_numbers = [1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
print(f'My list of numbers (first 10 triangle numbers): {my_numbers}')

# Substitute a subset of the list with new elements
my_numbers[1:3] = [4, 9]
print(f'My list of numbers (substitutions): {my_numbers}')

# Replace every Nth element with a new value, where N = 3
my_numbers[::3] = [1, 16, 49, 100]
print(f'My list of numbers (n-th replacements): {my_numbers}')

# Replace and resize a subset of the list
my_numbers[4:] = [25, 36, 49, 64]
print(f'My list of numbers (first 8 square numbers): {my_numbers}')

# Delete every Nth element starting from the 2nd element and where N = 2
del my_numbers[1::2]
print(f'My list of numbers (every other square number): {my_numbers}')
My list of numbers (first 10 triangle numbers): [1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
My list of numbers (substitutions): [1, 4, 9, 10, 15, 21, 28, 36, 45, 55]
My list of numbers (n-th replacements): [1, 4, 9, 16, 15, 21, 49, 36, 45, 100]
My list of numbers (first 8 square numbers): [1, 4, 9, 16, 25, 36, 49, 64]
My list of numbers (every other square number): [1, 9, 25, 49]

2.4. Shallow and Deep List Copies

In [48]:
# Define a list of phrases
my_phrases = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
print(f'Original list of phrases: {my_phrases}')
    
# Create a shallow copy of the original list using slice notation, plus append a new element
my_shallow_phrases = my_phrases[:2] + [['j', 'k', 'l']]
print(f'Shallow copy of my phrases: {my_shallow_phrases}')
    
# Alternatively you may use the list() function to create a shallow copy
my_other_shallow_phrases = list(my_phrases) + [['j', 'k', 'l']]
print(f'Another shallow copy of my phrases: {my_other_shallow_phrases}')

# Make a change to the original list of phrases only
my_phrases[0][0] = 'ALPHA'
my_phrases[0][1] = 'BETA'
my_phrases[0][2] = 'GAMMA'
print(f'\nUpdated original list of phrases: {my_phrases}')

# Examine the shallow copies of the original list
print(f'Shallow copy of my phrases: {my_shallow_phrases}')
print(f'Another shallow copy of my phrases: {my_other_shallow_phrases}')
Original list of phrases: [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
Shallow copy of my phrases: [['a', 'b', 'c'], ['d', 'e', 'f'], ['j', 'k', 'l']]
Another shallow copy of my phrases: [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['j', 'k', 'l']]

Updated original list of phrases: [['ALPHA', 'BETA', 'GAMMA'], ['d', 'e', 'f'], ['g', 'h', 'i']]
Shallow copy of my phrases: [['ALPHA', 'BETA', 'GAMMA'], ['d', 'e', 'f'], ['j', 'k', 'l']]
Another shallow copy of my phrases: [['ALPHA', 'BETA', 'GAMMA'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['j', 'k', 'l']]
In [49]:
# Create a deep copy of the original list
import copy

my_phrases = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
my_deep_phrases = copy.deepcopy(my_phrases)
print(f'Original list of phrases: {my_phrases}')
print(f'Deep copy of my phrases: {my_deep_phrases}')

# Make a change to the original list of phrases only
my_phrases[0][0] = 'ALPHA'
my_phrases[0][1] = 'BETA'
my_phrases[0][2] = 'GAMMA'
print(f'\nUpdated original list of phrases: {my_phrases}')

# Examine the deep copy of the original list
print(f'Deep copy of my phrases: {my_deep_phrases}')
Original list of phrases: [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
Deep copy of my phrases: [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]

Updated original list of phrases: [['ALPHA', 'BETA', 'GAMMA'], ['d', 'e', 'f'], ['g', 'h', 'i']]
Deep copy of my phrases: [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]

2.5. Iterating Lists

In [57]:
# Create a list
my_diatomic_list = [0, 1, 1, 2, 1, 3, 2, 3, 1, 4, 3, 5, 2, 5, 3, 4]

# Iterate the list using a while loop
i = 0
while i < len(my_diatomic_list):
    print(f'Diatomic Sequence - Element #{i + 1}: {my_diatomic_list[i]}')
    i += 1
Diatomic Sequence - Element #1: 0
Diatomic Sequence - Element #2: 1
Diatomic Sequence - Element #3: 1
Diatomic Sequence - Element #4: 2
Diatomic Sequence - Element #5: 1
Diatomic Sequence - Element #6: 3
Diatomic Sequence - Element #7: 2
Diatomic Sequence - Element #8: 3
Diatomic Sequence - Element #9: 1
Diatomic Sequence - Element #10: 4
Diatomic Sequence - Element #11: 3
Diatomic Sequence - Element #12: 5
Diatomic Sequence - Element #13: 2
Diatomic Sequence - Element #14: 5
Diatomic Sequence - Element #15: 3
Diatomic Sequence - Element #16: 4
In [58]:
# Iterate the list using a for loop with the range function
for x in range(len(my_diatomic_list)):
    print(f'Diatomic Sequence - Element #{x + 1}: {my_diatomic_list[x]}')
Diatomic Sequence - Element #1: 0
Diatomic Sequence - Element #2: 1
Diatomic Sequence - Element #3: 1
Diatomic Sequence - Element #4: 2
Diatomic Sequence - Element #5: 1
Diatomic Sequence - Element #6: 3
Diatomic Sequence - Element #7: 2
Diatomic Sequence - Element #8: 3
Diatomic Sequence - Element #9: 1
Diatomic Sequence - Element #10: 4
Diatomic Sequence - Element #11: 3
Diatomic Sequence - Element #12: 5
Diatomic Sequence - Element #13: 2
Diatomic Sequence - Element #14: 5
Diatomic Sequence - Element #15: 3
Diatomic Sequence - Element #16: 4
In [59]:
# Iterate the list using a for loop with the in operator
for elem in my_diatomic_list:
    print(elem)
0
1
1
2
1
3
2
3
1
4
3
5
2
5
3
4
In [63]:
# Iterate the list using a for loop with the in operator and enumerate function
for idx, elem in enumerate(my_diatomic_list):
    print(f'Diatomic Sequence - Element #{idx + 1}: {elem}')
Diatomic Sequence - Element #1: 0
Diatomic Sequence - Element #2: 1
Diatomic Sequence - Element #3: 1
Diatomic Sequence - Element #4: 2
Diatomic Sequence - Element #5: 1
Diatomic Sequence - Element #6: 3
Diatomic Sequence - Element #7: 2
Diatomic Sequence - Element #8: 3
Diatomic Sequence - Element #9: 1
Diatomic Sequence - Element #10: 4
Diatomic Sequence - Element #11: 3
Diatomic Sequence - Element #12: 5
Diatomic Sequence - Element #13: 2
Diatomic Sequence - Element #14: 5
Diatomic Sequence - Element #15: 3
Diatomic Sequence - Element #16: 4

2.6. List Membership

In [65]:
# Test whether an element exists in a list
squares = [1, 4, 9, 16, 25]
x = 16
if x in squares:
    print(f"{x} exists in our list of square numbers")
else:
    print(f"{x} does not exist in our list of square numbers")
    
# Test whether an element is NOT in a list
y = 169
if y not in squares:
    print(f"{y} does not exist in our list of square numbers")
else:
    print(f"{y} exists in our list of square numbers")
16 exists in our list of square numbers
169 does not exist in our list of square numbers

2.7. List Comprehension

In [68]:
# Create a list of square numbers using list comprehension
squares = [num * num for num in range(1, 9)]
print(squares)
[1, 4, 9, 16, 25, 36, 49, 64]
In [71]:
# Create a list formed of characters from a string
letters_in_abibliophobia = [character for character in 'abibliophobia']
print(letters_in_abibliophobia)
['a', 'b', 'i', 'b', 'l', 'i', 'o', 'p', 'h', 'o', 'b', 'i', 'a']
In [76]:
# Create a list of all the prime numbers between 1 and 100
def isPrime(num):
    if num <= 1 or num % 1 > 0:
        return False
    for i in range(2, num//2):
        if num % i == 0:
            return False
    return True

prime_numbers = [i for i in range(1, 101) if isPrime(i)]
print(prime_numbers)
[2, 3, 4, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
In [77]:
# Create a list of all the even numbers between 1 and 100, and replace the odd numbers with 0
even_numbers_zeroed_odd = [i if i % 2 == 0 else 0 for i in range(1, 101)]
print(even_numbers_zeroed_odd)
[0, 2, 0, 4, 0, 6, 0, 8, 0, 10, 0, 12, 0, 14, 0, 16, 0, 18, 0, 20, 0, 22, 0, 24, 0, 26, 0, 28, 0, 30, 0, 32, 0, 34, 0, 36, 0, 38, 0, 40, 0, 42, 0, 44, 0, 46, 0, 48, 0, 50, 0, 52, 0, 54, 0, 56, 0, 58, 0, 60, 0, 62, 0, 64, 0, 66, 0, 68, 0, 70, 0, 72, 0, 74, 0, 76, 0, 78, 0, 80, 0, 82, 0, 84, 0, 86, 0, 88, 0, 90, 0, 92, 0, 94, 0, 96, 0, 98, 0, 100]

2.8. Common List Methods

In [78]:
# Create a list of square numbers
squares = [1, 4, 9, 16]
more_squares = [25, 36, 49, 64, 81, 100]

# list.append(element)
squares.append(25)
print(squares)

# list.extend(newlist)
del more_squares[0]
squares.extend(more_squares)
print(squares)

# list.insert(index, element)
squares.insert(0, 0)
print(squares)

# list.remove(element)
squares.remove(0)
print(squares)

# list.pop([index])
squares.pop()
print(squares)

# list.clear()
squares.clear()
print(squares)
[1, 4, 9, 16, 25]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81]
[]
In [79]:
# Populate the list of square numbers again
squares.extend([1, 4, 9, 16, 25, 36, 49, 64, 81, 100])

# list.index(element[, start[, end]])
print(squares.index(64))

# list.count(element)
print(squares.count(169))

# list.sort()
squares.sort()
print(squares)

# list.reverse()
squares.reverse()
print(squares)

# list.copy()
squares_copy = squares.copy()
print(squares_copy)
7
0
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[100, 81, 64, 49, 36, 25, 16, 9, 4, 1]
[100, 81, 64, 49, 36, 25, 16, 9, 4, 1]

2.9. Common List Functions

In [81]:
# Create a list of numbers
my_numbers = [34, 13, 101, 4, 10, 24, 7]

# Create a list of letters
my_letters = ['j', 'z', 'e', 'f', 'x']

# len()
print(len(my_numbers))

# sorted()
print(sorted(my_numbers))
print(sorted(my_letters))

# max()
print(max(my_numbers))
print(max(my_letters))

# min()
print(min(my_numbers))
print(min(my_letters))
7
[4, 7, 10, 13, 24, 34, 101]
['e', 'f', 'j', 'x', 'z']
101
z
4
e

3. Lists in Lists

3.1. Multi-Dimensional Arrays

3.1.1. Two-Dimensional Arrays

In [32]:
# Create a two-dimensional array
my_2d_array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for row in my_2d_array:
    for elem in row:
        print(elem, end=' ')
    print()
1 2 3 
4 5 6 
7 8 9 
In [41]:
# Create a two-dimensional array with list comprehension
number_cols = 3
number_rows = 3
my_2d_array = [[0 for i in range(number_cols)] for j in range(number_rows)]
for row in my_2d_array:
    for elem in row:
        print(elem, end=' ')
    print()
0 0 0 
0 0 0 
0 0 0 
In [47]:
# Access elements using square brackets and indices
my_2d_array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(my_2d_array[0][0])
print(my_2d_array[1][1])
print(my_2d_array[2][2])
1
5
9
In [59]:
# Create a two-dimensional array
my_2d_array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

# Update a specific element in our two-dimensional array
my_2d_array[1][1] = 0

# Insert a new row in our two-dimensional array at a given row number using the insert method
my_2d_array.insert(2, [9, 9, 9])

# Append a new row to our two-dimensional array using the append method
my_2d_array.append([7, 4, 7])

# Append elements to an existing row in our two-dimensional array at a given row number using the extend method
my_2d_array[0].extend([0, 0])
my_2d_array[1].extend([0, 0])
my_2d_array[2].extend([0, 0])
my_2d_array[3].extend([0, 0])
my_2d_array[4].extend([0, 0])

# Reverse the order of the elements in a given row in our two-dimensional array using the reverse method
my_2d_array[2].reverse()

# Delete a row at a given row number from our two-dimensional array
del my_2d_array[3]

# Display out final two-dimensional array
for row in my_2d_array:
    for elem in row:
        print(elem, end=' ')
    print()
1 2 3 0 0 
4 0 6 0 0 
0 0 9 9 9 
7 4 7 0 0 
In [57]:
for row in my_2d_array:
    for elem in row:
        print(elem, end=' ')
    print()
1 2 3 0 0 
4 0 6 0 0 
0 0 9 9 9 
7 8 9 0 0 
7 4 7 0 0 

3.1.2. Three-Dimensional Arrays

In [78]:
import pprint

# Create a three-dimensional array of size 3 x 3 x 3
my_3d_array = [[[x + y + z for x in range(3)] for y in range(3)] for z in range(3)]
pprint.pprint(my_3d_array)

# Access a list element in our three-dimensional array
print(my_3d_array[1][2])

# Access a specific element in our three-dimensional array 
print(my_3d_array[2][0][1])
[[[0, 1, 2], [1, 2, 3], [2, 3, 4]],
 [[1, 2, 3], [2, 3, 4], [3, 4, 5]],
 [[2, 3, 4], [3, 4, 5], [4, 5, 6]]]
[3, 4, 5]
3

4. Comparing Sequences

In [5]:
# Compare two given strings using comparison operators
print("Hello" > "Hello")
print("Hello" < "Hello")
print("abracadabra" > "Hello")
print("abracadabra" > "Hello")
print('a' < 'b' < 'c')
False
False
True
True
True
In [3]:
# Compare two given lists using comparison operators
print([1, 2, 3] > [1, 2, 3])
print([1, 2, 3] < [1, 2, 3])
print([1, 2, 3] > [1, 2, 4])
print([1, 2, 3] < [1, 2, 4])
False
False
False
True