[CPE一星49題] UVA10008 - What's Cryptanalysis 題目解析與實作
編輯製作: 莊祺仁、蔡豐聲
出品團隊: 中國醫藥大學 醫療資訊學系 程式俱樂部
YT: https://youtu.be/lim8mc4xOqc
## 題目資訊
- 題目名稱: What's Cryptanalysis
- 編號: CPE10402, UVA10008
- 相關平台: Zero Judge, Online Judge
## 題目解析
密碼翻譯(Cryptanalysis)是指把某個人寫的密文(Cryptographic writing)加以分解。這個程序通常會對密文訊息做統計分析。你的任務就是寫一個程式來對給定的密文進行簡單的字元統計分析。
## 輸入說明
輸入的第 1 列有一個正整數 $n$,代表以下有多少列需要作分析的密文。
接下來的 $n$ 列,每列含有 0 或多個字元(可能包含空格、標點符號與數字)。
## 輸出說明
- 統計輸入中所有英文字母出現的頻率(大小寫視為相同,例如
A與a算同一字元)。
- 每列包含一個大寫字元 (A~Z) 和一個正整數(代表該字母出現的次數),兩者以空格分開。
- 排序規則:
- 按照字元出現的次數由大到小排列(降序)。
- 如果有 2 個以上的字元出現次數相同,則按照字母順序由小到大排列(升序,如
A在H之前)。
- 注意:若某一字母未在輸入中出現過,則不應出現在輸出中。
## 範例測試
- 輸入:
3
This is a test.
Count me 1 2 3 4 5.
Wow!!!! Is this question easy?
- 輸出:
S 7
T 6
I 5
E 4
O 3
A 2
H 2
N 2
U 2
W 2
C 1
M 1
Q 1
Y 1
## 解題思路
- 字串處理常用方法
char.upper():將字元轉換為大寫,方便不分大小寫合併計數。char.isalpha():檢查字元是否為英文字母,可用來過濾標點符號、數字與空格。
- 字典(Dictionary)計數
- 利用字典結構儲存
{字母: 出現次數}。 - 當讀到字母時,若已在字典中則累加
+1,若尚未出現則初始化設為1(亦可使用dict.get(key, 0) + 1)。
- 多條件自訂排序(sorted + lambda)
- 使用
dict.items()取出所有(key, value)(即(字母, 次數))的鍵值對。 - 透過
lambda item: (-item[1], item[0])設定複合排序鍵:
(i) -item[1]:次數加上負號,使出現次數呈現由大到小(降序)。 (ii) item[0]:當次數相同時,依字母本身順序呈現由小到大(升序)。## 實作程式碼 (Python)
# 1. 讀取整數 n
n = int(input())
# 初始化一個字典,用來記錄每個字母出現的次數
total = {}
# 2. 讀取 n 行輸入字串
for _ in range(n):
str_a = input() # 讀取一行字串
# 逐字走訪字串中的每個字元
for char in str_a:
char = char.upper() # 將字元轉為大寫,實現不分大小寫統計
if char.isalpha(): # 檢查是否為英文字母 (過濾掉標點符號、數字與空格)
if char in total:
total[char] += 1 # 若字母已存在字典中,累加計數
else:
total[char] = 1 # 若字母首次出現,初始化計數為 1
# 3. 對統計結果進行排序並印出:
# -item[1]: 依出現次數由大到小排序 (降序)
# item[0] : 若次數相同,則依字母 A-Z 順序排序 (升序)
for i in sorted(total.items(), key=lambda item: (-item[1], item[0])):
print(f"{i[0]} {i[1]}") # 印出字母與其對應的出現次數