继续挑战,越来越有趣了
第30题地址yankeedoodle.html
- 网页标题是
relax you are on 30
,题目内容为The picture is only meant to help you relax
,源码里面有一行隐藏内容:<!– while you look at the csv file –>
很明显了,标题没有什么用,说这题是休息的,题目内容也说图片是帮助休息的,就只有提示里面那句话有用了,也就是下载yankeedoodle.csv了:
import requests
with requests.Session() as sess:
sess.auth = ('repeat', 'switch')
response = sess.get('http://www.pythonchallenge.com/pc/ring/yankeedoodle.csv').text
print(response[:200])
0.82207, 0.91181, 0.88563, 0.78018, 0.64716, 0.34371, 0.28306, 0.21141,
0.12154, 0.29302, 0.22339, 0.22462, 0.27513, 0.34526, 0.67971, 0.78513,
0.96414, 0.72911, 0.99316, 0.72118, 0.90557, 0.98607, 0.
这个csv
里面就是一些逗号分隔的数,看上去没什么规律,但都是0-1之间的数。应该就是一张图片了,只不过像素值归一化了。
yankeedoodle = [f.strip() for f in response.split(',')]
print('count:', len(yankeedoodle))
count: 7367
接下来就是找出图像的大小(质因数分解):
def prime_factor(n: int) -> tuple:
factors = []
while n > 1:
for i in range(2, n // 2 + 1):
if n % i == 0:
factors.append(i)
n //= i
break
else:
factors.append(n)
break
return tuple(factors)
print(prime_factor(len(yankeedoodle)))
(53, 139)
只有一种分解方式:\(7367=53\times139\)。所以图像大小为(53, 139)
:
from PIL import Image
img = Image.new('L', prime_factor(len(yankeedoodle)))
img.putdata([float(p) for p in yankeedoodle], 256)
img
需要翻转一下:
img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_90)
img
写的是\(n=str(x[i])[5]+str(x[i+1])[5]+str(x[i+2])[6]\),所以是三个数值一组,连成一个字符串:
x = yankeedoodle
encoded_str = [str(x[i])[5] + str(x[i + 1])[5] + str(x[i + 2])[6] for i in range(0, len(x) // 3 * 3, 3)]
print(encoded_str[:20])
['083', '111', '044', '032', '121', '111', '117', '032', '102', '111', '117', '110', '100', '032', '116', '104', '101', '032', '104', '105']
这个也像是字节码,翻译一下:
decoded_str = bytes(int(s) for s in encoded_str)
print(decoded_str.decode()[:200])
So, you found the hidden message.
There is lots of room here for a long message, but we only need very little space to say "look at grandpa", so the rest is just garbage.
VTZ.l'tf*Om@I"p]#R`cWEBZ40o
所以,我们切换地址到grandpa.html,来到了下一题。