Mastering Python

Source: https://www.w3resource.com/python-exercises/python_100_exercises_with_solutions.php

Exercise 1:

Create a list with values ranging from 0 to 9.

soln

lists take in iterators

#my_list = [i for i in range(10)]
my_list = list(range(10))
my_list

output

0123456789

Exercise 2:

Convert a list of integers to a list of strings.

soln

map(function, iterable, *iterables) map returns an iterator. it applies fn to an iterator with iterable args.

my_list_as_strs = list(map(str, my_list))
my_list_as_strs

output

0123456789

Exercise 3:

Multiply all elements in a list by 2.

soln

a very functional programming approach; manipulating data with subsequent functional transformations.

also, unusually I could not find any documentation on lambda expressions in the main Python Standard Library. I had to click into the tutorial and take a look at “more control flow tools”.

another_list = list(range(5))
times_two_list = list(map(lambda x: 2*x, another_list))
times_two_list

output

02468

Exercise 4:

Extract all odd numbers from a list of integers.

soln

maps continue to be useful, however perhaps a filter will be a better idea here.

another_list = list(range(20))
odd_lists = list(filter(lambda x: x%2==1, another_list))
odd_lists

the modulo 2 case would equal 1 whenever an odd number was given. we’re spitting out the cases of which that was true:

output

135791113151719

Exercise 5:

Replace all odd numbers in a list with -1.

soln

we go back to a map for this one.

note that the ternary operator syntax is different to C/Java.

another_list = list(range(20))
odd_lists_minus_one = list(map(lambda x:-1 if x%2==1 else x, another_list))
odd_lists_minus_one

output

0-12-14-16-18-110-112-114-116-118-1

Exercise 6:

Convert a list of integers to a list of booleans where all non-zero values become True.

soln

note that in Python, true is actually True and false, False.

list_ints = list(range(15))
bool_list = list(map(lambda x: True if x != 0 else False, list_ints))
bool_list

output

FalseTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrueTrue

Exercise 7:

Replace all even numbers in a list with their negative.

list_ints = list(range(15))
neg_list = list(map(lambda x: -x if x % 2 == 0 else x, list_ints))
neg_list

Exercise 8:

Create a 3x3 list of lists with random values and normalize it.

soln

crazy: notice that the randint bounds are <= and >=!

import random
random.seed(4)
def create_n_by_n_list(n):
        return [[random.randint(0,n) for i in range(n)] for i in list(range(0,n))]
def normalise_list(l, n):
        import numpy
        return numpy.array(l) / n
my_list = create_n_by_n_list(6)
norm_list = normalise_list(my_list, 6)
print(norm_list)

output

I generalised the problem to nxn.

also I used numpy to skip a list comprehension.

[[0.16666667 0.33333333 0.         0.83333333 0.5        0.5       ]
 [0.16666667 0.         0.         0.         0.5        0.66666667]
 [0.33333333 1.         1.         0.         0.16666667 0.66666667]
 [0.66666667 0.33333333 0.33333333 1.         0.16666667 1.        ]
 [0.         0.33333333 0.16666667 0.         1.         0.83333333]
 [1.         0.33333333 1.         0.33333333 0.16666667 0.16666667]]

Exercise 9:

Calculate the sum of the diagonal elements of a 3x3 matrix (list of lists).

soln

import numpy
print(sum(numpy.diag(norm_list)))

Exercise 10:

Find the indices of non-zero elements in a list.

soln

this notation is illegal: lambda i, v:

new_list = list(range(-5, 4))
tuple_list = filter(lambda t: t[1] != 0, enumerate(new_list)) # filter correct tuples
out_list = [e[0] for e in tuple_list] # construct list of indices
out_list

output

fk that was hard.

01234678

Exercise 11:

Reverse a list.

soln

one thing to be careful of with the list.reverse() method is that the reversal happens “in-place”, i.e. on the object that the method was called on.

out_list.reverse() # no return value for this
print(out_list)
print(new_list) # defined in the last q
print(reversed(new_list)) # returns an iterator object
print(list(reversed(new_list)))

further, it must noted that all the above are “shallow-copies”, whilst they are fast, if the objects which constitute the list are mutable, then you could run into problems with the reversed list misbehaving later:

x = 6
a = 7
b = 8
var_list = [x, a, b]
print(f"var_list: {var_list}")
stable_list = var_list[::-1]
question_list = list(reversed(var_list))
x = 1
a = 2
b = 3
unstable_list = list(reversed(var_list))
print(question_list)
print(unstable_list)
print(stable_list)

now, notice that you STILL cannot see a difference! this is because your x,a,b variables are immutable; they are integers.

var_list: [6, 7, 8]
[8, 7, 6]
[8, 7, 6]
[8, 7, 6]

try this code

x = [6]
a = [7]
b = [8]
var_list = [x, a, b]
print(f"var_list: {var_list}")
stable_list = var_list[::-1]
question_list = list(reversed(var_list))
x.append(1)
a.append(2)
b.append(3)
unstable_list = list(reversed(var_list))
print(f"question_list: {question_list}")
print(f"unstable_list: {unstable_list}")
print(f"stable_list: {stable_list}")

ultimately, if you want a non-shallow copy you must use deepcopy

import copy
stable_list = copy.deepcopy(var_list)
print(f"stable_list: {stable_list}")
# and now, even if you mutate the lists, stable_list does not change but unstable_list will:
x.pop()
print(f"unstable_list: {unstable_list}")
print(f"still stable: {stable_list}")

Exercise 12:

Create a 3x3 identity matrix as a list of lists.

import numpy as np
print(np.eye(3))

Exercise 13:

Reshape a 1D list to a 2D list with 2 rows.

soln1

l = np.array(range(12))
print(l.reshape(2, -1))

output

[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]]

soln2, no numpy

l = list(range(12))
x = [l[x:x+int(len(l)/2)] for x in range(0, len(l), int(len(l)/2))]
print(x)

output

terrific, well done!

[[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11]]

Exercise 14:

Stack two lists vertically.

l1 = list(range(4))[::-1]
l2 = list(range(4))
l = [l1, l2]
print(l)

Exercise 15:

Get the common items between two lists.

shit, I accidentally got all the unique items by using sets

l1 = list(range(4))[::-1]
l2 = list(range(7))
l1.extend(l2)
s = list(set(l1))
print(s)

that’s okay, it’s not much different to find the duplicates; we can use the intersection method of sets

l1 = list(range(4))[::-1]
l2 = list(range(7))
dupes = list(set(l1).intersection(set(l2)))
# also, note that the intersection method can accept any iterable! thus this works too:
dupes = list(set(l1).intersection(l2))
print(dupes)

output

[0, 1, 2, 3]

Exercise 16:

Create a 5x5 list of lists with row values ranging from 0 to 4.

soln1

import random
random.seed(4)
n = 5
l = [ [random.randint(0,n-1) for i in range(n)] for i in range(n)]
print(l)

soln2

i believe we can accomplish the same thing more quickly with numpy:

import numpy
m = numpy.random.randint(5, size=(5,5))
print(m)

timing

import timeit

# Setup code for the list-comprehension approach
setup1 = """
import random
random.seed(4)
n = 5
"""

# The statement we want to time repeatedly
stmt1 = """
l = [[random.randint(0, n - 1) for i in range(n)] for j in range(n)]
"""

# Setup code for the NumPy approach
setup2 = """
import numpy
"""

# The statement we want to time repeatedly
stmt2 = """
m = numpy.random.randint(5, size=(5, 5))
"""

# Number of iterations to run timeit
iterations = 1_000_000

time1 = timeit.timeit(stmt=stmt1, setup=setup1, number=iterations)
time2 = timeit.timeit(stmt=stmt2, setup=setup2, number=iterations)

print(f"List comprehension approach: {time1:.6f} seconds")
print(f"NumPy approach:              {time2:.6f} seconds")

Exercise 17:

Find the index of the maximum value in a list.

soln

max(max(l))

and for a single dimensional array (the above was 2d)

max(range(15))

however, the number of max calls is clearly dependent on the dimensionality. as such we can use numpy:

numpy.amax(l)

Exercise 18:

Normalize the values in a list between 0 and 1.

we can do it nakedly with the math library and implement softmax, which is defined in multi-variate calculus.

import math
my_list = list(range(7))
new_list = list(map(lambda x: math.exp(x) / sum(math.exp(y) for y in my_list), my_list))
print(new_list)
print(sum(new_list)) # checking it all sums to 1
import numpy as np
def softmax(x):
    return np.exp(x) / sum(np.exp(x))

print(sum(softmax(my_list)))
print(softmax(my_list))

Exercise 19:

Calculate the dot product of two lists.

random.seed(4)
list_a = random.choices(range(10),k=10) # without numpy
list_b = random.choices(range(10),k=10)
print(list_a)
print(list_b)
dot_p = sum(list(map(math.prod, zip(list_a,list_b))))
print(dot_p)

Exercise 20:

Count the number of elements in a list within a specific range.

def count_elements_within_range(a, b, x):
    return sum(a <= y <= b for y in x)
count_elements_within_range(5, 12, list(range(14))[5::3])

Exercise 21:

Find the mean of each row in a 2D list.

def average(l):
    return sum(l)/len(l)

""" takes in list of lists
    returns list of averages, one for each row
"""
def mean_list_of_rows(ml):
  return [average(x) for x in ml]

my_list = [[1,2,3],[4,5],[3,3]]
mean_list_of_rows(my_list)

Exercise 22:

Create a random 4x4 list of lists and extract the diagonal elements.

import numpy as np
list_of_lists = np.random.randint(10, size=(4,4))
print(list_of_lists)
np.diag(list_of_lists)

Exercise 23:

Count the number of occurrences of a specific value in a list.

range_list = list(range(6))
range_list.count(4)

Exercise 24:

Replace all values in a list with the mean of the list.

range_list = list(range(6))
range_list = [average(range_list) for x in range_list]
print(range_list)

Exercise 25:

Find the indices of the maximum and minimum values in a list.

range_list = list(range(6))
print(range_list.index(min(range_list)))
print(range_list.index(max(range_list)))

you of course also have the numpy method, however that requires the overhead of converting to a numpy array first:

range_list = list(range(6))
print(np.argmin(range_list))
print(np.argmax(range_list))

Exercise 26:

Create a 2D list with 1 on the border and 0 inside.

# note this program only works for odd n
n = 3
mat = np.ones((n,n))
mat[n//2][n//2] = 0
print(mat)

Exercise 27:

Find the unique values and their counts in a list.

l1 = list(range(6))
l2 = list(range(2,7))
l1.extend(l2)
uniq = list(set(l1))
counts = {x: l1.count(x) for x in l1}
print(counts)
print(uniq)

Exercise 28:

Create a 3x3 list of lists with values ranging from 0 to 8.

nums = list(range(9))
ll_nums = [nums[x:x+3] for x in range(0,9,3)]
print(ll_nums)

Exercise 29:

Calculate the exponential of all elements in a list.

import math
nums = list(range(9))
nums = [math.exp(x) for x in nums]
print(nums)

Exercise 30:

Swap two rows in a 2D list.

import random
matrix = create_n_by_n_list(4)
print(matrix)
matrix[0], matrix[1] = matrix[1], matrix[0]
print(matrix)

Exercise 31:

Create a random 3x3 list of lists and replace all values greater than 0.5 with 1 and all others with 0.

soln

import random
random.seed(3)
print([[1 if random.random() > 0.5 else 0 for _ in range(3)] for _ in range(3)])

output

[[0, 1, 0], [1, 1, 0], [0, 1, 0]]

Exercise 32:

Find the indices of the top N maximum values in a list.

soln

top_n_idx = lambda x,n: list(list(zip(*sorted(enumerate(x), key=lambda x:x[1], reverse=True)))[0][:n:])
print(top_n_idx([1, 2, 6, 4], 3))

output

[2, 3, 1]

Exercise 33:

Calculate the mean of each column in a 2D list.

soln (oops sums over rows!)

mean_cols = lambda l: [sum(l[i]) / len(l) for i in range(len(l))]
n = 5
d2_list = [[random.randint(0,10) for _ in range(n)] for _ in range(n)]
print(mean_cols(d2_list))

soln (over cols)

mean_cols = lambda l: [sum(row[i] for row in l) / len(l) for i in range(len(l))]
n = 5
d2_list = [[random.randint(0,10) for _ in range(n)] for _ in range(n)]
print(mean_cols(d2_list))

Exercise 34:

Normalize the values in each column of a 2D list.

soln

random.seed(4)
mean_cols = lambda l: [
        [l[r][c] / sum(l[i][c] for i in range(len(l[r])))
         for c in range(len(l[r]))]
        for r in range(len(l))
  ]
n = 5
d2_list = [[random.randint(0,10) for _ in range(n)] for _ in range(n)]
print("original matrix:", d2_list)
print(mean_cols(d2_list))

output

original matrix: [[3, 4, 1, 6, 7], [2, 1, 1, 0, 6], [8, 4, 0, 3, 8], [8, 5, 4, 2, 1], [4, 3, 0, 10, 4]]
[[0.12, 0.23529411764705882, 0.16666666666666666, 0.2857142857142857, 0.2692307692307692], [0.08, 0.058823529411764705, 0.16666666666666666, 0.0, 0.23076923076923078], [0.32, 0.23529411764705882, 0.0, 0.14285714285714285, 0.3076923076923077], [0.32, 0.29411764705882354, 0.6666666666666666, 0.09523809523809523, 0.038461538461538464], [0.16, 0.17647058823529413, 0.0, 0.47619047619047616, 0.15384615384615385]]

lessons

  1. you need be careful along the axis which you are computing index calculations on
  2. if you are going to use huge lambda functions, at least indent them and split them across multiple lines.

Exercise 35:

Concatenate two lists.

soln

l1 = list(range(5))
l2 = ['a', 'b', 'string']
l1.extend(l2)
print(l1)

output

[0, 1, 2, 3, 4, 'a', 'b', 'string']

Exercise 36:

Create a 2D list with random values and sort each row.

soln

import random
n = 3
sort_rows = lambda l: [sorted(row) for row in l]
print(sort_rows([[random.randint(0,n) for _ in range(n)] for _ in range(n)]))

output

[[0, 3, 3], [2, 2, 3], [0, 3, 3]]

Exercise 37:

Check if all elements in a list are non-zero.

soln(bad)

my_list = [random.randint(0,n) for _ in range(n)]
check_nonzero = lambda l: True if len(list(filter(lambda x: x == 0, l))) == 0 else False
print(my_list)
print(check_nonzero(my_list))

output

[3, 3, 3]
True
[3, 0, 3]
False

soln(good)

my_list = [random.randint(0,n) for _ in range(n)]
check_nonzero = lambda l: all(l)
print(my_list)
print(check_nonzero(my_list))

output

[0, 3, 2]
False
[3, 3, 3]
True

Exercise 38:

Find the indices of the maximum value in each row of a 2D list.

soln

my_list = [[random.randint(0,n+2) for _ in range(n)] for _ in range(n)]
max_idx_rows_as_list = lambda l: list(map(lambda x: x.index(max(x)), l))
print(my_list)
print(max_idx_rows_as_list(my_list))

output

[[2, 0, 5], [1, 2, 3], [0, 5, 0]]
[2, 2, 1]

Exercise 39:

Create a 2D list and replace all nan values with the mean of the list.

soln

my_list = [[random.randint(0,n+2) for _ in range(n)] for _ in range(n)]
max_idx_rows_as_list = lambda l: list(map(lambda x: x.index(max(x)), l))
print(my_list)
print(max_idx_rows_as_list(my_list))

output

Exercise 40:

Calculate the mean of each row in a 2D list ignoring nan values.

soln

import math
matrix = [[1, float('nan'), 3], [4, 5, float('nan')], [7, 8, 9]]
#row_means = [sum(x for x in row if not math.isnan(x)) / sum(1 for x in row if not math.isnan(x)) for row in matrix]
row_means = list(map(lambda x: sum(i for i in x if not math.isnan(i)) / sum(1 for i in x if not math.isnan(i)) , matrix))
print(row_means)

soln

[2.0, 4.5, 8.0]

lessons

to summon a nan, you may use float('nan'). or you may also use

n1 = float("nan")
n2 = float("Nan")
n3 = float("NaN")
n4 = float("NAN")
print n1, n2, n3, n4
from decimal import *

n1 = Decimal("nan")
n2 = Decimal("Nan")
n3 = Decimal("NaN")
n4 = Decimal("NAN")
print n1, n2, n3, n4
import math

n1 = math.nan
print(n1)
print(math.isnan(n1))
import numpy as np

n1 = np.nan

# Check if a value is NaN
print(np.isnan(n1))

furthermore, to sum across elements in an unknown dimensional array, with each of the entries contributing weights, we can use sum(i for i in x if not math.isnan(i)).

then for when only the existence of the digit matters, you can use sum(1 for i in x if not math.nan(i)) as above.

Exercise 41:

Compute the sum of diagonal elements in a 2D list.

soln

import random
random.seed(3)
n = 10
my_list = [ [random.randint(0,n) for _ in range(n) ] for _ in range(n)]
diag_2d = lambda l: sum(l[i][i] for i in range(n))
print(my_list)
print(diag_2d(my_list))

Exercise 42:

Convert radians to degrees for each element in a list.

soln

import math
convert_list = [1, 2, 0.5, 0.25]
rad_2_deg = lambda x: [y*180/math.pi for y in x]
#rad_2_deg = lambda x: list(map(lambda y: y*180/math.pi, x))
print(rad_2_deg(convert_list))

Exercise 43:

Calculate the pairwise Euclidean distance between two lists.

soln

import math
first_list = [1, 2, 0.5, 0.25]
second_list = list(range(4))
pairwise_euc = lambda x, y: [abs(i[0] - i[1]) for i in zip(x,y)]
print(pairwise_euc(first_list, second_list))

Exercise 44:

Create a list and set the values between the 25th and 75th percentile to 0.

soln

def percentile(data, percentile):
  data = sorted(data)
  k = (len(data) - 1) * (percentile / 100)
  return data[int(k)]

lst = [10, 20, 30, 40, 50]
q1 = percentile(lst, 25)
q3 = percentile(lst, 75)
lst = [0 if q1 <= x <= q3 else x for x in lst]
print(lst)

lst = [10, 20, 30, 40, 50]
percentile_25th = sorted(lst)[int(len(lst) * 0.25)] # indexing into the first quarter
percentile_75th = sorted(lst)[int(len(lst) * 0.75)]
lst = [0 if percentile_25th <= x <= percentile_75th else x for x in lst]
print(lst)

Exercise 45:

Calculate the element-wise square of the difference between two lists.

soln

import math
first_list = [1, 2, 0.5, 0.25]
second_list = list(range(4))
pairwise_squared = lambda x, y: [(i[0] - i[1])**2 for i in zip(x,y)]
print(pairwise_euc(first_list, second_list))

Exercise 46:

Replace all even numbers in a list with the next odd number.

soln

my_list = list(range(10))
replace_evens = lambda l: list(map(lambda y: y+1 if y%2==0 else y, l))
print(replace_evens(my_list))

Exercise 47:

Create a 2D list and normalize each column by its range.

soln (worst code I’ve ever written 🤠

random.seed(4)
twod_list = [list(random.randint(0,10) for _ in range(10)) for _ in range(4)]
get_range_rows = lambda l: sorted(new_list,reverse=True)[0] - sorted(new_list)[0]
normalise_2d_rows = lambda l: [ [l[row_idx][col_idx]/get_range_rows(row) for col_idx in range(len(row))] for row_idx, row in enumerate(l) ]
get_range_cols = lambda matrix: (num_rows := len(matrix),
                                   num_cols := len(matrix[0]),
                                   [max(row[col_idx] for row in matrix) - min(row[col_idx] for row in matrix) for col_idx in range(num_cols)])[-1]
normalise_2d_cols = lambda l: [ [(l[row_idx][col_idx]-min(row[col_idx] for row in l))/(get_range_cols(l))[col_idx] for col_idx in range(len(row))] for row_idx, row in enumerate(l) ]

print(twod_list)
print(get_range_cols(twod_list))
#print(sorted(twod_list,reverse=True))
#print(normalise_2d_rows(twod_list))
print(normalise_2d_cols(twod_list))

soln (official)

import random
matrix = [[random.random() for _ in range(3)] for _ in range(3)]
min_col = [min(row[i] for row in matrix) for i in range(3)]
max_col = [max(row[i] for row in matrix) for i in range(3)]
normalized_matrix = [[(row[i] - min_col[i]) / (max_col[i] - min_col[i]) for i in range(3)] for row in matrix]
print(normalized_matrix)

Exercise 48:

Compute the cumulative sum of elements along a given axis in a 2D list.

soln

cum_sum = lambda l, axis: [ [sum(l[row_idx][:col_idx+1]) for col_idx in range(len(row)) ] for row_idx, row in enumerate(l) ]
print(twod_list)
print(cum_sum(twod_list, 0))
cum_sum_lambda = lambda l, axis: (
  [
        [sum(col[0:row_idx+1]) for row_idx in range(len(col))]
        for col in zip(*l)
  ] if axis == 0 else [
        [sum(row[0:col_idx+1]) for col_idx in range(len(row))]
        for row in l
  ]
)
print(cum_sum_lambda(twod_list, 0))
print(cum_sum_lambda(twod_list, 1))

Exercise 49:

Check if any element in a list is non-zero.

soln

non_zero = lambda l: any(l)
print(non_zero(twod_list[0]))

Exercise 50:

Create a 2D list with random integers and replace all values greater than a certain threshold with that threshold.

soln

threshold_replace = lambda l, t: [ [ t if l[row_idx][col_idx] > t else l[row_idx][col_idx] for col_idx in range(len(row)) ] for row_idx, row in enumerate(l) ]
print(threshold_replace(twod_list, 5))

Exercise 51:

Find the median of a list of numbers.

soln

import random
random.seed()
list_nums = [random.randint(0,5) for _ in range(5)]
median = lambda l: l[len(l) / 2 if len(l) % 2 == 0 else len(l)//2 ]
print(list_nums)
print(median(list_nums))

Exercise 52:

Convert a list of numbers to a list of their logarithms.

soln

import math
log_list = lambda l: [math.log(x) for x in l]
print(log_list(list_nums))

Exercise 53:

Find the mode of a list of numbers.

soln

disclaimer: this implementation does not deal with multiple most often occurring values

list_nums = [random.randint(0,5) for _ in range(5)]
def mode(l):
  uniques = set(l)
  mo = (0,) # most often
  for x in uniques:
    y = l.count(x)
    if y > mo[0]:
        mo = (y, x)
  return mo[1]
print(list_nums)
print(mode(list_nums))

Exercise 54:

Flatten a list of lists.

soln

nested_list = [[ [ random.randint(0,4) for _ in range(4) ] for _ in range(3) ] for _ in range(2) ]
twod_nested_list = [ [ random.randint(0,4) for _ in range(4) ] for _ in range(3) ]
print(nested_list)
unwrap_2d = lambda l: [x for rows in l for x in rows]
print(unwrap_2d(twod_nested_list))
print(nested_list)
unwrap_3d = lambda l: [x for matrices in l for rows in matrices for x in rows]
print(unwrap_3d(nested_list))

Exercise 55:

Transpose a 2D list.

soln

print(twod_nested_list)
transpose = lambda l: [[ l[j][i] for j in range(len(l)) ] for i in range(len(l[0]))]
print(transpose(twod_nested_list))

Exercise 56:

Remove duplicates from a list while preserving order.

soln

lst = [5,3,2,3,4,5,5,1,2,1,1]
seen = set()
print(set(lst)) # note that this orders things, that's all.
unique_lst = [x for x in lst if not (x in seen or seen.add(x))] # i'm not grasping the seen.add(x) part.
print(unique_lst)

Exercise 57:

Find the intersection of two lists.

soln

lst1 = [5,2,5,3,1,2]
lst2 = [1,3,9,5,2]
print(set(lst1).intersection(lst2))
# turns out there's another way:
print(set(lst1) & set(lst2))

Exercise 58:

Merge two dictionaries.

soln

dic1 = {'a': 1, 'c': 6}
dic2 = {'d': 6, 'r': 2, 'l': 3}
print(dic1 | dic2)
# furthermore, there is
print({**dic1, **dic2})

Exercise 59:

Sort a list of dictionaries by a key.

soln

print(sorted(dic2.items(), key=lambda x:x[0])) # can sort on values with x[1]

this is actually not what the question asked for. they asked for sorting on a specific key from a list of dicts.

lst = [{'name' : 'Alice', 'age': 10}, {'name':'Bob','age':15}, {'name':'Charlie','age':20}]
print(sorted(lst, key=lambda x:x['age']))

Exercise 60:

Filter a dictionary based on its values.

soln

d = {'a': 1, 'b':2, 'c':3}
filtered_dict = {k:v for k,v in d.items() if v > 1}
print(filtered_dict)

Exercise 61:

Create a dictionary from two lists.

soln

keys = ['a','b','c','d']
values = [1,2,3,4]
joined_dict = dict(zip(keys,values))
print(joined_dict)

Exercise 62:

Find the maximum value in a dictionary.

soln

print(max(joined_dict))
print(max(joined_dict.items()))
print(max(joined_dict.values()))

Exercise 63:

Invert a dictionary (swap keys and values).

soln

new_dict = {v:k for k,v in joined_dict.items()}
print(new_dict)

Exercise 64:

Create a dictionary with a default value.

soln

keys = ['x', 'y', 'z']
v = 5
mydict = {k:v for k in keys}
print(mydict)

Exercise 65:

Convert a dictionary to a list of tuples.

soln

ts = [item for item in mydict.items()]
# the above is probably a little slower than:
ts_fast = list(mydict.items()) # note that [] is different here than to list.
print(ts_fast)

list comparison aside

# [] is different to list(). [] is a literal, whereas list() is a constructor
# [] is bytecode, list() requires a function call
import timeit
print(timeit.timeit("[]", number=10**6)) # faster
print(timeit.timeit("list()", number=10**6)) # slower
# list() is more versatile and can convert iterables into lists
# [] can only define new lists.

Exercise 66:

Find the length of the longest string in a list.

soln

strings = ["my", "cartridge", "got", "hitroadige", "by", "a", "truck"]
print(max(strings)) # alphabetised
print(max(strings, key=lambda x: len(x)))

Exercise 67:

Reverse the words in a sentence.

soln

s = "oh my god, I might fail this course"
list_of_words = s.split()
print(' '.join(list_of_words[::-1]))

Exercise 68:

Check if a string is a palindrome.

soln

palindrome_checker = lambda s: True if s==s[::-1] else False
print(palindrome_checker("lick"))
print(palindrome_checker("kayak"))

Exercise 69:

Remove punctuation from a string.

soln

import string
remove_punc = lambda s: s.translate(str.maketrans('','',string.punctuation))
print(remove_punc("remove, punc? punk!"))

Exercise 70:

Count the occurrences of each character in a string.

soln

print(s)
count_chars = lambda s: {char: s.count(char) for char in set(s)}
print(sorted(list(count_chars(s).items()), key=lambda x:x[1]))

Exercise 71:

Find the longest common prefix among a list of strings.

soln

lstrings = ["hello", "world", "worldly", "hells"]

def longest_prefix(lstr):
      if not lstr:
          return ""
      shortest_str = min(lstr, key=len)
      longest_common_prefix = ""
      for i in range(len(shortest_str)):
          current_char = shortest_str[i]
          if all(x[i] == current_char for x in lstr):
              longest_common_prefix += current_char
          else:
              break
      return longest_common_prefix

print(longest_prefix(["flower","flow","flight"]))

Exercise 72:

Convert a string to a list of characters.

soln

stringcheese = "stringcheese"
listcheese = [stringcheese[i] for i in range(len(stringcheese))]
print(listcheese)
# this could be done more easily with:
print(list(stringcheese)) # recall that list takes an iterable object

Exercise 73:

Generate a list of random integers.

soln


import random
rand_list = [random.randint(0,5) for _ in range(5)]
print(rand_list)

Exercise 74:

Shuffle a list.

soln

print(random.shuffle(rand_list)) # returns none
print(rand_list)

Exercise 75:

Generate a random password of a given length.

soln

#cheating with this one to see what the sols want:
import string
import random
length = 8
password = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(length))
print(password)

Exercise 76:

Calculate the factorial of a number.

soln

def factorial(n):
  if n < 0:
    return -1
  if n == 0:
    return 1
  return n*factorial(n-1)

print(factorial(-1))
print(factorial(10))

Exercise 77:

Calculate the Fibonacci sequence up to a given number of terms.

soln


def fibonacci(n):
     if n == 0:
         return 0
     if n == 1:
         return 1
     return fibonacci(n-1) + fibonacci(n-2)
for i in range(10):
     print(fibonacci(i))

Exercise 78:

Check if a number is prime.

soln

def is_prime(n):
     if n <= 1:
          return False
     for i in range(2, n):
         if n % i == 0:
             return False
     return True

for i in range(1,20):
    print(i, "prime" if is_prime(i) else "not")

Exercise 79:

Find the greatest common divisor (GCD) of two numbers.

soln


def gcd(a, b):
    limit = max(a,b)
    highest = 1
    for i in range(1,limit+1):
        if a%i==0 and b%i==0:
            highest=i

    return highest

print(gcd(8,6))

Exercise 80:

Find the least common multiple (LCM) of two numbers.

soln

""" returns the highest number that is divisible by both a and b """
def lcm(a, b):
    i = 1
    while True:
        if i%a==0 and i%b==0:
            return i
        else:
            i += 1

print(lcm(8,6))

Exercise 81:

Sort a list of tuples by the second element.

soln

lt = [('a',2),('c',3),('b',1)]
sorted(lt,key=lambda x:x[1])

Exercise 82:

Find the second largest number in a list.

soln

second_largest = [5,1,2,1,3,4,7]
sorted(second_largest)[-2]

Exercise 83:

Check if a list is a palindrome.

soln

p = ['k', 'a', 'y', 'a', 'k']
n = ['n', 'o', 't']
def list_palindrome(l):
    for i in range(len(l)//2):
        if l[i] != l[-1-i]:
            return False
    return True

list_palindrome(n)

Exercise 84:

Find the sum of the digits of a number.

soln

num = 804
def sum_digits(n):
    digits = len(str(n))
    sum = 0
    for i in range(digits):
        sum += int(str(n)[i])
    return sum

sum_digits(num)

Exercise 85:

Find the product of the digits of a number.

soln

def prod_digits(n):
    digits = len(str(n))
    prod = 1
    for i in range(digits):
        prod *= int(str(n)[i])
    return prod

prod_digits(43)

Exercise 86:

Check if a string is a valid number.

soln

def check_str_is_num(s):
  return s.replace('.', '', 1).isdigit()
check_str_is_num("6s")
check_str_is_num("s")
check_str_is_num("7")
check_str_is_num("4.0")

Exercise 87:

Find the length of the longest word in a sentence.

soln

import string
sentence = "here are some words in a sentence"
def len_longest_word(s):
    words = s.split()
    return len(max(words, key=len))
    #return ' '.join(["word", "maybe", "cat"])
len_longest_word(sentence)

Exercise 88:

Convert a list of tuples to a dictionary.

soln

print(lt)
print(dict(lt))

Exercise 89:

Filter a list of dictionaries based on a key value.

soln

lst = [{'name': 'Vivek', 'age': 25}, {'name': 'Esther', 'age': 22}, {'name': ' Neassa', 'age': 28}]
filtered_lst = [x for x in lst if x['age'] > 23]
print(filtered_lst)

Exercise 90:

Sort a list of tuples by multiple keys.

soln

one thing to understand is that tuples can be n-dimensional: (a,b,c,d,...,n)!

list_of_t = [(1,2,3,4),(1,2,3),(4,2,1),(1,2,3)]
print(sorted(list_of_t,key=lambda x: (x[1],x[2])))

note also that you can get an IndexError if the lambda func within sorted is accessing outofbounds incdices.

[(4, 2, 1), (1, 2, 3, 4), (1, 2, 3), (1, 2, 3)]

Exercise 91:

Merge two lists into a dictionary, using one as keys and the other as values.

soln

keys = ['jonah','sarah','cupcake']
values = [14,21,33]
merge_lists_dict = lambda k,v: dict(zip(k,v))
print(merge_lists_dict(keys,values))

Exercise 92:

Create a dictionary with keys as numbers and values as their squares.

soln

nums = range(6)
dict_square = dict(zip(nums, [x**2 for x in nums]))
print(dict_square)

Exercise 93:

Check if two strings are anagrams.

soln

I may have glimpsed at the solution, it’s quite clean

str1, str2 = "listen", "silent"
str3, str4 = "mold", "wolf"
check_anagram = lambda s1,s2: True if sorted(s1)==sorted(s2) else False
print(check_anagram(str1,str2))
print(check_anagram(str3,str4))

Exercise 94:

Count the number of vowels in a string.

soln

vowel_counter= lambda s: sum(1 for c in s.lower() if c in "aeiou")
print(vowel_counter("hello world's people"))

Exercise 95:

Check if a string contains only digits.

soln

str_is_dig = lambda s:True if sum(1 for c in s if c.isdigit()) == len(s) else False
print(str_is_dig("123"))
print(str_is_dig("12a"))
# as it turns out, you don't even need the for loop:
print("123456".isdigit())
print("1a23".isdigit())

Exercise 96:

Find the first non-repeated character in a string.

soln

this one is pretty interesting. I’ve never used the next iterator:

ultimate = "frisbee"
non_repeated_char = lambda s: [char for char in s if s.count(char) == 1][0] # you could also use next!
print(non_repeated_char(ultimate))
print(non_repeated_char(ultimate))

Exercise 97:

Reverse each word in a sentence.

soln

s = "oh my god, I will not fail any course"
s_as_l = s.split()
print(' '.join(word[::-1] for word in s_as_l))

Exercise 98:

Generate a list of Fibonacci numbers up to a given number.

soln

def fibonacci(n):
     if n == 0:
         return 0
     if n == 1:
         return 1
     return fibonacci(n-1) + fibonacci(n-2)

def fibo_until(x):
    n=0
    y=[fibonacci(n)]
    while x >= y[n]:
        fib = fibonacci(n)
        if fib > x:
             break
        n+=1
        y.append(fib)
    return y

print(fibo_until(55))

Exercise 99:

Remove all whitespaces from a string.

soln

tring = "here are some words and a \n"
print(tring.strip()) # won't replace all whitespace, only trailing and leading.
print(tring.replace(" ", ""))

Exercise 100:

Replace all occurrences of a substring in a string.

soln

mainstr = "my mother is a grand wolf"
print(mainstr.replace("wolf", "bob"))

instructGPT appendix

def binomial_coefficient(n, r):
  C = [0 for i in range(r+1)]
  C[0]=1
  for i in range(1,n+1):
    j = min(i,r)
    while j > 0:
      C[j] += C[j-1]
      j -= 1
    print(C)
  return C[r]

binomial_coefficient(4,4)