diff --git a/.gitignore b/.gitignore index 5ba74c7624a29abd67a2feb4e2a6a9deb1e95549..add018ff1c7206e952e5384e8968c2cbd2dcf008 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ __pycache__ *.pyc *.zip -*.out \ No newline at end of file +*.out +*.pdf \ No newline at end of file diff --git "a/data/1.python\345\210\235\351\230\266/1.\351\242\204\345\244\207\347\237\245\350\257\206/2.\347\250\213\345\272\217\350\256\276\350\256\241\346\200\235\346\203\263/class.json" "b/data/1.python\345\210\235\351\230\266/1.\351\242\204\345\244\207\347\237\245\350\257\206/2.\347\250\213\345\272\217\350\256\276\350\256\241\346\200\235\346\203\263/class.json" index 4511f86ab8c35dda213959de0679a41847586ea3..1b60c9625321a4e4d3aa161f56ba5fc5189faedd 100644 --- "a/data/1.python\345\210\235\351\230\266/1.\351\242\204\345\244\207\347\237\245\350\257\206/2.\347\250\213\345\272\217\350\256\276\350\256\241\346\200\235\346\203\263/class.json" +++ "b/data/1.python\345\210\235\351\230\266/1.\351\242\204\345\244\207\347\237\245\350\257\206/2.\347\250\213\345\272\217\350\256\276\350\256\241\346\200\235\346\203\263/class.json" @@ -1,14 +1,5 @@ { - "one_line": { - "print(\"\".join(result))": [ - "print(\",\".join(result))", - "print(result)" - ], - "result.append(token[\"key\"])": [ - "result.append(token)" - ] - }, - "source": "class.py", + "source": "class.md", "depends": [], "exercise_id": 26, "type": "code_options" diff --git "a/data/1.python\345\210\235\351\230\266/1.\351\242\204\345\244\207\347\237\245\350\257\206/2.\347\250\213\345\272\217\350\256\276\350\256\241\346\200\235\346\203\263/class.md" "b/data/1.python\345\210\235\351\230\266/1.\351\242\204\345\244\207\347\237\245\350\257\206/2.\347\250\213\345\272\217\350\256\276\350\256\241\346\200\235\346\203\263/class.md" new file mode 100644 index 0000000000000000000000000000000000000000..367cffeeb1d19e0a4f7da181bb1dc375465e3083 --- /dev/null +++ "b/data/1.python\345\210\235\351\230\266/1.\351\242\204\345\244\207\347\237\245\350\257\206/2.\347\250\213\345\272\217\350\256\276\350\256\241\346\200\235\346\203\263/class.md" @@ -0,0 +1,363 @@ +# Alice、Bob 和他们的朋友们 + +密码学家 Rivest、Shamir、Adleman 于1977年4月撰写了一篇论文《数字签名与公钥密码学》(On Digital Signatures and Public-Key Cryptosystems),并投稿至了一个期刊上,不过很遗憾这篇论文被拒稿了。随后他们修改了论文,并将论文重新命名为《一种实现数字签名和公钥密码系统的方法》(A Method of Obtaining Digital Signatures and Public-Key Cryptosystems),最终于1978年2月成功发表于顶级期刊《ACM通信》(Communications of the ACM)。在这篇论文中,三位密码学家嫌弃使用A、B两个字母代表角色太无聊,就用Alice和Bob来代替A和B。 + +在随后的几十年里密码学界又新增了很多著名人物。布鲁斯·施奈尔所著的《应用密码学》(Applied Cryptography)里详细列举了这些人物: + +```python +crypto_roles = [ + '爱丽丝(Alice)是信息发送者。', + '与鲍伯(Bob)是信息接受者。通例上,爱丽丝希望把一条消息发送给鲍伯。', + '卡罗尔或查利(Carol或Charlie)是通信中的第三位参加者。', + '戴夫(Dave)是通信中的第四位参加者。', + '伊夫(Eve)是一位偷听者(eavesdropper),但行为通常是被动的。她拥有偷听的技术,但不会中途篡改发送的消息。在量子密码学中,伊夫也可以指环境(environment)。', + '艾萨克(Isaac)是互联网服务提供者 (ISP)。', + '伊凡(Ivan)是发行人,使用于商业密码学中。', + '贾斯汀(Justin)是司法(justice)机关。', + '马洛里(Mallory)是一位恶意攻击者(malicious attacker)。与伊夫不同的是,马洛里会篡改发送的消息。对付马洛里所需的信息安全技术比对伊夫的高出很多。有时亦会叫作马文(Marvin)或马利特(Mallet)。', + '马提尔达(Matilda)是一位商人(merchant),用于电子商务。', + '奥斯卡(Oscar)是敌人,通常与马洛里一样。', + '帕特(Pat)或佩吉(Peggy)是证明者(prover),维克托(Victor)是验证者(verifier)。两人会证实一项事件是否有实际进行,多使用于零知识证明。', + '普特(Plod或Officer Plod)是执法官员。名称来自伊妮·布来敦所著的儿童文学《诺弟》(Noddy)中的角色“普特先生”。', + '史蒂夫(Steve)代指隐写术(Steganography)。', + '特伦特(Trent)是一位可信赖的仲裁人(trusted arbitrator),中立的第三者,根据存在的协议而判断。', + '特鲁迪(Trudy)是侵入者(intruder),等同马洛里。', + '沃特(Walter)是看守人(warden)。根据已存在的协议而保护爱丽丝和鲍伯。', + '佐伊(Zoe)通常是一个安全协议中的最后参与者。' +] +``` + +Python 是一门多范式编程语言,其中包括面向对象编程。 + +首先,我们用 `Python 类(class)` 定义一个密码城邦人物类型: + +```python +class CryptographyPeople: + def __init__(self, name_cn, name_en, role, desc): + self.name_cn = name_cn + self.name_en = name_en + self.role = role + self.desc = desc +``` + +其次,我们添加一个简易的密码城邦人物解析器,它的作用是将类似`'马提尔达(Matilda)是一位商人(merchant),用于电子商务。',`这样的`人物剧本`解析成`CryptographyPeople`,创建一个密码城邦人物: + +```python +class SimpleCryptographyPeopleParser: + def __init__(self, text) -> None: + self.text = text + + def parse(self, desc): + # 解析名字部分 + name_cn, name_en, rest = self.parse_name(desc) + + # 解析角色部分 + role, rest = self.parse_role(rest) + + # 解析描述不符 + desc = self.parse_desc(rest) + + # 创建密码城邦人物 + people = CryptographyPeople(name_cn, name_en, role, desc) + + return people + + def parse_name(self, text): + # 解析名字部分 + index = text.find('是') + name, rest = text[0:index], text[index+1:] + + # 解析中英文名字 + start = name.find('(') + end = name.find(')') + name_cn = name[0:start] + name_en = name[start+1:end] + + return name_cn.strip(), name_en.strip(), rest + + def parse_role(self, text): + index1 = text.find('。') + index2 = text.find(',') + + index = 0 + if index1 > 0 and index2 > 0: + index = min(index1, index2) + else: + index = max(index1, index2) + + role, rest = text[0:index], text[index+1:len(text)-1] + + # 去除冗余量词 + counts = ['一名', '一位', '一个'] + for count in counts: + role = role.replace(count, '') + return role.strip(), rest.strip() + + def parse_desc(self, name_cn, name_en, role, rest): + desc = rest + if desc: + # 识别自我主语 + self_list = [name_cn, '他', '她'] + for self_item in self_list: + desc = desc.replace(self_item, '我') + else: + # 补充默认描述 + desc = '很高兴认识你' +``` + +最后,我们希望创建一个密码城邦,它包含 `add` 和 `introduce` 两个方法: + +```python +class CryptographyCity: + def __init__(self): + self.peoples = [] + + def add(self, text): + parser = SimpleCryptographyPeopleParser(text) + people = parser.parse(text) + self.peoples.append(people) + + # TODO(YOU): 请在此实现 introduce 方法 +``` + +最终,我们可以构建起密码城邦,并让市民们全部自报家门: + +```python +if __name__ == '__main__': + crypto_roles = ... + + city = CryptographyCity() + for crypto_role in crypto_roles: + city.add(crypto_role) + city.introduce() +``` + +密码城邦人物的自我介绍如下: + +```bash +爱丽丝(Alice): 密码学家说我是一位信息发送者,很高兴认识你。 +鲍伯(Bob): 密码学家说我是一位信息接受者,通例上,爱丽丝希望把一条消息发送给我。 +卡罗尔或查利(Carol或Charlie): 密码学家说我是一位通信中的第三位参加者,很高兴认识你。 +戴夫(Dave): 密码学家说我是一位通信中的第四位参加者,很高兴认识你。 +伊夫(Eve): 密码学家说我是一位偷听者(eavesdropper),但行为通常是被动的。我拥有偷听的技术,但不会中途篡改发送的消息。在量子密码学中,我也可以指环境(environment)。 +艾萨克(Isaac): 密码学家说我是一位互联网服务提供者 (ISP),很高兴认识你。 +伊凡(Ivan): 密码学家说我是一位发行人,使用于商业密码学中。 +贾斯汀(Justin): 密码学家说我是一位司法(justice)机关,很高兴认识你。 +马洛里(Mallory): 密码学家说我是一位恶意攻击者(malicious attacker),与伊夫不同的是,我会篡改发送的消息。对付我所需的信息安全技术比对伊夫的高出很多。有时亦会叫作马文(Marvin)或马利特(Mallet)。 +马提尔达(Matilda): 密码学家说我是一位商人(merchant),用于电子商务。 +奥斯卡(Oscar): 密码学家说我是一位敌人,通常与马洛里一样。 +帕特(Pat): 密码学家说我是一位证明者(prover),维克托(Victor)是验证者(verifier)。两人会证实一项事件是否有实际进行,多使用于零知识证明。 +普特(Plod或Officer Plod): 密码学家说我是一位执法官员,名称来自伊妮·布来敦所著的儿童文学《诺弟》(Noddy)中的角色“我先生”。 +史蒂夫(Steve): 密码学家说我是一位隐写术(Steganography),很高兴认识你。 +特伦特(Trent): 密码学家说我是一位可信赖的仲裁人(trusted arbitrator),中立的第三者,根据存在的协议而判断。 +特鲁迪(Trudy): 密码学家说我是一位侵入者(intruder),等同马洛里。 +沃特(Walter): 密码学家说我是一位看守人(warden),根据已存在的协议而保护爱丽丝和鲍伯。 +佐伊(Zoe): 密码学家说我是一位安全协议中的最后参与者,很高兴认识你。 +``` + +请找出以下对类`CryptographyCity`的方法`introduce`的实现中,不正确的选项。 + +## template + +```python +class CryptographyPeople: + def __init__(self, name_cn, name_en, role, desc): + self.name_cn = name_cn + self.name_en = name_en + self.role = role + self.desc = desc + + +class SimpleCryptographyPeopleParser: + def __init__(self, text) -> None: + self.text = text + + def parse(self, desc): + # 解析名字部分 + name_cn, name_en, rest = self.parse_name(desc) + + # 解析角色部分 + role, rest = self.parse_role(name_cn, name_en, rest) + + # 解析描述不符 + desc = self.parse_desc(name_cn, name_en, role, rest) + + # 创建密码城邦人物 + people = CryptographyPeople(name_cn, name_en, role, desc) + + return people + + def parse_name(self, text): + # 解析名字部分 + index = text.find('是') + name, rest = text[0:index], text[index+1:] + + # 解析中英文名字 + start = name.find('(') + end = name.find(')') + name_cn = name[0:start] + name_en = name[start+1:end] + + return name_cn.strip(), name_en.strip(), rest + + def parse_role(self, name_cn, name_en, text): + index1 = text.find('。') + index2 = text.find(',') + + index = 0 + if index1 > 0 and index2 > 0: + index = min(index1, index2) + else: + index = max(index1, index2) + + role, rest = text[0:index], text[index+1:len(text)-1] + + # 去除冗余量词 + counts = ['一名', '一位', '一个'] + for count in counts: + role = role.replace(count, '') + return role.strip(), rest.strip() + + def parse_desc(self, name_cn, name_en, role, rest): + desc = rest + if desc: + # 识别自我主语 + self_list = [name_cn, '他', '她'] + for self_item in self_list: + desc = desc.replace(self_item, '我') + else: + # 补充默认描述 + desc = '很高兴认识你' + return desc + + +class CryptographyCity: + def __init__(self): + self.peoples = [] + + def add(self, text): + parser = SimpleCryptographyPeopleParser(text) + people = parser.parse(text) + self.peoples.append(people) + + def introduce(self): + for people in self.peoples: + info = f'{people.name_cn}({people.name_en}): 密码学家说我是一位{people.role},{people.desc}。' + print(info) + + +if __name__ == '__main__': + crypto_roles = [ + '爱丽丝(Alice)是信息发送者。', + '鲍伯(Bob)是信息接受者。通例上,爱丽丝希望把一条消息发送给鲍伯。', + '卡罗尔或查利(Carol或Charlie)是通信中的第三位参加者。', + '戴夫(Dave)是通信中的第四位参加者。', + '伊夫(Eve)是一位偷听者(eavesdropper),但行为通常是被动的。她拥有偷听的技术,但不会中途篡改发送的消息。在量子密码学中,伊夫也可以指环境(environment)。', + '艾萨克(Isaac)是互联网服务提供者 (ISP)。', + '伊凡(Ivan)是发行人,使用于商业密码学中。', + '贾斯汀(Justin)是司法(justice)机关。', + '马洛里(Mallory)是一位恶意攻击者(malicious attacker)。与伊夫不同的是,马洛里会篡改发送的消息。对付马洛里所需的信息安全技术比对伊夫的高出很多。有时亦会叫作马文(Marvin)或马利特(Mallet)。', + '马提尔达(Matilda)是一位商人(merchant),用于电子商务。', + '奥斯卡(Oscar)是敌人,通常与马洛里一样。', + '帕特(Pat)或佩吉(Peggy)是证明者(prover),维克托(Victor)是验证者(verifier)。两人会证实一项事件是否有实际进行,多使用于零知识证明。', + '普特(Plod或Officer Plod)是执法官员。名称来自伊妮·布来敦所著的儿童文学《诺弟》(Noddy)中的角色“普特先生”。', + '史蒂夫(Steve)是隐写术(Steganography)。', + '特伦特(Trent)是一位可信赖的仲裁人(trusted arbitrator),中立的第三者,根据存在的协议而判断。', + '特鲁迪(Trudy)是侵入者(intruder),等同马洛里。', + '沃特(Walter)是看守人(warden),根据已存在的协议而保护爱丽丝和鲍伯。', + '佐伊(Zoe)通常是一个安全协议中的最后参与者。' + ] + + city = CryptographyCity() + for crypto_role in crypto_roles: + city.add(crypto_role) + city.introduce() +``` + +## 答案 + +```python +class CryptographyCity: + def __init__(self): + self.peoples = [] + + def add(self, text): + parser = SimpleCryptographyPeopleParser(text) + people = parser.parse(text) + self.peoples.append(people) + + def introduce(): + for people in peoples: + say(people) + + def say(people): + info = f'{people.name_cn}({people.name_en}): 密码学家说我是一位{people.role},{people.desc}。' + print(info) +``` + +## 选项 + +### for 语句实现 + +```python +class CryptographyCity: + def __init__(self): + self.peoples = [] + + def add(self, text): + parser = SimpleCryptographyPeopleParser(text) + people = parser.parse(text) + self.peoples.append(people) + + def introduce(self): + for people in self.peoples: + self.say(people) + + def say(self, people): + info = f'{people.name_cn}({people.name_en}): 密码学家说我是一位{people.role},{people.desc}。' + print(info) +``` + +### while语句实现 + +```python +class CryptographyCity: + def __init__(self): + self.peoples = [] + + def add(self, text): + parser = SimpleCryptographyPeopleParser(text) + people = parser.parse(text) + self.peoples.append(people) + + def introduce(self): + i=0 + while i None: - super().__init__() - self.tokens = [] - def add_action_token(self, token): - self.tokens.append({"key": token}) +class CryptographyPeople: + def __init__(self, name_cn, name_en, role, desc): + self.name_cn = name_cn + self.name_en = name_en + self.role = role + self.desc = desc - def play(self): - result = [] - for token in self.tokens: - result.append(token["key"]) - print("".join(result)) +class SimpleCryptographyPeopleParser: + def __init__(self, text) -> None: + self.text = text -def main(): - m = Monkey() - m.add_action_token("猴子在") - m.add_action_token("苹果树下") - m.add_action_token("打架") - m.play() + def parse(self, desc): + # 解析名字部分 + name_cn, name_en, rest = self.parse_name(desc) + + # 解析角色部分 + role, rest = self.parse_role(name_cn, name_en, rest) + + # 解析描述不符 + desc = self.parse_desc(name_cn, name_en, role, rest) + + # 创建密码城邦人物 + people = CryptographyPeople(name_cn, name_en, role, desc) + + return people + + def parse_name(self, text): + # 解析名字部分 + index = text.find('是') + name, rest = text[0:index], text[index+1:] + + # 解析中英文名字 + start = name.find('(') + end = name.find(')') + name_cn = name[0:start] + name_en = name[start+1:end] + + return name_cn.strip(), name_en.strip(), rest + + def parse_role(self, name_cn, name_en, text): + index1 = text.find('。') + index2 = text.find(',') + + index = 0 + if index1 > 0 and index2 > 0: + index = min(index1, index2) + else: + index = max(index1, index2) + + role, rest = text[0:index], text[index+1:len(text)-1] + + # 去除冗余量词 + counts = ['一名', '一位', '一个'] + for count in counts: + role = role.replace(count, '') + return role.strip(), rest.strip() + + def parse_desc(self, name_cn, name_en, role, rest): + desc = rest + if desc: + # 识别自我主语 + self_list = [name_cn, '他', '她'] + for self_item in self_list: + desc = desc.replace(self_item, '我') + else: + # 补充默认描述 + desc = '很高兴认识你' + return desc + + +class CryptographyCity: + def __init__(self): + self.peoples = [] + + def add(self, text): + parser = SimpleCryptographyPeopleParser(text) + people = parser.parse(text) + self.peoples.append(people) + + def introduce(self): + for people in self.peoples: + info = f'{people.name_cn}({people.name_en}): 密码学家说我是一位{people.role},{people.desc}。' + print(info) if __name__ == '__main__': - main() + crypto_roles = [ + '爱丽丝(Alice)是信息发送者。', + '鲍伯(Bob)是信息接受者。通例上,爱丽丝希望把一条消息发送给鲍伯。', + '卡罗尔或查利(Carol或Charlie)是通信中的第三位参加者。', + '戴夫(Dave)是通信中的第四位参加者。', + '伊夫(Eve)是一位偷听者(eavesdropper),但行为通常是被动的。她拥有偷听的技术,但不会中途篡改发送的消息。在量子密码学中,伊夫也可以指环境(environment)。', + '艾萨克(Isaac)是互联网服务提供者 (ISP)。', + '伊凡(Ivan)是发行人,使用于商业密码学中。', + '贾斯汀(Justin)是司法(justice)机关。', + '马洛里(Mallory)是一位恶意攻击者(malicious attacker)。与伊夫不同的是,马洛里会篡改发送的消息。对付马洛里所需的信息安全技术比对伊夫的高出很多。有时亦会叫作马文(Marvin)或马利特(Mallet)。', + '马提尔达(Matilda)是一位商人(merchant),用于电子商务。', + '奥斯卡(Oscar)是敌人,通常与马洛里一样。', + '帕特(Pat)或佩吉(Peggy)是证明者(prover),维克托(Victor)是验证者(verifier)。两人会证实一项事件是否有实际进行,多使用于零知识证明。', + '普特(Plod或Officer Plod)是执法官员。名称来自伊妮·布来敦所著的儿童文学《诺弟》(Noddy)中的角色“普特先生”。', + '史蒂夫(Steve)是隐写术(Steganography)。', + '特伦特(Trent)是一位可信赖的仲裁人(trusted arbitrator),中立的第三者,根据存在的协议而判断。', + '特鲁迪(Trudy)是侵入者(intruder),等同马洛里。', + '沃特(Walter)是看守人(warden),根据已存在的协议而保护爱丽丝和鲍伯。', + '佐伊(Zoe)通常是一个安全协议中的最后参与者。' + ] + + city = CryptographyCity() + for crypto_role in crypto_roles: + city.add(crypto_role) + city.introduce()