PythonChallenge_1
一、实验说明
下述介绍为实验楼默认环境,如果您使用的是定制环境,请修改成您自己的环境介绍。
1. 环境登录
无需密码自动登录,系统用户名shiyanlou,密码shiyanlou
2. 环境介绍
本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌面上的程序:
1. LX终端(LXTerminal): Linux命令行终端,打开后会进入Bash环境,可以使用Linux命令
2. Firefox:浏览器,可以用在需要前端界面的课程里,只需要打开环境里写的HTML/JS页面即可
3. GVim:非常好用的编辑器,最简单的用法可以参考课程Vim编辑器
3. 环境使用
使用GVim编辑器输入实验所需的代码及文件,使用LX终端(LXTerminal)运行所需命令进行操作。
完成实验后可以点击桌面上方的“实验截图”保存并分享实验结果到微博,向好友展示自己的学习进度。实验楼提供后台系统截图,可以真实有效证明您已经完成了实验。
实验记录页面可以在“我的主页”中查看,其中含有每次实验的截图及笔记,以及每次实验的有效学习时间(指的是在实验桌面内操作的时间,如果没有操作,系统会记录为发呆时间)。这些都是您学习的真实性证明。
二、课程介绍
本次`PythonChallenge`系列一共有11个项目,持续更新中,每个项目课程里面会详细讲解3个`pythonchallenge`通关题目以及不同解决方案,课后习题里面布置一个任务题,该题目会在下一个项目中被揭开面纱。
本系列题目属于在线闯关题,由于实验楼暂时不提供访问外网,因此请各位验证答案的时候烦劳点击自己的浏览器访问网页以验证答案。
所有题目和参考的解决方案版权归PythonChallenge官网,课程编写属于实验楼原创,欢迎在问答区积极提问,小编会积极解答,也欢迎在评论区吐槽~
三、实验内容
3.1 热身
问题:尝试根据以上图片,改变`URL`地址:http://www.pythonchallenge.com/pc/def/0.html。
**小编脑洞:**映入眼帘的是三个数字,长得像2的38次方,难道结果就是这个?试试在Python交互式环境算出结果吧~
麻利解决,看看是不是`274877906944`?(改变`URL`地址中的最后一个子链接`0`即可。)
好轻松、好神奇有木有?进入下一个http://www.pythonchallenge.com/pc/def/map.html。额,果然是热身运动,是不是太低估你们的智商了?不要紧,咱们接着玩~
### 3.2 如何转换?
问题:大家注意咯,请考虑以下字符串:
`g fmnc wms bgblr rpylqjyrc gr zw fylb. rfyrq ufyr amknsrcpq ypc dmp. bmgle gr gl zw fylb gq glcddgagclr ylb rfyr‘q ufw rfgq rcvr gq qm jmle. sqgle qrpgle.kyicrpylq() gq pcamkkclbcb. lmu ynnjw ml rfc spj.`
**小编脑洞:**`K->M`、`0->Q`、`E->G`这三个转换都是中间隔了一个字符,分别是`L`、`P`、`F`;难道说以上乱七八糟字符串转换规则就是每个原字符的`ASCII码`加2?
首先,通过剪切板将以上字符加载到实验楼环境下的文本test_1.py中:
1 text = """g fmnc wms bgblr rpylqjyrc gr zw fylb. rfyrq ufyr amknsrcpq ypc dmp. bmgle gr gl zw fylb gq glcddgagclr ylb rfyr‘q ufw rfgq rcvr gq qm jmle. sqgle qrpgle.kyicrpylq() gq pcamkkclbcb. lmu ynnjw ml rfc spj."""
接下来,如何将字母转换为`ASCII码`?`Python`中提供函数`ord()`将字母转换成`ASCII码`,提供函数`chr()`将相对应的`ASCII码`转化为字母,那么问题很简单,只要依次遍历字符串中的字符,并利用以上函数将字母转化即可:
1 o = "" 2 3 for each in text: 4 5 if ord(each) >= ord(‘a‘) and ord(each) <= ord(‘z‘): 6 7 o += chr((ord(each) + 2 - ord(‘a‘)) % 26 + ord(‘a‘)) # 尝试理解该转换公式 8 9 else: 10 11 o += x 12 13 print o
看看输出结果:
由上图给出的答案可知(需要具备四级英语水平,不行就是用在线翻译)将以上方法对`url`链接中的`map`进行转换即可。
**标准答案**
出题人推荐使用函数`string.maketrans()`,那么这个函数是干嘛用的?
在`Python`交互式窗口输入:
1 import string 2 3 help(string.maketrans)
输出函数文档:
一大堆英文,了解以下信息即可(键盘输入`q`即可推出文档):
该函数有两个参数`frm`以及`to`,这两个参数必须具有相同的长度,该函数返回的是一个转换公式`table`。
与该函数相对应的是函数`string.translate`,你可以尝试同上面一样查看函数文档;函数`string.translate`有两个参数分别是字符串`s`以及转换公式`table`,返回的是通过该转换公式转换后的字符串`s`。
这么说理论,你们可能无法明白,直接修改原文件`test_1.py`,添加代码(注意把原来的方法注释掉,或者跟我一样直接把每一种解决方案包装成函数):
1 import string 2 3 4 5 def std_solution(text): 6 7 table = string.maketrans( 8 9 string.ascii_lowercase, 10 11 string.ascii_lowercase[2:] + string.ascii_lowercase[:2]) 12 13 print string.translate(text, table) 14 15 16 17 if __name__ == ‘__main__‘: 18 19 std_solution(text)
仔细看`string.maketrans()`里面的两个参数,其中`string.lowercase`指的是小写的26个英文字母`a-z`,第二个参数是要转换的格式`c-z`+`ab`,也就是将每个字符后移两位的方法,因此直接用定义好的方法`table`,将`text`字符串应用该方法转换即可。
那么答案很明显,将上面的`text`内容替换为网页链接中的`map`字符即可,输出为`ocr`,尝试打开http://www.pythonchallenge.com/pc/def/ocr.html找到下一题的通关口。
3.3 字符识别
问题:识别出字符串,它们可能在书里面,也可能在源码里面
**小编脑洞:**书上是基本看不到什么信息,就算有也是大海捞针,既然说是在源码里面,那么我们通过右键“审查元素”查看一下源代码,于是在这个地方:
的下面找到了一群看起来毫无规律可言的一大堆字符串:
注意,它有提醒:从下面一团乱的字符串中找出稀有的字符。这个就是我们真正要解决的问题!
由于实验楼环境不能访问外网,小编已经把那乱七八糟的字符上传到实验楼环境了,请使用如下命令下载文件:
1 wget http://labfile.oss.aliyuncs.com/courses/408/mess.txt
找出最少的字符,既然是字符,那么就不是普通的符号,直接找出字符试试:
1 import string 2 3 4 5 text = open(‘mess.txt‘).read() # 打开文件读取字符串 6 7 8 9 def my_solution(text): 10 11 """从text中挑选出属于英文字母的字符""" 12 13 14 15 s = filter(lambda x: x in string.letters, text) 16 17 print s 18 19 20 21 if __name__ == ‘__main__‘: 22 23 my_solution(text)
运行结果:
下一关的网址显然是将`equality`代入即可。
对于函数`filter`请同学们积极使用`help`命令查看函数文档,其中`filter`的第一个参数是一个`lambda`函数,第二个参数是字符串序列`text`。
对于`lambda`的用法,请看以下例子:
这里的`lambda`函数,完成同上面普通函数`f(x)`相同的事情。注意这里的简短的语法:在参数列表周围没有括号,而且忽略了`return`关键字(隐含存在,因为整个函数只有一行)。而且,该函数没有函数名称,但是可以将它赋值给一个变量如`g`进行调用。
**标准答案**
出现次数最少等价于出现的频率低于字符出现频率平均值
我们要从一大堆混乱的字符中找出出现次数最少的字符,诀窍是考虑文本`mess.txt`中出现次数低于平均水平的字符,我们唯一掌握的信息就是字符是非频繁的,是与`url`类型兼容的(比如回车符号以及空格符就不再考虑范围内)。
算法如下:
1. 读取文本内容;
2. 定义一个字典,里面存储每个字符以及对应出现的频数;
3. 计算出字符平均稀有情况(所有字符数量/字符数量);
4. 循环输出稀有性低于平均水平的的字符。
1 s = ‘‘.join([line.rstrip() for line in open(‘mess.txt‘)]) 2 3 occ = {} 4 5 6 7 for c in s: 8 9 occ[c] = occ.get(c, 0) + 1 # 相同的字符,字典的值加1 10 11 avgOC = len(s) // len(occ) 12 13 14 15 print ‘‘.join([c for c in s if OCCURRENCES[c] < avgOC])
这里要注意的是,引用字典的值的时候最好用`occ.get(c)`而不是`occ[c]`,否则很容易出现`KeyError`,至于原因,请大家自己思考并利用百度等搜索引擎查询并了解相关知识。
**编者评论:**虽然官方的答案引用了比较高大上的字典,但是“稀有情况”这个评价指标并不是很好,不符合一般人的评价标准,一般人的评价一般是统计意义的,比如出现的频率。
那么就有人比较聪明的抓住“rare”这个单词,也就是字符数量是稀有的,那么假设就是字符出现的次数就是`1`呢?
**“投机取巧”方案**
其实解决方案就是这么丰富,脑洞就是这么大;那么大家有没有想到一种更`pythonic`的方式,关于获取那一堆杂乱的字符串是否可以通过`python`直接获取源代码并选出那一堆字符串直接存储呢?(留给大家作为课外习题)。
四、Task_1
那么,介绍了那么多解决方案的你是否也是跃跃欲试?是不是因为找到这个系列题目的规律呢?那么给你一个机会,解决以下问题:
问题:如上图所示,下一题的答案提示:中间是一个小写字母,两边分别有三个大写字母做保镖!
**小编提示:**通往下一题的单词格式是按照上面问题给出的提示一样,另外字符来源可以参考上面的题目给出的解题思路哦!(我是不是说的太明显了~)另外,不一定用`python`语言解决这个问题,你可以使用你熟悉的语言解决。