StevenPZChan
StevenPZChan
3 min read

Categories

Tags

继续挑战,开始算法的世界了


第24题地址ambiguity.html

  • maze.png
  • 网页标题是from top to bottom,题目内容为空,源码里面也没有隐藏内容

图片放大看密密麻麻的,像一座迷宫,名字maze.png告诉我们它就是一座迷宫,而标题说从上到下,仔细一看,右上角和左下角正好都有一个缺口,应该就是走迷宫了。


在走迷宫之前,我们再仔细观察这幅迷宫。
迷宫的墙是用白色(255, 255, 255)标注出来的,其他的是通路,一般是黑色(0, 0, 0),但零星会分布着一些红点,R值还不尽相同。
所以我的猜想是在走迷宫的同时,将这些红点的内容提取出来组合成一段字符,可能是什么信息,也有可能是什么格式的文件。

from io import BytesIO
import requests
from PIL import Image

with requests.Session() as sess:
    sess.auth = ('butter', 'fly')
    response = sess.get('http://www.pythonchallenge.com/pc/hex/maze.png').content
    img = Image.open(BytesIO(response))
img

png

估计迷宫走法只有一个,所以使用DFS深度优先搜索的方法来比较快。

from collections import deque
import numpy as np

width, height = img.size
img_data = img.load()
visit = np.zeros((width, height))
neighbors = ((-1, 0), (0, -1), (0, 1), (1, 0))
start, end = (width - 2, 0), (1, height - 1)
path = deque()

path.append(start)
visit[start[0], start[1]] = True
while path and path[-1] != end:
    cx, cy = path[-1]
    for dx, dy in neighbors:
        x, y = cx + dx, cy + dy
        if all((0 <= x < width, 0 <= y < height, not visit[x, y], img_data[x, y][2] == 0)):
            path.append((x, y))
            visit[x, y] = True
            break
    else:
        path.pop()
print(len(path))
44623

标注路线并取数据:

maze = bytearray()
for x, y in path:
    R, _, *others = img_data[x, y]
    img_data[x, y] = (R, 255, *others)
    maze.append(R)
print(maze[:20])
img
bytearray(b'\x00P\x00K\x00\x03\x00\x04\x00\x14\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00')

png

是一个以PK\x03\x04开头的PKZip文件:

from io import BytesIO
from zipfile import ZipFile

with ZipFile(BytesIO(maze[1::2]), 'r') as f:
    print(f.filelist)
[<ZipInfo filename='maze.jpg' compress_type=deflate filemode='-rw-r--r--' file_size=19616 compress_size=18407>, <ZipInfo filename='mybroken.zip' filemode='-rw-r--r--' file_size=2701>]

里面是一张名为maze.jpg的图片和一个名为mybroken.zip的压缩包,把图片打开看看:

from io import BytesIO
from zipfile import ZipFile
from PIL import Image

with ZipFile(BytesIO(maze[1::2]), 'r') as f:
    with f.open('maze.jpg', 'r') as f_jpg:
        maze_img = Image.open(f_jpg).copy()
maze_img

png

好了,地址改为lake.html,来到了下一题。
至于那个mybroken.zip,先放放吧。

总结:这一题就是走迷宫,考验经典算法的功底,还有一些观察力。

本题代码地址24_ambiguity.ipynb