Python挑战的解决方案(1-10)

Python挑战(Python Challenge) 提供了一系列有趣的谜题,需要你用Python编程解决。本文是为了记录作者一步一步地实现这些谜题的解决。一共有33个等级的挑战,笔者会一点点地实现并记录下来。欢迎喜欢Python的读者可以把你认为更好,更有趣的解决方案贴在留言中,供Python爱好者交流学习。

Level0:


这是让你算2的38次方,如果你熟悉Python的数学计算的话,这道题很简单。答案如下:

print 2 ** 38
274877906944
学习笔记:

这道题的目的是学习基础的Python编程,刚开始学习Python的朋友可以参考这个Python基础学习。


Level1


这道题是解密码,你需要从图片中理解密码规律,然后编程解开密码。从图中可以推断出所包含的密码规律为,将字母变为它字母序后的第2位。

abcdefghijklmnopqrstuvwxyz
cdefghijklmnopqrstuvwxyzab

解这道题有很多的方法,最简单的是利用Python的string模块。笔者准备提供两种解决方案。第一种是最简单利用string模块,第二种是为了学习巩固Python的循环和分支。

密码原文为

origin = "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."

第一种方法:

code = string.maketrans("abcdefghijklmnopqrstuvwxyz", "cdefghijklmnopqrstuvwxyzab")
translated = origin.translate(code)
print translated
i hope you didnt translate it by hand. thats what computers are for. doing it in by hand is inefficient and that's why this text is so long. using string.maketrans() is recommended. now apply on the url.
最后你只要将密码表应用到相应的地址就好了

"map".translate(code)
'ocr'

第二种方法:

我用了一种最傻瓜的方法,试图包含很多的Python内容。这样可以帮助初学者,在这个小小的应用中,学习一些常用的Python函数。

ascii = string.ascii_lowercase
code = "cdefghijklmnopqrstuvwxyzab"
code_map = {}
for i in range(26):
	code_map[ascii[i]] = code[i]
def translate(origin, code_map):
	t = ""
	for c in origin:
		if c in string.ascii_lowercase:
			t += code_map.get(c)
		else:
			t += c
	return t
translate(origin, code_map)
translate("map", code_map)

学习笔记

Python的文本操作是非常方便的,这是它的一大优势。我想,本题是为了让你了解一些它强大的文本操作。学习更多的string相关的函数,请参考Python string module.


Level2


这道题其实是为了让你过滤掉一些乱码。我认为它是为了让你进一步学习Python强大的文本处理。在这道题,你可以学习最基本的正则表达式的使用。

这道题的数据其实是隐藏在它的HTML源码中,所以你可以使用Python的urllib2去获取它的源码。这里笔者提供一种最简单的解决方案。

import urllib2
import re

html = urllib2.urlopen("http://www.pythonchallenge.com/pc/def/ocr.html").read()
b = html.find("\n%%")
html = html[b:]
print "".join(re.findall("[a-zA-Z]", html))
'equality'
学习笔记

用到了urllib或urllib2, 和正则表达式。这方面得内容网上很多,大家可以参考Python For Beginners和Python Tutorial。


Level3

这道题还是关于正则表达式的应用,数据还是隐藏在HTML源码中,你需要将源数据抓取出来,然后应用正则表达式找到你所需要的信息。

这道题的意思是让你找到所有的小写字母,必须是被前后各3个大写字母包裹着,大写字母的数量必须是3个。这其实是一个简单的正则表达式应用。

import urllib2
import re

html = urllib2.urlopen("http://www.pythonchallenge.com/pc/def/equality.html").read()
b = html.find("\n<!--")
html = html[b:]
print "".join(re.findall("[^A-Z]+[A-Z]{3}([a-z])[A-Z]{3}[^A-Z]+", html))
linkedlist


Level4

这道题是让你用Python编程来跟网页交流,当你点击了图片之后,网址就会转向:
http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=12345

同时,页面会显示:

and the next nothing is 44827

不难发现,我可以用页面中显示的数字来替换当前URL中的nothing=12345的数字。然而我替换了数字之后,它指向了另一URL及对应的页面。 同样,页面中有一个新的数字,45439。可想而知,如果我继续手动地替换数字,它又会指向另一个网址及对应的数字,还不知道要手工换多少次。看来只能用Python来自动完成替换URL中数字的工作了。

url_string = "http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=%s"
	nothing = "123456"
	count = 1
	while True:
		try:
			response = urllib2.urlopen(url_string % nothing).read()
			print str(count) + "  " +response
			count += 1
			nothing = re.search(r'(\d+)', response).group(1)
		except:
			break

但是马上我发现了个问题:

There maybe misleading numbers in the text. One example is 82683. Look only for the next nothing and the next nothing is 63579

居然有干扰信息的,正则表达式需要修改下。

nothing = re.search(r'and the next nothing is (\d+)', response).group(1)

它还会说你需要把这个数字除以2。那就除呗,修改下初始值,继续跑程序就能得到你想要的结果peak.


level5

这道题,看了半天源码,只知道数据是存在这里的。可是就是不知道该怎么处理数据,网上搜了下才知道原来是要用pickle。学习了一下他的概念大概知道要干嘛了。

f = urllib2.urlopen("http://www.pythonchallenge.com/pc/def/banner.p")
raw = pickle.load(f)
f.close()
print '\n'.join([''.join([letter*number for letter,number in row]) for row in raw])

运行之后,得到结果是channel.


Level6

看到这个题,第一感觉是“会不会是让我捐款”。打开源码之后,看到注释之后知道不是。可是还是没有线索,就是首行的zip有点奇怪。马上想到,会不会zip指的是后缀,要下载一个zip包。我就把channel.html改成了channel.zip,果然,下载了一个zip文件,里面有很多以数字命名的文件,感觉有点像第4题。读一下Readme,果然又是一个类似的问题,让你根据每个文件里的线索找到目标文件里面的信息。很自然地,我根据第四题的思路,有了以下代码

number = "90052"
path = "channel/%s.txt"
pattern = "Next nothing is (\d+)"
while True:
	try:
		f = open(path % number)
		text = f.read()
		f.close()
		print text
		number = re.search(pattern,text).group(1)
	except:
		break
可是最后的结果是“collect the comments"。让我收集注释,可是哪儿有注释啊。上网查了下,终于知道原来注释是隐藏在zip文件里,我需要用到一个python的模块叫做 zipfile,我需要抓取每个文件在zip里的注释。修改下代码,加入抓取注释的部分,不过这次,我得用zipfile来打开文件。

number = "90052"
path = "%s.txt"
pattern = "Next nothing is (\d+)"
zf = zipfile.ZipFile('channel.zip')
comment = ''
while True:
	try:
		text = zf.read(path % number)
		print text
		comment += zf.getinfo(path % number).comment
		number = re.search(pattern,text).group(1)
	except:
		break
zf.close()
print comment
结果是hockey。可是当我把网址改成hockey.html的时候,它让我仔细查看字母,我重新查看了字母, 原来是oxygen。






你可能感兴趣的:(Python挑战的解决方案(1-10))