Hướng dẫn python problem solving website - trang web giải quyết vấn đề python

Bạn có phải là một nhà phát triển Python cải thiện các kỹ năng của bạn trước một cuộc phỏng vấn? Nếu vậy, thì hướng dẫn này sẽ mở ra cho bạn một loạt các vấn đề thực hành Python nhằm mô phỏng các kịch bản kiểm tra mã hóa thông thường. Sau khi bạn phát triển các giải pháp của riêng mình, bạn sẽ đi qua câu trả lời của nhóm Python thực sự để bạn có thể tối ưu hóa mã của mình, gây ấn tượng với người phỏng vấn và tìm được công việc mơ ước của bạn!Python practice problems meant to simulate common coding test scenarios. After you develop your own solutions, you’ll walk through the Real Python team’s answers so you can optimize your code, impress your interviewer, and land your dream job!

Nội phân chính

  • Bài tập thực hành Python 1: Tổng của một loạt các số nguyên
  • Mô tả vấn đề
  • Giải pháp vấn đề
  • Bài tập thực hành Python Bài 2: Caesar Mật mã
  • Mô tả vấn đề
  • Giải pháp vấn đề
  • Bài tập thực hành Python Bài 2: Caesar Mật mã
  • Mô tả vấn đề
  • Giải pháp vấn đề
  • Bài tập thực hành Python Bài 2: Caesar Mật mã
  • Mô tả vấn đề
  • Giải pháp vấn đề
  • Bài tập thực hành Python Bài 2: Caesar Mật mã
  • Mô tả vấn đề
  • Giải pháp vấn đề

Bài tập thực hành Python Bài 2: Caesar Mật mã

  • Bài tập thực hành Python 3: Caesar Mật mã Redux for interview-style problems
  • Bài tập thực hành Python 4: trình phân tích cú pháp đăng nhập during the interview
  • Bài tập thực hành Python 5: Giải quyết Sudokufrequently overlooked details
  • Trong hướng dẫn này, bạn sẽ học cách:design decisions and trade-offs

Viết mã cho các vấn đề về kiểu phỏng vấn

Thảo luận về các giải pháp của bạn trong cuộc phỏng vấn

Bài tập thực hành Python 1: Tổng của một loạt các số nguyên

Làm việc thông qua các chi tiết thường xuyên bị bỏ qua

Nói về các quyết định thiết kế và đánh đổi

Mô tả vấn đề

Giải pháp vấn đề

Bài tập thực hành Python Bài 2: Caesar Mật mã [

# integersums.py
def add_it_up[n]:
    try:
        result = sum[range[n + 1]]
    except TypeError:
        result = 0
    return result
0]

Bài tập thực hành Python 3: Caesar Mật mã Redux

Bài tập thực hành Python 4: trình phân tích cú pháp đăng nhập

Bài tập thực hành Python 5: Giải quyết Sudoku

Giải pháp vấn đề

Bài tập thực hành Python Bài 2: Caesar Mật mã

Bài tập thực hành Python 3: Caesar Mật mã Redux

Bài tập thực hành Python 4: trình phân tích cú pháp đăng nhập

# integersums.py
def first[n]:
    num = 1
    sum = 0
    while num >> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'
1 từ lớp
>>> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'
2 trong thư viện tiêu chuẩn. Nếu bạn vật lộn với vấn đề này, thì bạn có thể muốn tạm dừng một chút và xem xét làm thế nào bạn có thể sử dụng
>>> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'
1 trong giải pháp của mình.

Được rồi, bây giờ bạn đã sẵn sàng, hãy để Lôi nhìn vào giải pháp này:

 1# caesar.py
 2import string
 3
 4def caesar[plain_text, shift_num=1]:
 5    letters = string.ascii_lowercase
 6    mask = letters[shift_num:] + letters[:shift_num]
 7    trantab = str.maketrans[letters, mask]
 8    return plain_text.translate[trantab]

Bạn có thể thấy rằng chức năng sử dụng ba điều từ mô -đun

>>> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'
4:

  1. >>> import string
    >>> x = string.ascii_lowercase
    >>> x
    'abcdefghijklmnopqrstuvwxyz'
    >>> x[3:]
    'defghijklmnopqrstuvwxyz'
    >>> x[:3]
    'abc'
    
    5
  2. >>> import string
    >>> x = string.ascii_lowercase
    >>> x
    'abcdefghijklmnopqrstuvwxyz'
    >>> x[3:]
    'defghijklmnopqrstuvwxyz'
    >>> x[:3]
    'abc'
    
    6
  3. >>> import string
    >>> x = string.ascii_lowercase
    >>> x
    'abcdefghijklmnopqrstuvwxyz'
    >>> x[3:]
    'defghijklmnopqrstuvwxyz'
    >>> x[:3]
    'abc'
    
    1

Trong hai dòng đầu tiên, bạn tạo một biến với tất cả các chữ cái chữ thường của bảng chữ cái [chỉ ASCII cho chương trình này] và sau đó tạo một

>>> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'
8, cùng một tập hợp các chữ cái, chỉ thay đổi. Cú pháp cắt không phải lúc nào cũng rõ ràng, vì vậy, hãy để Lôi đi qua nó với một ví dụ trong thế giới thực:

>>>

>>> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'

Bạn có thể thấy rằng

>>> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'
9 là tất cả các chữ cái sau chữ cái thứ ba,
 1# caesar.py
 2import string
 3
 4def shift_n[letter, amount]:
 5    if letter not in string.ascii_lowercase:
 6        return letter
 7    new_letter = ord[letter] + amount
 8    while new_letter > ord["z"]:
 9        new_letter -= 26
10    while new_letter  ord["z"]:
 9        new_letter -= 26
10    while new_letter  ord["z"]:
 9        new_letter -= 26
10    while new_letter  ord["z"]:
 9        new_letter -= 26
10    while new_letter >> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'
8 của các chữ cái bạn muốn ánh xạ, bạn sẽ gọi
>>> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'
6 để tạo bảng dịch.

Tiếp theo, bạn chuyển bảng dịch sang phương thức chuỗi

>>> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'
1. Nó ánh xạ tất cả các ký tự trong
 1# caesar.py
 2import string
 3
 4def shift_n[letter, amount]:
 5    if letter not in string.ascii_lowercase:
 6        return letter
 7    new_letter = ord[letter] + amount
 8    while new_letter > ord["z"]:
 9        new_letter -= 26
10    while new_letter >> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'
8 và để lại tất cả các ký tự khác một mình.

Câu hỏi này là một bài tập trong việc biết và sử dụng thư viện tiêu chuẩn. Bạn có thể được hỏi một câu hỏi như thế này tại một số điểm trong một cuộc phỏng vấn. Nếu điều đó xảy ra với bạn, thì thật tốt khi dành thời gian để suy nghĩ về câu trả lời có thể. Nếu bạn có thể nhớ phương pháp, ____________ 51 trong trường hợp này, thì bạn đã đặt tất cả.

Nhưng có một vài kịch bản khác để xem xét:

  1. Bạn hoàn toàn có thể vẽ một khoảng trống. Trong trường hợp này, bạn có thể sẽ giải quyết vấn đề này theo cách bạn giải quyết vấn đề tiếp theo và đó là một câu trả lời chấp nhận được.

  2. Bạn có thể nhớ rằng thư viện tiêu chuẩn có chức năng để làm những gì bạn muốn nhưng không nhớ các chi tiết.

Nếu bạn đang làm công việc bình thường và đánh một trong những tình huống này, thì bạn sẽ chỉ thực hiện một số tìm kiếm và đang trên đường. Nhưng trong một tình huống phỏng vấn, nó sẽ giúp lý do của bạn để nói to vấn đề.

Yêu cầu người phỏng vấn giúp đỡ cụ thể tốt hơn nhiều so với việc bỏ qua nó. Hãy thử một cái gì đó giống như tôi nghĩ rằng có một chức năng ánh xạ một bộ ký tự sang một bộ khác. Bạn có thể giúp tôi nhớ những gì nó gọi là không?

Trong một tình huống phỏng vấn, nó thường tốt hơn để thừa nhận rằng bạn không biết điều gì đó hơn là cố gắng vượt qua.

Bây giờ, bạn đã thấy một giải pháp sử dụng thư viện tiêu chuẩn Python, hãy để lại thử lại vấn đề tương tự, nhưng không có sự giúp đỡ đó!

Bài tập thực hành Python 3: Caesar Mật mã Redux

Đối với vấn đề thực hành thứ ba, bạn sẽ giải quyết một lần nữa Caesar Mật mã, nhưng lần này bạn sẽ làm điều đó mà không cần sử dụng

>>> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'
1.

Mô tả vấn đề

Mô tả về vấn đề này giống như vấn đề trước đó. Trước khi bạn đi sâu vào giải pháp, bạn có thể tự hỏi tại sao bạn lại lặp lại cùng một bài tập, chỉ cần không có sự giúp đỡ của

>>> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'
1.

Đó là một câu hỏi tuyệt vời. Trong cuộc sống bình thường, khi mục tiêu của bạn là có được một chương trình làm việc, có thể duy trì, viết lại các phần của thư viện tiêu chuẩn là một lựa chọn kém. Thư viện tiêu chuẩn Python được đóng gói với các giải pháp hoạt động, được thử nghiệm tốt và nhanh chóng cho các vấn đề lớn và nhỏ. Tận dụng tối đa của nó là một dấu hiệu của một lập trình viên giỏi.

Điều đó nói rằng, đây không phải là một dự án làm việc hoặc một chương trình mà bạn xây dựng để đáp ứng nhu cầu. Đây là một bài tập học tập, và nó là loại câu hỏi có thể được hỏi trong một cuộc phỏng vấn. Mục tiêu cho cả hai là xem làm thế nào bạn có thể giải quyết vấn đề và sự đánh đổi thiết kế thú vị nào bạn thực hiện trong khi thực hiện nó.

Vì vậy, theo tinh thần học tập, hãy để cố gắng giải quyết Mật mã Caesar mà không cần

>>> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'
1.

Giải pháp vấn đề

Đối với vấn đề này, bạn sẽ có hai giải pháp khác nhau để xem xét khi bạn đã sẵn sàng mở rộng phần bên dưới.

Đối với vấn đề này, hai giải pháp khác nhau được cung cấp. Kiểm tra cả hai và xem bạn thích cái nào!

Giải pháp 1

Đối với giải pháp đầu tiên, bạn theo sát mô tả sự cố, thêm một lượng vào mỗi ký tự và lật nó trở lại đầu bảng chữ cái khi nó tiếp tục vượt quá

 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
3:

 1# caesar.py
 2import string
 3
 4def shift_n[letter, amount]:
 5    if letter not in string.ascii_lowercase:
 6        return letter
 7    new_letter = ord[letter] + amount
 8    while new_letter > ord["z"]:
 9        new_letter -= 26
10    while new_letter >> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'
1 trong thực tế Bài toán 2.

Giải pháp 2

Giải pháp thứ hai cho vấn đề này bắt chước hành vi của phương pháp tích hợp Python,

>>> import string
>>> x = string.ascii_lowercase
>>> x
'abcdefghijklmnopqrstuvwxyz'
>>> x[3:]
'defghijklmnopqrstuvwxyz'
>>> x[:3]
'abc'
1. Thay vì chuyển từng chữ cái theo một số tiền nhất định, nó tạo ra một bản đồ dịch và sử dụng nó để mã hóa từng chữ cái:

 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]

Bắt đầu với

 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
4 trên dòng 11, bạn bắt đầu bằng cách khắc phục vấn đề
Jul 11 16:11:51:490 [139681125603136] dut: Device State: ON
1 lớn hơn
Jul 11 16:11:51:490 [139681125603136] dut: Device State: ON
2. Trong giải pháp trước, bạn đã lặp lại nhiều lần cho đến khi kết quả nằm trong phạm vi thích hợp. Tại đây, bạn có một cách tiếp cận trực tiếp và hiệu quả hơn khi sử dụng toán tử mod [
Jul 11 16:11:51:490 [139681125603136] dut: Device State: ON
3].

Toán tử mod tạo ra phần còn lại từ một bộ phận số nguyên. Trong trường hợp này, bạn chia cho

Jul 11 16:11:51:490 [139681125603136] dut: Device State: ON
2, điều đó có nghĩa là kết quả được đảm bảo nằm trong khoảng từ
# integersums.py
def add_it_up[n]:
    try:
        result = sum[range[n + 1]]
    except TypeError:
        result = 0
    return result
6 đến
Jul 11 16:11:51:490 [139681125603136] dut: Device State: ON
6, bao gồm.

Tiếp theo, bạn tạo bảng dịch. Đây là một sự thay đổi từ các giải pháp trước đó và đáng chú ý. Bạn sẽ thấy thêm về điều này vào cuối phần này.

Khi bạn tạo

Jul 11 16:11:51:490 [139681125603136] dut: Device State: ON
7, phần còn lại của
 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
4 giống hệt với giải pháp trước: Danh sách hiểu để mã hóa mỗi chữ cái và
 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
6 để tạo chuỗi.

 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
7 tìm thấy chỉ số của chữ cái đã cho trong bảng chữ cái và sau đó sử dụng nó để lấy một chữ cái từ
Jul 11 16:11:51:490 [139681125603136] dut: Device State: ON
7. Khối
 1# caesar.py
 2import string
 3
 4def caesar[plain_text, shift_num=1]:
 5    letters = string.ascii_lowercase
 6    mask = letters[shift_num:] + letters[:shift_num]
 7    trantab = str.maketrans[letters, mask]
 8    return plain_text.translate[trantab]
5 bắt được những trường hợp mà aren tìm thấy trong danh sách các chữ cái viết thường.

Bây giờ hãy để thảo luận về vấn đề tạo bảng. Đối với ví dụ đồ chơi này, có lẽ nó không quan trọng quá nhiều, nhưng nó minh họa một tình huống xảy ra thường xuyên trong sự phát triển hàng ngày: cân bằng sự rõ ràng của mã chống lại các tắc nghẽn hiệu suất đã biết.

Nếu bạn kiểm tra lại mã, bạn sẽ thấy

Jul 11 16:11:51:490 [139681125603136] dut: Device State: ON
7 chỉ được sử dụng bên trong
 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
7. Điều này chỉ ra rằng, trong những trường hợp bình thường, nó nên được tạo ra và do đó có phạm vi giới hạn của nó,
 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
7:

________số 8

Vấn đề với cách tiếp cận đó là nó dành thời gian tính toán cùng một bảng cho mỗi chữ cái của tin nhắn. Đối với các tin nhắn nhỏ, lần này sẽ không đáng kể, nhưng nó có thể thêm vào cho các tin nhắn lớn hơn.

Một cách khác có thể mà bạn có thể tránh được hình phạt hiệu suất này sẽ là biến

Jul 11 16:11:51:490 [139681125603136] dut: Device State: ON
7 thành một biến toàn cầu. Mặc dù điều này cũng cắt giảm hình phạt xây dựng, nó làm cho phạm vi
Jul 11 16:11:51:490 [139681125603136] dut: Device State: ON
7 thậm chí còn lớn hơn. Điều này không có vẻ tốt hơn so với cách tiếp cận được hiển thị ở trên.

Vào cuối ngày, sự lựa chọn giữa việc tạo

Jul 11 16:11:51:490 [139681125603136] dut: Device State: ON
7 một khi lên phía trước và đưa ra một phạm vi lớn hơn hoặc chỉ tạo nó cho mỗi lá thư là những gì mà một người gọi là quyết định thiết kế. Bạn cần chọn thiết kế dựa trên những gì bạn biết về vấn đề thực tế mà bạn đang cố gắng giải quyết.design decision. You need to choose the design based on what you know about the actual problem you’re trying to solve.

Nếu đây là một dự án nhỏ và bạn biết nó sẽ được sử dụng để mã hóa các tin nhắn lớn, thì việc tạo bảng chỉ một lần có thể là quyết định đúng đắn. Nếu đây chỉ là một phần của một dự án lớn hơn, có nghĩa là khả năng duy trì là chìa khóa, thì có lẽ việc tạo bảng mỗi lần là tùy chọn tốt hơn.

Vì bạn đã xem xét hai giải pháp, nên nó đáng để dành một chút thời gian để thảo luận về sự tương đồng và khác biệt của họ.

So sánh giải pháp

Bạn đã thấy hai giải pháp trong phần này của Mật mã Caesar và chúng khá giống nhau theo nhiều cách. Họ nói về cùng một số dòng. Hai thói quen chính là giống hệt nhau ngoại trừ giới hạn

Jul 11 16:11:51:490 [139681125603136] dut: Device State: ON
1 và tạo
Jul 11 16:11:51:490 [139681125603136] dut: Device State: ON
7. Nó chỉ khi bạn nhìn vào hai phiên bản của hàm trợ giúp,
 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
7, rằng sự khác biệt xuất hiện.

 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
7 đầu tiên là một bản dịch gần như theo nghĩa đen về những gì vấn đề đang yêu cầu: Thay đổi chữ cái xuống bảng chữ cái và quấn nó xung quanh tại
 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
3. Điều này rõ ràng ánh xạ trở lại tuyên bố vấn đề, nhưng nó có một vài nhược điểm.

Mặc dù nó có cùng độ dài với phiên bản thứ hai, phiên bản đầu tiên của

 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
7 phức tạp hơn. Sự phức tạp này đến từ việc chuyển đổi chữ cái và toán học cần thiết để thực hiện dịch. Các chi tiết liên quan đến việc chuyển đổi với các số, trừ đi và gói gọn các thao tác mà bạn đang thực hiện.
 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
7 thứ hai ít tham gia vào các chi tiết của nó.

Phiên bản đầu tiên của hàm cũng cụ thể để giải quyết vấn đề cụ thể này. Phiên bản thứ hai của

 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
7, như thư viện tiêu chuẩn ____ ____51 mà nó được mô hình hóa sau đó, có mục đích chung hơn và có thể được sử dụng để giải quyết một loạt các vấn đề lớn hơn. Lưu ý rằng đây không nhất thiết là một mục tiêu thiết kế tốt.

Một trong những câu thần chú xuất phát từ phong trào lập trình cực đoan là bạn, bạn sẽ cần nó [Yagni]. Thông thường, các nhà phát triển phần mềm sẽ xem xét một chức năng như

 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
7 và quyết định rằng nó sẽ tốt hơn và có mục đích chung hơn nếu họ làm cho nó trở nên linh hoạt hơn, có lẽ bằng cách chuyển trong một tham số thay vì sử dụng
 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
8.

Mặc dù điều đó thực sự sẽ làm cho chức năng trở nên chung chung hơn, nó cũng sẽ làm cho nó phức tạp hơn. Câu thần chú Yagni ở đó để nhắc nhở bạn không thêm sự phức tạp trước khi bạn có một trường hợp sử dụng cụ thể cho nó.

Để kết thúc phần Mật mã Caesar của bạn, có sự đánh đổi rõ ràng giữa hai giải pháp, nhưng

 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
7 thứ hai có vẻ như là một chức năng pythonic thứ hai tốt hơn một chút.

Bây giờ, bạn đã viết Caesar Mật mã ba cách khác nhau, hãy để Lừa chuyển sang một vấn đề mới.

Bài tập thực hành Python 4: trình phân tích cú pháp đăng nhập

Vấn đề trình phân tích cú pháp nhật ký là một vấn đề xảy ra thường xuyên trong phát triển phần mềm. Nhiều hệ thống tạo ra các tệp nhật ký trong quá trình hoạt động bình thường và đôi khi bạn sẽ cần phải phân tích các tệp này để tìm sự bất thường hoặc thông tin chung về hệ thống đang chạy.

Mô tả vấn đề

Đối với vấn đề này, bạn sẽ cần phải phân tích tệp nhật ký với định dạng được chỉ định và tạo báo cáo:

Trình phân tích cú pháp đăng nhập [

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
21] [
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
21]

Chấp nhận một tên tệp trên dòng lệnh. Tệp là một tệp nhật ký giống như Linux từ một hệ thống bạn đang gỡ lỗi. Được trộn lẫn giữa các câu lệnh khác nhau là các thông báo chỉ ra trạng thái của thiết bị. Họ trông như thế này:

Jul 11 16:11:51:490 [139681125603136] dut: Device State: ON

Thông điệp trạng thái thiết bị có nhiều giá trị có thể, nhưng chương trình này chỉ quan tâm đến ba:

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
22,
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
23 và
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
24.

Chương trình của bạn sẽ phân tích tệp nhật ký đã cho và in ra báo cáo cho thiết bị

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
22 và dấu thời gian của bất kỳ điều kiện
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
24 nào.

Lưu ý rằng mã bộ xương được cung cấp không bao gồm các bài kiểm tra đơn vị. Điều này đã bị bỏ qua vì định dạng chính xác của báo cáo là tùy thuộc vào bạn. Hãy suy nghĩ và viết của riêng bạn trong quá trình.

Một tệp

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
27 được bao gồm, cung cấp cho bạn một ví dụ. Giải pháp mà bạn sẽ kiểm tra tạo ra đầu ra sau:

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
0

Mặc dù định dạng đó được tạo ra bởi giải pháp Python thực sự, bạn có thể tự do thiết kế định dạng của riêng bạn cho đầu ra. Tệp đầu vào mẫu nên tạo thông tin tương đương.

Giải pháp vấn đề

Trong phần bị sụp đổ bên dưới, bạn sẽ tìm thấy một giải pháp khả thi cho vấn đề trình phân tích cú pháp nhật ký. Khi bạn đã sẵn sàng, hãy mở rộng hộp và so sánh nó với những gì bạn đã nghĩ ra!

Giải pháp đầy đủ

Vì giải pháp này dài hơn những gì bạn thấy đối với các tổng số nguyên hoặc các vấn đề về mật mã Caesar, hãy để bắt đầu với chương trình đầy đủ:

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
1

Đó là giải pháp đầy đủ của bạn. Bạn có thể thấy rằng chương trình bao gồm ba chức năng và phần chính. Bạn sẽ làm việc thông qua họ từ đầu.

Hàm trợ giúp:
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
28

Đầu tiên là

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
28:

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
2

Bởi vì nó chứa một câu lệnh

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
30, chức năng này là một trình tạo. Điều đó có nghĩa là bạn có thể sử dụng nó để tạo một sự kiện từ tệp nhật ký tại một thời điểm.

Bạn có thể vừa sử dụng

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
31, nhưng thay vào đó bạn thêm một chút lọc. Thói quen gọi điện sẽ chỉ nhận được những sự kiện có
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
32 trong đó. Điều này giữ cho tất cả các phân tích phân tích cụ thể trong một chức năng duy nhất.

Điều này có thể làm cho

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
28 phức tạp hơn một chút, nhưng nó là một chức năng tương đối nhỏ, vì vậy nó vẫn đủ ngắn để đọc và hiểu. Nó cũng giữ mã phức tạp được gói gọn trong một vị trí duy nhất.

Bạn có thể tự hỏi khi

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
34 bị đóng cửa. Miễn là bạn gọi trình tạo cho đến khi tất cả các dòng được đọc từ
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
34, vòng
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
36 sẽ hoàn thành, cho phép bạn rời khỏi khối
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
37 và thoát khỏi hàm.

Hàm trợ giúp:
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
38

Hàm thứ hai là

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
38, như tên cho thấy, tính toán số giây giữa hai dấu thời gian: thời gian:

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
3

Có một vài điểm thú vị cho chức năng này. Đầu tiên là việc trừ hai đối tượng

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
40 dẫn đến
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
41. Đối với vấn đề này, bạn sẽ báo cáo tổng số giây, vì vậy việc trả lại
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
42 từ
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
43 là phù hợp.

Mục thứ hai của lưu ý là có rất nhiều, rất nhiều gói trong Python đơn giản hóa ngày xử lý và thời gian. Trong trường hợp này, mô hình sử dụng của bạn đủ đơn giản để nó không đảm bảo sự phức tạp của việc kéo vào một thư viện bên ngoài khi các chức năng thư viện tiêu chuẩn sẽ đủ.

Điều đó nói rằng,

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
44 là đáng được đề cập. Khi được truyền một chuỗi và một định dạng cụ thể, ____ 145 phân tích cú pháp chuỗi đó có định dạng đã cho và tạo ra một đối tượng
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
40.

Đây là một nơi khác, trong một tình huống phỏng vấn, điều quan trọng là không hoảng sợ nếu bạn có thể nhớ tên chính xác của các chức năng thư viện tiêu chuẩn Python.

Tiếp theo là

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
47, phần lớn công việc trong chương trình này. Trước khi bạn đi sâu vào mã, hãy để Lùi lại và nói về các máy nhà nước.

Máy trạng thái là các thiết bị phần mềm [hoặc phần cứng] chuyển từ trạng thái này sang trạng thái khác tùy thuộc vào đầu vào cụ thể. Đó là một định nghĩa thực sự rộng rãi có thể khó nắm bắt, vì vậy, hãy để nhìn vào một sơ đồ của máy trạng thái mà bạn sẽ sử dụng dưới đây: are software [or hardware] devices that transition from one state to another depending on specific inputs. That’s a really broad definition that might be difficult to grasp, so let’s look at a diagram of the state machine you’ll be using below:

Trong sơ đồ này, các trạng thái được đại diện bởi các hộp được dán nhãn. Chỉ có hai trạng thái ở đây,

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
22 và
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
23, tương ứng với trạng thái của thiết bị. Ngoài ra còn có hai tín hiệu đầu vào,
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
50 và
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
51. Sơ đồ sử dụng mũi tên để hiển thị những gì xảy ra khi đầu vào xảy ra trong khi máy ở mỗi trạng thái.

Ví dụ: nếu máy ở trạng thái

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
22 và đầu vào
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
50 xảy ra, thì máy vẫn ở trạng thái
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
22. Không có thay đổi xảy ra. Ngược lại, nếu máy nhận được đầu vào
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
51 khi nó ở trạng thái
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
22, thì nó sẽ chuyển sang trạng thái
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
23.

Mặc dù máy trạng thái ở đây chỉ là hai trạng thái có hai đầu vào, máy trạng thái thường phức tạp hơn nhiều. Tạo sơ đồ hành vi dự kiến ​​có thể giúp bạn làm cho mã thực hiện máy trạng thái ngắn gọn hơn.

Hãy để Lừa chuyển trở lại

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
47:

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
4

Có thể khó nhìn thấy máy nhà nước ở đây. Thông thường, máy trạng thái yêu cầu một biến để giữ trạng thái. Trong trường hợp này, bạn sử dụng

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
59 để phục vụ hai mục đích:

  1. Chỉ ra trạng thái:
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    59 giữ trạng thái của máy trạng thái của bạn. Nếu nó
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    61, thì máy ở trạng thái
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    23. Nếu nó
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    63, thì máy là
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    22.
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    59 holds the state of your state machine. If it’s
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    61, then the machine is in the
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    23 state. If it’s
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    63, then the machine is
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    22.
  2. Lưu trữ Thời gian bắt đầu: Nếu trạng thái là
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    22, thì
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    59 cũng giữ dấu thời gian khi thiết bị bật. Bạn sử dụng dấu thời gian này để gọi
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    38.
    If the state is
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    22, then
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    59 also holds the timestamp of when the device turned on. You use this timestamp to call
    # integersums.py
    def better[n]:
        sum = 0
        for num in range[n + 1]:
            sum += num
        return sum
    
    38.

Đầu của

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
47 thiết lập biến trạng thái của bạn,
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
59 và cả hai đầu ra bạn muốn.
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
70 là danh sách các dấu thời gian mà tại đó thông báo
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
24 được tìm thấy và
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
72 là tổng của tất cả các giai đoạn khi thiết bị được bật.

Khi bạn đã hoàn thành thiết lập ban đầu, bạn gọi trình tạo

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
28 để truy xuất từng sự kiện và dấu thời gian.
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
74 mà nó nhận được được sử dụng để điều khiển máy trạng thái, nhưng trước khi kiểm tra các thay đổi trạng thái, trước tiên, nó sử dụng khối
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
75 để lọc bất kỳ điều kiện
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
24 nào và thêm chúng vào
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
70.

Sau khi kiểm tra lỗi, khối

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
78 đầu tiên xử lý việc chuyển sang trạng thái
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
22. Bạn chỉ có thể chuyển sang
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
22 khi bạn ở trạng thái
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
23, được báo hiệu bởi
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
59 là
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
83. Nếu bạn chưa ở trạng thái
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
22 và hành động là
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
85, thì bạn lưu trữ
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
86, đưa máy vào trạng thái
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
22.

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
78 thứ hai xử lý quá trình chuyển đổi sang trạng thái
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
23. Trong quá trình chuyển đổi này,
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
47 cần tính toán số giây mà thiết bị đã bật. Nó thực hiện điều này bằng cách sử dụng
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
38 mà bạn đã thấy ở trên. Nó thêm vào thời gian này vào hoạt động
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
72 và đặt
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
59 trở lại
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
61, đưa máy trở lại trạng thái
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
23 một cách hiệu quả.

Chức năng chính

Cuối cùng, bạn có thể chuyển sang phần

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
96. Phần cuối cùng này vượt qua
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
97, là đối số dòng lệnh đầu tiên, đến
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
47 và sau đó trình bày một báo cáo về kết quả:

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
5

Để gọi giải pháp này, bạn chạy tập lệnh và chuyển tên của tệp nhật ký. Chạy mã ví dụ của bạn dẫn đến kết quả đầu ra này:

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
6

Giải pháp của bạn có thể có định dạng khác nhau, nhưng thông tin phải giống nhau cho tệp nhật ký mẫu.

Có nhiều cách để giải quyết một vấn đề như thế này. Hãy nhớ rằng trong một tình huống phỏng vấn, nói qua vấn đề và quá trình suy nghĩ của bạn có thể quan trọng hơn giải pháp bạn chọn để thực hiện.

Đó là nó cho giải pháp phân tích log. Hãy cùng chuyển sang thử thách cuối cùng: Sudoku!

Bài tập thực hành Python 5: Giải quyết Sudoku

Vấn đề thực hành Python cuối cùng của bạn là giải một câu đố Sudoku!

Tìm một giải pháp nhanh chóng và tiết kiệm bộ nhớ cho vấn đề này có thể là một thách thức khá lớn. Giải pháp mà bạn sẽ kiểm tra đã được chọn để đọc thay vì tốc độ, nhưng bạn có thể tự do tối ưu hóa giải pháp của mình nhiều như bạn muốn.

Mô tả vấn đề

Mô tả cho bộ giải Sudoku có liên quan nhiều hơn một chút so với các vấn đề trước đây:

Giải quyết Sudoku [

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
99] [
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
99]

Đưa ra một chuỗi ở định dạng SDM, được mô tả bên dưới, viết một chương trình để tìm và trả lại giải pháp cho câu đố Sudoku trong chuỗi. Giải pháp nên được trả về ở cùng định dạng SDM với đầu vào.

Một số câu đố sẽ không thể giải được. Trong trường hợp đó, hãy trả lại chuỗi không thể giải quyết được.

Định dạng SDM chung được mô tả ở đây.

Đối với mục đích của chúng tôi, mỗi chuỗi SDM sẽ là một chuỗi 81 chữ số, một chữ cái cho mỗi vị trí trên câu đố Sudoku. Các số đã biết sẽ được đưa ra và các vị trí chưa biết sẽ có giá trị bằng không.

Ví dụ: giả sử bạn đã đưa ra chuỗi chữ số này:

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
7

Chuỗi đại diện cho câu đố Sudoku bắt đầu này:

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
8

Các bài kiểm tra đơn vị được cung cấp có thể mất một lúc để chạy, vì vậy hãy kiên nhẫn.

Lưu ý: Một mô tả về câu đố Sudoku có thể được tìm thấy trên Wikipedia. A description of the sudoku puzzle can be found on Wikipedia.

Bạn có thể thấy rằng bạn sẽ cần phải đối phó với việc đọc và viết sang một định dạng cụ thể cũng như tạo ra một giải pháp.

Giải pháp vấn đề

Khi bạn đã sẵn sàng, bạn có thể tìm thấy một lời giải thích chi tiết về một giải pháp cho vấn đề Sudoku trong hộp bên dưới. Một tệp bộ xương với các bài kiểm tra đơn vị được cung cấp trong repo.

Đây là một vấn đề lớn hơn và phức tạp hơn so với bạn đã xem xét cho đến nay trong hướng dẫn này. Bạn sẽ đi qua vấn đề từng bước, kết thúc bằng một chức năng đệ quy để giải câu đố. Ở đây, một phác thảo sơ bộ về các bước bạn sẽ thực hiện:

  • Đọc câu đố vào một dạng lưới. the puzzle into a grid form.
  • Đối với mỗi ô:
    • Đối với mỗi số có thể trong ô đó:
      • Đặt số trong ô. the number in the cell.
      • Hủy bỏ số đó khỏi hàng, cột và hình vuông nhỏ. that number from the row, column, and small square.
      • Di chuyển đến vị trí tiếp theo. to the next position.
    • Nếu không có số có thể vẫn còn, thì hãy khai báo câu đố không thể giải quyết được.unsolvable.
    • Nếu tất cả các ô được lấp đầy, sau đó trả lại giải pháp.return the solution.

Phần khó khăn của thuật toán này là theo dõi lưới ở mỗi bước của quy trình. Bạn sẽ sử dụng đệ quy, tạo một bản sao mới của lưới ở mỗi cấp độ của đệ quy, để duy trì thông tin này.

Với phác thảo đó trong tâm trí, hãy để bắt đầu với bước đầu tiên, tạo lưới.

Tạo ra một lưới từ một dòng

Để bắt đầu, nó rất hữu ích để chuyển đổi dữ liệu câu đố thành định dạng có thể sử dụng hơn. Ngay cả khi cuối cùng bạn muốn giải câu đố ở định dạng SDM đã cho, bạn có thể sẽ thực hiện tiến độ nhanh hơn hoạt động thông qua các chi tiết của thuật toán của bạn với dữ liệu ở dạng lưới. Khi bạn có một giải pháp hoạt động, thì bạn có thể chuyển đổi nó để hoạt động trên một cấu trúc dữ liệu khác.

Cuối cùng, hãy để bắt đầu với một vài chức năng chuyển đổi:

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
9

Hàm đầu tiên của bạn,

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
00, chuyển đổi dữ liệu từ một chuỗi gồm tám mươi mốt chữ số thành danh sách danh sách. Ví dụ: nó chuyển đổi chuỗi
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
01 thành lưới như
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
02:

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
0

Mỗi danh sách bên trong ở đây đại diện cho một hàng ngang trong câu đố sudoku của bạn.

Bạn bắt đầu với một

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
03 trống và một
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
01 trống rỗng. Sau đó, bạn xây dựng mỗi
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
01 bằng cách chuyển đổi chín ký tự từ chuỗi
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
06 sang số nguyên một chữ số và sau đó thêm chúng vào
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
01 hiện tại. Khi bạn có chín giá trị trong
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
01, như được chỉ ra bởi
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
09 trên dòng 7, bạn chèn
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
01 vào
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
03 và bắt đầu một cái mới.

Hàm kết thúc bằng cách nối thêm

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
01 cuối cùng vào
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
03. Bạn cần điều này bởi vì vòng lặp
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
36 sẽ kết thúc với
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
01 cuối cùng vẫn được lưu trữ trong biến cục bộ và chưa được thêm vào
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
03.

Hàm nghịch đảo,

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
17, ngắn hơn một chút. Nó sử dụng biểu thức máy phát với
 1# caesar.py
 2import string
 3
 4def shift_n[letter, table]:
 5    try:
 6        index = string.ascii_lowercase.index[letter]
 7        return table[index]
 8    except ValueError:
 9        return letter
10
11def caesar[message, amount]:
12    amount = amount % 26
13    table = string.ascii_lowercase[amount:] + string.ascii_lowercase[:amount]
14    enc_list = [shift_n[letter, table] for letter in message]
15    return "".join[enc_list]
6 để tạo chuỗi chín chữ số cho mỗi hàng. Sau đó, nó nối chuỗi đó vào tổng thể
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
01 và trả về nó. Lưu ý rằng nó có thể sử dụng các trình tạo lồng nhau để tạo ra kết quả này trong ít dòng mã hơn, nhưng khả năng đọc của giải pháp bắt đầu giảm đáng kể.

Bây giờ bạn đã có dữ liệu trong cấu trúc dữ liệu bạn muốn, hãy để bắt đầu làm việc với nó.

Tạo ra một vòng lặp vuông nhỏ

Chức năng tiếp theo của bạn là một trình tạo sẽ giúp bạn tìm kiếm vị trí nhỏ hơn ba chiều một vị trí nhất định. Đã đưa ra các tọa độ X và Y Hình vuông chứa nó:

Trong hình trên, bạn đã kiểm tra ô

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
20, vì vậy trình tạo của bạn sẽ tạo ra các cặp tọa độ tương ứng với tất cả các ô được tô bóng nhẹ, bỏ qua các tọa độ được truyền vào:

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
1

Đặt logic để xác định hình vuông nhỏ này vào một hàm tiện ích riêng biệt giữ cho dòng chảy của các chức năng khác của bạn dễ đọc hơn. Làm cho nó trở thành một trình tạo cho phép bạn sử dụng nó trong vòng lặp

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
36 để lặp qua từng giá trị.

Hàm để làm điều này liên quan đến việc sử dụng các hạn chế của toán học số nguyên:

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
2

Có rất nhiều threes trong một vài dòng đó, làm cho các dòng như

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
22 trông khó hiểu. Ở đây, những gì xảy ra khi
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
23 là
# integersums.py
def add_it_up[n]:
    try:
        result = sum[range[n + 1]]
    except TypeError:
        result = 0
    return result
3.

>>>

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
3

Sử dụng cách làm tròn của toán học số nguyên cho phép bạn có được bội số cao nhất tiếp theo của ba giá trị nhất định. Khi bạn có cái này, trừ ba sẽ cung cấp cho bạn bội số ba bên dưới số đã cho.

Có một vài chức năng tiện ích cấp thấp hơn để kiểm tra trước khi bạn bắt đầu xây dựng trên đầu chúng.

Chuyển đến vị trí tiếp theo

Giải pháp của bạn sẽ cần phải đi qua cấu trúc lưới một ô tại một thời điểm. Điều này có nghĩa là tại một số điểm, bạn sẽ cần phải tìm ra vị trí tiếp theo nên là gì.

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
25 để giải cứu!

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
25 lấy các tọa độ X và Y hiện tại làm đầu vào và trả về một tuple chứa cờ
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
27 cùng với các tọa độ X và Y của vị trí tiếp theo:

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
4

Cờ ____227 cho người gọi rằng thuật toán đã bỏ qua cuối câu đố và đã hoàn thành tất cả các ô vuông. Bạn có thể thấy cách mà sử dụng trong phần sau.

Loại bỏ các số không thể

Tiện ích cấp thấp cuối cùng của bạn là khá nhỏ. Nó lấy một giá trị số nguyên và một điều khác. Nếu giá trị là khác nhau và xuất hiện trong ITBEBLE, thì hàm sẽ loại bỏ nó khỏi điều đáng tin cậy:

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
5

Thông thường, bạn sẽ biến một chút chức năng nhỏ này thành một chức năng. Tuy nhiên, bạn sẽ sử dụng chức năng này nhiều lần, vì vậy, tốt nhất là phải tuân theo nguyên tắc khô hạn và kéo nó lên một chức năng.

Bây giờ bạn đã thấy mức dưới cùng của kim tự tháp chức năng. Đó là thời gian để bước lên và sử dụng các công cụ đó để xây dựng một chức năng phức tạp hơn. Bạn gần như đã sẵn sàng để giải câu đố!

Tìm kiếm những gì có thể

Chức năng tiếp theo của bạn sử dụng một số chức năng cấp thấp mà bạn đã đi qua. Đưa ra một lưới và một vị trí trên lưới đó, nó xác định vị trí mà vị trí đó vẫn có thể có:

Đối với lưới ở trên, tại vị trí

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
20, các giá trị có thể là
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
30 vì các giá trị khác đều có mặt, trong hàng hoặc cột đó hoặc trong hình vuông nhỏ mà bạn đã xem xét trước đó.

Đây là trách nhiệm của

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
31:

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
6

Hàm bắt đầu bằng cách kiểm tra xem vị trí đã cho tại

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
23 và
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
33 đã có giá trị khác. Nếu vậy, thì đó là giá trị duy nhất có thể và nó trả về.

Nếu không, thì hàm tạo ra một tập hợp các số một đến chín. Chức năng tiến hành kiểm tra các số chặn khác nhau và loại bỏ các số khác khỏi bộ này.

Nó bắt đầu bằng cách kiểm tra cột và hàng của vị trí đã cho. Điều này có thể được thực hiện với một vòng lặp duy nhất bằng cách xen kẽ thay đổi chỉ số nào.

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
34 Kiểm tra các giá trị trong cùng một cột, trong khi
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
35 kiểm tra các giá trị đó trong cùng một hàng. Bạn có thể thấy rằng bạn đang sử dụng
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
36 ở đây để đơn giản hóa mã.

Khi các giá trị đó đã bị xóa khỏi bộ

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
37 của bạn, hàm di chuyển đến hình vuông nhỏ. Đây là nơi mà Trình tạo
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
38 bạn đã tạo trước khi có ích. Bạn có thể sử dụng nó để lặp lại từng vị trí trong hình vuông nhỏ, một lần nữa sử dụng
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
36 để loại bỏ bất kỳ giá trị nào đã biết khỏi danh sách
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
37 của bạn.

Khi tất cả các giá trị chặn đã biết đã bị xóa khỏi bộ của bạn, bạn có danh sách tất cả các giá trị

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
37 cho vị trí đó trên lưới đó.

Bạn có thể tự hỏi tại sao mã và mô tả của nó lại đưa ra quan điểm về vị trí là trên mạng đó. Trong chức năng tiếp theo của bạn, bạn sẽ thấy rằng chương trình tạo ra nhiều bản sao của lưới khi nó cố gắng giải quyết nó.

Giải quyết nó

Bạn đã đạt đến trung tâm của giải pháp này:

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
42! Hàm này là đệ quy, vì vậy một lời giải thích trước một chút có thể giúp ích.

Thiết kế chung của

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
42 dựa trên việc thử nghiệm một vị trí tại một thời điểm. Đối với vị trí quan tâm, thuật toán nhận được danh sách các giá trị có thể và sau đó chọn các giá trị đó, một lần, ở vị trí này.

Đối với mỗi giá trị này, nó tạo ra một lưới với giá trị đoán ở vị trí này. Sau đó, nó gọi một chức năng để kiểm tra giải pháp, chuyển trong lưới mới và vị trí tiếp theo.

Nó chỉ xảy ra rằng chức năng mà nó gọi là chính nó.

Đối với bất kỳ đệ quy, bạn cần một điều kiện chấm dứt. Thuật toán này có bốn trong số chúng:

  1. Không có giá trị có thể cho vị trí này. Điều đó cho thấy giải pháp mà nó thử nghiệm có thể làm việc.
  2. Nó đi bộ đến cuối lưới và tìm thấy một giá trị có thể cho từng vị trí. Câu đố được giải quyết!
  3. Một trong những dự đoán ở vị trí này, khi được chuyển trở lại cho người giải, trả lại một giải pháp.
  4. Nó đã thử tất cả các giá trị có thể ở vị trí này và không ai trong số chúng sẽ hoạt động.

Chúng ta hãy nhìn vào mã cho điều này và xem tất cả các diễn ra như thế nào:

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
7

Điều đầu tiên cần lưu ý trong chức năng này là nó tạo ra một

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
44 của lưới. Nó thực hiện một bản sao sâu vì thuật toán cần theo dõi chính xác nơi nó ở bất kỳ điểm nào trong đệ quy. Nếu hàm chỉ tạo một bản sao nông, thì mọi phiên bản đệ quy của hàm này sẽ sử dụng cùng một lưới.deep copy because the algorithm needs to keep track of exactly where it was at any point in the recursion. If the function made only a shallow copy, then every recursive version of this function would use the same grid.

Khi lưới được sao chép,

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
42 có thể hoạt động với bản sao mới,
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
46. Một vị trí trên lưới đã được thông qua, do đó, đó là số mà phiên bản này của hàm này sẽ giải quyết. Bước đầu tiên là xem những giá trị nào có thể ở vị trí này. Như bạn đã thấy trước đó,
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
31 trả về một danh sách các giá trị có thể có thể trống.

Nếu không có giá trị có thể, thì bạn đã đạt được điều kiện chấm dứt đầu tiên cho đệ quy. Hàm trả về

# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
83 và thói quen gọi di chuyển.

Nếu có các giá trị có thể, thì bạn cần phải tiếp tục và xem bất kỳ trong số chúng là một giải pháp. Trước khi bạn làm điều đó, bạn có thể thêm một chút tối ưu hóa vào mã. Nếu chỉ có một giá trị có thể, thì bạn có thể chèn giá trị đó và chuyển sang vị trí tiếp theo. Giải pháp hiển thị thực hiện điều này trong một vòng lặp, vì vậy bạn có thể đặt nhiều số vào lưới mà không cần phải tái diễn.

Điều này có vẻ như là một cải tiến nhỏ và tôi sẽ thừa nhận việc thực hiện đầu tiên của tôi không bao gồm điều này. Nhưng một số thử nghiệm cho thấy giải pháp này nhanh hơn đáng kể so với đơn giản là định kỳ ở đây với giá của mã phức tạp hơn.

Đôi khi, tất nhiên, sẽ có nhiều giá trị có thể cho vị trí hiện tại và bạn sẽ cần phải quyết định xem có ai trong số chúng sẽ dẫn đến một giải pháp hay không. May mắn thay, bạn đã xác định vị trí tiếp theo trong lưới, vì vậy bạn có thể từ bỏ các giá trị có thể.

Nếu vị trí tiếp theo là kết thúc của lưới, thì vị trí hiện tại là vị trí cuối cùng để điền. Nếu bạn biết rằng có ít nhất một giá trị có thể cho vị trí này, thì bạn đã tìm thấy một giải pháp! Vị trí hiện tại được điền vào và lưới hoàn thành được đưa trở lại chức năng gọi.

Nếu vị trí tiếp theo vẫn nằm trên lưới, thì bạn lặp qua từng giá trị có thể cho vị trí hiện tại, điền vào dự đoán tại vị trí hiện tại và sau đó gọi

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
42 với lưới
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
46 và vị trí mới để kiểm tra.

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
42 chỉ có thể trả về một lưới đã hoàn thành hoặc
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
83, vì vậy nếu bất kỳ dự đoán nào có thể trả về kết quả đó là
# integersums.py
def better[n]:
    sum = 0
    for num in range[n + 1]:
        sum += num
    return sum
83, thì kết quả đã được tìm thấy và lưới đó có thể được trả lại.

Nếu tất cả các dự đoán có thể đã được thực hiện và không ai trong số chúng là một giải pháp, thì lưới được thông qua là không thể giải quyết được. Nếu đây là cuộc gọi cấp cao nhất, thì điều đó có nghĩa là câu đố không thể giải quyết được. Nếu cuộc gọi thấp hơn trong cây đệ quy, thì điều đó chỉ có nghĩa là nhánh của cây đệ quy này không thể.

Để tất cả chúng cùng nhau

Tại thời điểm này, bạn gần như thông qua giải pháp. Ở đó, chỉ còn một chức năng cuối cùng,

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
54:

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
8

Chức năng này thực hiện ba điều:

  1. Chuyển đổi chuỗi đầu vào thành một lưới
  2. Gọi
    # integersums.py
    def even_better[n]:
        return sum[range[n + 1]]
    
    42 với lưới đó để có được giải pháp
  3. Trả về giải pháp dưới dạng chuỗi hoặc
    # integersums.py
    def even_better[n]:
        return sum[range[n + 1]]
    
    56 nếu không có giải pháp

Đó là nó! Bạn đã đi qua một giải pháp cho vấn đề giải quyết Sudoku.

Phỏng vấn các chủ đề thảo luận

Giải pháp giải quyết Sudoku mà bạn vừa đi qua là một mã tốt cho một tình huống phỏng vấn. Một phần của quá trình phỏng vấn có thể là thảo luận về một số mã và quan trọng hơn là một số sự đánh đổi thiết kế mà bạn đã thực hiện. Hãy cùng xem xét một vài trong số những sự đánh đổi đó.

Đệ quy

Quyết định thiết kế lớn nhất xoay quanh việc sử dụng đệ quy. Nó có thể viết một giải pháp không nhận được cho bất kỳ vấn đề nào có giải pháp đệ quy. Tại sao chọn đệ quy qua một lựa chọn khác?

Đây là một cuộc thảo luận không chỉ phụ thuộc vào vấn đề mà còn vào các nhà phát triển liên quan đến việc viết và duy trì giải pháp. Một số vấn đề cho vay để giải pháp đệ quy khá sạch sẽ, và một số don don.

Nói chung, các giải pháp đệ quy sẽ mất nhiều thời gian hơn để chạy và sử dụng nhiều bộ nhớ hơn các giải pháp không được ghi. Nhưng điều đó không phải lúc nào cũng đúng và quan trọng hơn, nó không phải lúc nào cũng quan trọng.

Tương tự, một số nhóm các nhà phát triển thoải mái với các giải pháp đệ quy, trong khi những nhóm khác thấy chúng kỳ lạ hoặc phức tạp không cần thiết. Khả năng duy trì nên chơi vào các quyết định thiết kế của bạn là tốt.

Một cuộc thảo luận tốt để có về một quyết định như thế này là xung quanh hiệu suất. Giải pháp này cần thực hiện nhanh như thế nào? Nó sẽ được sử dụng để giải quyết hàng tỷ câu đố hay chỉ là một số ít? Nó sẽ chạy trên một hệ thống nhúng nhỏ với các ràng buộc bộ nhớ, hay nó sẽ ở trên một máy chủ lớn?

Những yếu tố bên ngoài này có thể giúp bạn quyết định đó là một quyết định thiết kế tốt hơn. Đây là những chủ đề tuyệt vời để đưa ra một cuộc phỏng vấn khi bạn làm việc thông qua một vấn đề hoặc thảo luận về mã. Một sản phẩm duy nhất có thể có những nơi mà hiệu suất rất quan trọng [ví dụ như thực hiện theo dõi tia trên thuật toán đồ họa] và nơi nó không quan trọng [chẳng hạn như phân tích số phiên bản trong quá trình cài đặt].

Đưa ra các chủ đề như thế này trong một cuộc phỏng vấn cho thấy bạn không chỉ nghĩ về việc giải quyết một vấn đề trừu tượng, mà bạn còn sẵn sàng và có thể đưa nó lên một tầm cao mới và giải quyết một vấn đề cụ thể mà nhóm phải đối mặt.

Khả năng đọc và khả năng bảo trì

Đôi khi, nó đáng để chọn một giải pháp mà chậm hơn để tạo ra một giải pháp dễ dàng hơn để làm việc, gỡ lỗi và mở rộng. Quyết định trong thách thức bộ giải Sudoku để chuyển đổi cấu trúc dữ liệu thành lưới là một trong những quyết định đó.

Quyết định thiết kế đó có thể làm chậm chương trình, nhưng trừ khi bạn đo lường, bạn không biết. Ngay cả khi nó xảy ra, việc đặt cấu trúc dữ liệu vào một hình thức mà tự nhiên cho vấn đề có thể giúp mã dễ hiểu hơn.

Nó hoàn toàn có thể viết một bộ giải hoạt động trên các chuỗi tuyến tính mà bạn đã đưa ra làm đầu vào. Nó có khả năng nhanh hơn và có thể mất ít bộ nhớ hơn, nhưng

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
38, trong số những người khác, sẽ khó viết hơn, đọc và duy trì trong phiên bản này.

Sai lầm

Một điều khác để thảo luận với một người phỏng vấn, cho dù bạn có mã hóa trực tiếp hay thảo luận về mã bạn đã viết ngoại tuyến, là những sai lầm và lượt sai mà bạn đã thực hiện trên đường đi.

Điều này ít rõ ràng hơn và có thể hơi bất lợi, nhưng đặc biệt nếu bạn mã hóa trực tiếp, hãy thực hiện một bước để tái cấu trúc mã không đúng hoặc có thể tốt hơn có thể cho thấy cách bạn làm việc. Rất ít nhà phát triển có thể viết mã hoàn hảo lần đầu tiên. Heck, ít nhà phát triển có thể viết mã tốt lần đầu tiên.

Các nhà phát triển giỏi viết mã, sau đó quay lại và tái cấu trúc nó và sửa nó. Ví dụ: lần thực hiện đầu tiên của tôi về

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
31 trông như thế này:

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
9

Bỏ qua rằng nó không xem xét thông tin

# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
38, mã này có thể được cải thiện. Nếu bạn so sánh điều này với phiên bản cuối cùng của
# integersums.py
def even_better[n]:
    return sum[range[n + 1]]
31 ở trên, bạn sẽ thấy rằng phiên bản cuối cùng sử dụng một vòng lặp duy nhất để kiểm tra cả kích thước ngang và chiều dọc.

Gói lên

Đó là chuyến lưu diễn của bạn thông qua một giải pháp giải quyết Sudoku. Có thêm thông tin có sẵn trên các định dạng để lưu trữ các câu đố và một danh sách lớn các câu đố Sudoku mà bạn có thể kiểm tra thuật toán của mình.

Đó là sự kết thúc của cuộc phiêu lưu thực hành Python của bạn! Nhưng nếu bạn thích hơn nữa, hãy tham gia khóa học video và kiểm tra chức năng Python: Thực hành phỏng vấn để xem một nhà phát triển có kinh nghiệm giải quyết vấn đề phỏng vấn trong thời gian thực.

Sự kết luận

Chúc mừng bạn đã làm việc thông qua bộ vấn đề thực hành Python này! Bạn đã nhận được một số thực hành áp dụng các kỹ năng Python của bạn và cũng dành một chút thời gian để suy nghĩ về cách bạn có thể trả lời trong các tình huống phỏng vấn khác nhau.

Trong hướng dẫn này, bạn đã học được cách:

  • Viết mã cho các vấn đề về kiểu phỏng vấn for interview-style problems
  • Thảo luận về các giải pháp của bạn trong cuộc phỏng vấn during the interview
  • Làm việc thông qua các chi tiết thường xuyên bị bỏ quafrequently overlooked details
  • Nói về các quyết định thiết kế và đánh đổidesign decisions and trade-offs

Hãy nhớ rằng, bạn có thể tải xuống mã bộ xương cho những vấn đề này bằng cách nhấp vào liên kết bên dưới:

Hãy tiếp cận trong phần bình luận với bất kỳ câu hỏi nào bạn có hoặc đề xuất cho các vấn đề thực hành Python khác mà bạn muốn xem! Ngoài ra, hãy xem cuộc phỏng vấn mã hóa Python của bạn, con đường học tập của bạn để có thêm tài nguyên và tăng cường kỹ năng phỏng vấn Python của bạn.

Chúc may mắn với cuộc phỏng vấn!

Bài Viết Liên Quan

Chủ Đề