avatar
Siz Long

My name is Siz. I am a computer science graduate student specializing in backend development with Golang and Python, seeking opportunities in innovative tech projects. My personal website is me.longsizhuo.com .Connect with me on LinkedIn: https://www.linkedin.com/in/longsizhuo/.

  • Resume
  • Archives
  • Categories
  • Photos
  • Music



{{ date }}

{{ time }}

avatar
Siz Long

My name is Siz. I am a computer science graduate student specializing in backend development with Golang and Python, seeking opportunities in innovative tech projects. My personal website is me.longsizhuo.com .Connect with me on LinkedIn: https://www.linkedin.com/in/longsizhuo/.

  • 主页
  • Resume
  • Archives
  • Categories
  • Photos
  • Music

9021_TUT_3_25T1

  2025-03-07        
字数统计: 2.2k字   |   阅读时长: 13min

Exercise 1

Problem Description:

You are given two integers, m and n, where:

  • m represents the number of repeated units (patterns).
  • n represents the number of elements (underscores) within each unit.

The goal is to generate a string where:

  • Each unit contains n underscores (_), separated by |.
  • These units are then concatenated together, separated by *.

My Solution:

1
2
3
4
5
def generate_struct(n):
return '|'.join(n * ['_'])

def f1(m, n):
return ' * '.join(m * [generate_struct(n)])

My Thought Process:

I think of each unit as a separate structure. So, I decompose the problem by breaking down the smallest unit, which is the structure made of underscores joined by |.
After constructing each unit, I use join() to combine them together using *.

Helper Function generate_struct(n):

This function generates the basic structure.
It creates a list of underscores (_) of length n and joins them with |.
Example: If n = 2, the result will be “_|_“.

Standard Solution:

1
2
def f1(m, n):
return ' * '.join('|'.join('_' for _ in range(n)) for _ in range(m))

Concise Expression:

The inner join creates a string of n underscores joined by | using a generator expression ('_' for _ in range(n)).
The outer join repeats this process m times and concatenates the units using *.

In summary, my solution focuses on modularity by breaking down the problem into smaller parts (like creating a structural unit), whereas the standard solution compresses everything into one line using list comprehensions.

Exercise 2

Problem Description:

The goal is to generate a pattern based on the digits of a given number n. Specifically:

If a digit is odd, it should be represented by a black square (⬛).
If a digit is even, it should be represented by a white square (⬜).
The program takes a number n as input and prints a string of squares corresponding to the digits of n.

My Solution:

1
2
3
4
5
6
7
8
def f2(n):
ans = ''
for i in str(n):
if int(i) % 2 == 0:
ans += '⬜'
else:
ans += '⬛'
print(ans)

My Thought Process:

  1. Loop through each digit:
    Convert the number n to a string to iterate over each digit individually.

  2. Check if the digit is even or odd:
    Convert each digit back to an integer and use the modulus operator (% 2) to check if the digit is even or odd.

  3. Append the corresponding square:

    • If the digit is even, append a white square (⬜) to the result string.
    • If the digit is odd, append a black square (⬛).
  4. Print the final string:
    After processing all the digits, print the final string containing black and white squares.

Standard Solution:

1
2
def f2(n):
print(''.join({0: '\u2b1c', 1: '\u2b1b'}[int(d) % 2] for d in str(n)))

Dr.Martin’s solution is:

  1. More compact and Pythonic.
  2. Uses a dictionary and list comprehension for brevity and efficiency.
  3. The Unicode characters for the squares are referenced directly using their escape sequences (\u2b1c for white, \u2b1b for black).

Exercise 3

Problem Description:

In this task, the number n is treated as a number expressed in different bases (ranging from 2 to 10), and we aim to convert it into its corresponding base 10 value for each of these bases, where the conversion is valid.

For n = 2143:

  • 2143 in base 5 is equivalent to 298 in base 10.
  • 2143 in base 6 is equivalent to 495 in base 10.
  • And so on.

The goal is to iterate over different base systems from 2 to 10, treat the input number n as if it is expressed in each base, and then convert it to base 10.

My Solution:

1
2
3
4
5
6
7
8
def f3(n: int):
for i in range(2, 11):
try:
# Treat n as a number in base i and convert it to base 10
value = int(str(n), i)
print(f'{n} is {value} in base {i}')
except ValueError:
pass

My Thought Process:

  1. Iterating over Bases (2 to 10):

    • We loop through the base values i ranging from 2 to 10.
  2. Conversion Using int():

    • For each base i, we treat the number n as a number in that base. To do this, we first convert n to a string (str(n)) and then use int() to interpret it as a base i number.
    • If the digits of n are valid for base i, this conversion succeeds, and the result is the base 10 equivalent of n.
    • If the digits of n are not valid for base i (for example, if base 2 is used and n contains digits greater than 1), a ValueError is raised, and we skip the invalid base.
  3. Handling Errors with try-except:

    • The try-except block ensures that invalid bases are skipped, allowing us to handle cases where the digits in n are not valid for a particular base.

Standard Solution:

1
2
3
4
5
def f3(n):
n_as_string = str(n)
min_base = max(2, max({int(d) for d in n_as_string}) + 1)
for b in range(min_base, 11):
print(f'{n} is {int(n_as_string, b)} in base {b}')

It skips the bases where the digits in n are not valid, and it uses a set comprehension to extract the unique digits from n_as_string. The maximum digit is then used to determine the minimum base to start iterating from.

Exercise 4

Problem Description:

The task is to create a function f4(n, base) that returns a dictionary D, where:

Keys are integers from 0 to n.
Values are tuples that represent the base base representation of each key, converted from base 10.

My Solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def convert_to_base(n, base):
if n == 0:
return '0'
digits = []
while n:
digits.append(str(n % base))
n //= base
return ''.join(digits[::-1])

def f4(n: int, base: int):
D = {}
for i in range(0, n + 1):
D[i] = tuple(map(int, convert_to_base(i, base)))
return D

My Thought Process:

  1. Helper Function convert_to_base(n, base):

    • This function converts a number n from base 10 to the specified base.
    • We use a while loop to repeatedly take the modulus (n % base) and append the remainder to the list digits.
    • We then divide n by base (n //= base) to reduce it for the next iteration.
    • After collecting all digits, we reverse the list and return it as a string.
  2. Main Function f4(n, base):
    We initialize an empty dictionary D.
    For each number i from 0 to n, we convert i to the given base using convert_to_base().
    The converted base digits are then mapped to integers and stored in a tuple as the value for each key i in the dictionary.

Explanation of Why map() is not Pythonic:

In the function f4, the use of map(int, convert_to_base(i, base)) applies the int function
to each element of the result from convert_to_base, effectively converting each character to an integer.

However, it’s worth noting that the map() function, which originates from functional programming,
has largely been superseded by more Pythonic constructs such as list comprehensions.

These comprehensions are generally considered superior for several reasons:

  • They are more elegant and concise.
  • They tend to be shorter in terms of syntax, making the code easier to read.
  • They are easier to understand for most people, especially those who are more familiar with Python’s
    standard syntax rather than functional programming constructs.
  • In many cases, they are also more efficient in terms of performance.

For example, instead of using map(int, ...), the same functionality could be achieved with a
list comprehension, like so:

D[i] = tuple([int(digit) for digit in convert_to_base(i, base)])

This list comprehension achieves the same result but follows a more modern Pythonic style.

Standard Solution:

1
2
3
4
5
6
7
8
9
10
def f4(n, base):
D = {0: (0,)}
for m in range(1, n + 1):
digits = []
p = m
while p:
digits.append(p % base)
p //= base
D[m] = tuple(reversed(digits))
return D

Both solutions are valid and achieve the same result. My approach uses a helper function for base conversion, which adds modularity,
whereas the standard solution is more concise and directly integrates the conversion logic into the main function.

Exercise 5

At the first, try to run this:

1
print(0.1 + 0.2)

What happened? The result is not 0.3, but 0.30000000000000004. Why?

Problem Description:

The approach we are using in this exercise is designed to expose the limitations of floating-point arithmetic in computers. Let’s break down why this approach leads to precision inaccuracies and why other methods might not reveal these issues as clearly.

This problem can seem complex, and it’s designed to highlight the subtleties of floating-point arithmetic. Let’s walk through the logic using the test cases to figure out what the function does.

Key Concepts:

  • Floating-point numbers: Computers store floating-point numbers using a binary format, which often introduces precision errors.
  • Precision: We’re working with two types of precision in this function—simple precision (same as the length of the fractional part) and double precision (twice that length).

Solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def f5(integral_part, fractional_part):
# Calculate the number of digits in the fractional part
precision = len(str(fractional_part))

# Concatenate the integral and fractional parts as strings, then convert to a float
a_float = float(str(integral_part) + '.' + str(fractional_part))

# Format the float with precision equal to the number of digits in the fractional part (simple precision)
simple_precision = f'{a_float:.{precision}f}'

# Append a number of zeros equal to the fractional part length to the simple precision value (extended precision)
extended_simple_precision = simple_precision + '0' * precision

# Format the float with precision equal to twice the number of fractional digits (double precision)
double_precision = f'{a_float:.{precision * 2}f}'

# Print the first part of the output
print('With', precision * 2, 'digits after the decimal point, ', end='')

# Compare if extended precision and double precision values are the same
if extended_simple_precision == double_precision:
# If they are the same, it means the float is precise and has trailing zeros
print(simple_precision, 'prints out with', precision, 'trailing',
precision == 1 and 'zero,' or 'zeroes,', 'namely, as',
extended_simple_precision
)
else:
# If not, there is a precision error, and no trailing zeros
print(simple_precision, 'prints out as', double_precision)

Our function attempts to check and display this floating point error with simple precision (simple_precision) and double precision (double_precision). The error becomes more obvious when we represent floating point numbers with higher precision (double the number of decimal places). So in this way, we show that floating point numbers are not always actually stored as we expect them to be with more precise representation.

Exercise 6

Problem Description:

In this task, we are given:

  • A list L, which contains multiple sub-lists of integers, and all sub-lists have the same length n.
  • A list fields, which is a permutation of {1, ..., n}.

We are required to sort the list L by using a multi-key sorting mechanism, where:

  • First, the elements in L are sorted based on the position given by the first element of fields.
  • If two sub-lists are equal based on the first field, we move to the second field, and so on.
  • Finally, if required, the sorting proceeds up to the last field in fields.

Example of Fields Explanation:

If fields = [2, 1], it means:

  1. First, sort based on the second element of each sublist.
  2. If there are ties (same values in the second position), sort based on the first element.

My Solution:

1
2
def f6(L, fields):
return sorted(L, key=lambda x: [x[i-1] for i in fields])
  1. Sorting with sorted():
    The sorted() function is used to sort the list L.
    The key parameter defines how the sorting will be performed.

  2. Lambda Function:
    The lambda function defines how the sublists will be sorted. It generates a list of values for each sublist based on the positions specified in fields.
    For example, if fields = [2, 1], the lambda function will extract the second and first elements from each sublist in that order, and sorting will be done based on this new list.

  3. Key Structure:
    The key is a list of elements from each sublist, indexed by the positions specified in fields. We use x[i - 1] because fields is 1-based, and list indexing in Python is 0-based.

  4. What is Lambda Function?

For example:

We have:

1
f = lambda x: x * x

This is equivalent to:

1
2
def f(x):
return x * x

And lambda function in a sorted function is used to define a custom sorting key.

1
2
3
4
5
L = [(1,2), (3,1), (5,0)]

SortedL = sorted(L, key=lambda x: x[1])

print(SortedL)

The result is: [(5, 0), (3, 1), (1, 2)], it sorts the list based on the second element of each tuple.

Standard Solution:

1
2
def f6(L, fields):
return sorted(L, key=lambda x: tuple(x[i - 1] for i in fields))

Why Use a Tuple?:

  • Tuples are often preferred for multi-key sorting because they are immutable, and Python’s built-in sorting functions can efficiently compare tuples.
  • Each sublist is transformed into a tuple of its elements based on the order defined by fields. The sorted() function then uses these tuples to sort the list.
  • 9021
  • lab

扫一扫,分享到微信

微信分享二维码
9021_TUT_1_25T1
9021_TUT_7
目录
  1. 1. Exercise 1
    1. 1.0.1. Problem Description:
    2. 1.0.2. My Solution:
      1. 1.0.2.1. My Thought Process:
      2. 1.0.2.2. Helper Function generate_struct(n):
    3. 1.0.3. Standard Solution:
    4. 1.0.4. Concise Expression:
  • 2. Exercise 2
    1. 2.0.1. Problem Description:
    2. 2.0.2. My Solution:
      1. 2.0.2.1. My Thought Process:
    3. 2.0.3. Standard Solution:
  • 3. Exercise 3
    1. 3.0.1. Problem Description:
    2. 3.0.2. My Solution:
      1. 3.0.2.1. My Thought Process:
    3. 3.0.3. Standard Solution:
  • 4. Exercise 4
    1. 4.0.1. Problem Description:
    2. 4.0.2. My Solution:
      1. 4.0.2.1. My Thought Process:
    3. 4.0.3. Explanation of Why map() is not Pythonic:
    4. 4.0.4. Standard Solution:
  • 5. Exercise 5
    1. 5.0.1. Problem Description:
    2. 5.0.2. Key Concepts:
    3. 5.0.3. Solution:
  • 6. Exercise 6
    1. 6.0.1. Problem Description:
    2. 6.0.2. Example of Fields Explanation:
    3. 6.0.3. My Solution:
    4. 6.0.4. Standard Solution:

  • 150 篇 | 131.7k
    次 | 人
    这里自动载入天数这里自动载入时分秒
    2022-2025 loong loong | 新南威尔士龙龙号