Skip to content

Commit e41e867

Browse files
committed
Add solution to mission 31
1 parent 584b4c1 commit e41e867

File tree

2 files changed

+80
-2
lines changed

2 files changed

+80
-2
lines changed

31-grandpa.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
# This file is part of Python Challenge Solutions
5+
# https://github.com/scorphus/PythonChallengeSolutions
6+
7+
# Licensed under the BSD-3-Clause license:
8+
# https://opensource.org/licenses/BSD-3-Clause
9+
# Copyright (c) 2018-2020, Pablo S. Blum de Aguiar <scorphus@gmail.com>
10+
11+
# http://www.pythonchallenge.com/pc/rock/grandpa.html
12+
13+
from auth import get_last_attr
14+
from auth import get_last_src_url
15+
from auth import read_url
16+
from cache import autocached
17+
from etc import factorize
18+
from etc import image_to_text
19+
from io import BytesIO
20+
from PIL import Image
21+
22+
23+
def convert_to_number(s):
24+
try:
25+
return int(s)
26+
except ValueError:
27+
return float(s)
28+
29+
30+
def read_riddle_numbers(url):
31+
for el in ["left", "top", "width", "height", "iterations"]:
32+
yield convert_to_number(get_last_attr(url, el))
33+
34+
35+
def read_riddle_data(url):
36+
img_url = get_last_src_url(url)
37+
return (Image.open(BytesIO(read_url(img_url))), *read_riddle_numbers(url))
38+
39+
40+
@autocached
41+
def mandelbrot_set(left, top, width, height, image_size, max_iter):
42+
"""Generates an upside-down section of the Mandelbrot Set as pixel data for
43+
an image of size `image_size` doing `max_iter` maximum iterations"""
44+
dx = width / image_size[0]
45+
dy = height / image_size[1]
46+
data = []
47+
for y in range(image_size[1] - 1, -1, -1): # is mission's image upside down??? 🤷
48+
for x in range(image_size[0]):
49+
c0 = complex(left + x * dx, top + y * dy)
50+
c, i = complex(), 0
51+
while True:
52+
c = c * c + c0
53+
if abs(c) > 2 or i == max_iter - 1:
54+
break
55+
i += 1
56+
data.append(i)
57+
return data
58+
59+
60+
def diff_image(data_a, data_b):
61+
"""Generates a 1-bit black and white image by comparing `data_a` and `data_b`"""
62+
diff = [int(a > b) for a, b in zip(data_a, data_b) if a != b]
63+
img = Image.new("1", factorize(len(diff)))
64+
img.putdata(diff)
65+
return img
66+
67+
68+
url = "http://www.pythonchallenge.com/pc/rock/grandpa.html"
69+
img, left, top, width, height, iterations = read_riddle_data(url)
70+
mandelbrot = mandelbrot_set(left, top, width, height, img.size, iterations)
71+
diff_img = diff_image(img.getdata(), mandelbrot)
72+
print(image_to_text(diff_img, skip=1, white="▓▓"))

auth.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"http://www.pythonchallenge.com/pc/return": b"huge:file",
2020
"http://www.pythonchallenge.com/pc/hex": b"butter:fly",
2121
"http://www.pythonchallenge.com/pc/ring": b"repeat:switch",
22+
"http://www.pythonchallenge.com/pc/rock": b"kohsamui:thailand",
2223
}
2324

2425

@@ -49,10 +50,15 @@ def read_riddle(url, headers={}):
4950
return read_url(url, headers).decode()
5051

5152

53+
def get_last_attr(url, attr):
54+
"""Extracts the URL of the last `attr` attribute in the mission at `url`"""
55+
return read_riddle(url).split(f'{attr}="')[-1].split('"')[0]
56+
57+
5258
def get_last_attr_url(url, attr):
5359
"""Extracts the URL of the last `attr` attribute in the mission at `url`"""
54-
img_src = read_riddle(url).split(f'{attr}="')[-1].split('"')[0]
55-
return "{}/{}".format(url.rsplit("/", 1)[0], img_src)
60+
attr = get_last_attr(url, attr)
61+
return "{}/{}".format(url.rsplit("/", 1)[0], attr)
5662

5763

5864
def get_last_src_url(url):

0 commit comments

Comments
 (0)