題目:找出藏在字符串中的“密碼”
(1) 描述
1) 題源 1 Python Challenge, level 3
2) 題源 2 小甲魚老師的 Python 課程,第 20 講課后習題
3) 修改
- 題中帶有一條極長的字符串,不方便寫在此隨筆中
- 我自己心血來潮,將題目小小地改動了一下(其實是降低了難度)
- 具體見下方要求
(2) 要求
- 有一字符串,僅含英文字母(沒有回車、空格)
- 若有 1 個小寫的英文字母,其左右兩邊均有且僅有 3 個大寫字母,則將其挑出
- 將所有挑出的字母按順序輸出
- 例如
- 字符串:AAAAjBBBpCCCrDDmEEEyFFFqqGGG
- 輸出:py
(3) 程序
解法 1:一一檢測(像是暴力破解)
def decrypt(string):
len_str = len(string)
target = 4
if \ # 檢測開頭,即檢測整串字符串的第 3 位
string[0].isupper() and \
string[1].isupper() and \
string[2].isupper() and \
string[3].islower() and \
string[4].isupper() and \
string[5].isupper() and \
string[6].isupper() and \
string[7].islower():
print(string[3], end='')
while target < len_str-4:
if \# 檢測中間
string[target-4].islower() and \ # 若有多種字符,可用 not string[i].isupper()
string[target-3].isupper() and \
string[target-2].isupper() and \
string[target-1].isupper() and \
string[target ].islower() and \
string[target+1].isupper() and \
string[target+2].isupper() and \
string[target+3].isupper() and \
string[target+4].islower():
print(string[target], end='')
target += 4
else:
target += 1
if \ # 檢測結尾,即檢測整串字符串的倒數第 4 位
string[len_str-7].islower() and \
string[len_str-6].isupper() and \
string[len_str-5].isupper() and \
string[len_str-4].islower() and \
string[len_str-3].islower() and \
string[len_str-2].isupper() and \
string[len_str-1].isupper() and \
string[len_str ].isupper():
print(string[len_str-3], end='')
解法 2:利用編號
- 利用列表,使字符串中的每個字符都有一個對應的編號
- 因為字符串中只有大小寫英文字母,所以先理出所有小寫英文字母的編號,再檢查編號的間距
- 若某個編號與其左右相鄰的編號均相差 4,則該編號對應的字母即為所求之一
ABCdEFGhIj
0123456789
↓ ↓ ↓
3 7 9 # 第一輪,篩出小寫字母的編號
↓
3 # 第二輪,篩出符合規則的字母的編號
def decrypt(string):
len_str = len(string)
list0 = []
for i in range(len_str): # 找出所有小寫字母在 string 中的編號,並寫入 list0
if string[i].islower():
list0.append(i)
list1 = []
if list0[0] == 3 and list0[1] == 7: # 檢測開頭,即檢測整串字符串的第 3 位
list1.append(3)
for i in range(1, len(list0)): # 檢測中間,找出 list0 中符合要求的小寫字母的編號
if (list0[i]-4) == list0[i-1] and (list0[i]+4) == list0[i+1]:
list1.append(list0[i])
if list0[-1] == len_str-4 and list0[-2] == len_str-8:
# 檢測結尾,即檢測整串字符串的倒數第 4 位
list1.append(list0[-1])
for i in list1: # 輸出
print(string[i], end='')
解法 3:利用 3 個變量,統計大小寫字母的個數
(詳見下方 countA、countB、countC)
def decrypt(string):
countA = 0 # 統計小寫字母左側的大寫字母
countB = 0 # 統計小寫字母
countC = 0 # 統計小寫字母右側的大寫字母
len_str = len(string)
for i in range(len_str):
if string[i].isupper():
if countB: # AAAaA; AAAaAA; AAAaAAA
countC += 1
else: # A; AA; AAA; AAAA ...
countC = 0
countA += 1
if string[i].islower():
if countA != 3: # a; Aa; AAa; AAAAa ...
countA = 0
countB = 0
countC = 0
else:
if countB: # AAAaa
countA = 0
countB = 0
countC = 0
else: # AAAa
countB = 1
countC = 0
target = i
if countC == 3:
if i+1 != len_str and \ # 若 i 未迭代到最后一位
string[i+1].isupper(): # AAAaAAAA
countB = 0
countC = 0
else: # AAAaAAAb 總算找到了一個 a
print(string[target], end='')
countA = 3 # AAAb
countB = 0
countC = 0
解法 4:re 模塊
- re 模塊像“掛”似的
import re
text = "xxx" # 改 x 或用文件導入
pattern = "[^A-Z][A-Z]{3}([a-z])[A-Z]{3}[^A-Z]" # 設置格式
print(''.join(re.findall(pattern, text)))