# My Python Challenge Solutions

In [1]:
# -- 0 --
# problem : http://www.pythonchallenge.com/pc/def/0.html

In [2]:
2**38

Out[2]:
274877906944
In [3]:
# -- 1 --
# problem : http://www.pythonchallenge.com/pc/def/map.html
# solution : http://www.pythonchallenge.com/pcc/def/ocr.html

In [4]:
input_string = "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."

def decode_string(string):
def decode_char(char):
return chr((((ord(char) + 2) - 97) % 26) + 97) if char.isalpha() else char
return "".join(decode_char(char) for char in string)

decode_string(input_string)

Out[4]:
"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."
In [5]:
decode_string("map")

Out[5]:
'ocr'
In [6]:
# -- 2 --
# problem : http://www.pythonchallenge.com/pc/def/ocr.html
# solution : http://www.pythonchallenge.com/pcc/def/equality.html

In [7]:
import urllib.request
import re

def get_source(url):
with urllib.request.urlopen(url) as response:
return html

def print_source(url):
print(get_source(url).decode())

html = get_source("http://www.pythonchallenge.com/pc/def/ocr.html")

# https://docs.python.org/3.6/howto/regex.html#greedy-versus-non-greedy
# https://docs.python.org/3.6/howto/regex.html#compilation-flags
input_string = re.findall(b"<!--(.*?)-->", html, flags = re.DOTALL)[-1].strip().decode()
"".join(char for char in input_string if char.isalpha())

Out[7]:
'equality'
In [8]:
# -- 3 --
# problem : http://www.pythonchallenge.com/pc/def/equality.html

In [9]:
html = get_source("http://www.pythonchallenge.com/pc/def/equality.html")
input_string = re.findall(b"<!--(.*?)-->", html, flags = re.DOTALL)[-1].strip().decode()
"".join(re.findall(r"[^A-Z]+[A-Z]{3}([a-z]{1})[A-Z]{3}[^A-Z]+", input_string))

Out[9]:
'linkedlist'
In [10]:
# -- 4 --
# solution : http://www.pythonchallenge.com/pcc/def/peak.html

In [11]:
print_source("http://www.pythonchallenge.com/pc/def/linkedlist.php")

<html>
<body>
<!-- urllib may help. DON'T TRY ALL NOTHINGS, since it will never
end. 400 times is more than enough. -->
<center>
<br><br><font color="gold"></center>
Solutions to previous levels: <a href="http://wiki.pythonchallenge.com/"/>Python Challenge wiki</a>.
<br><br>
IRC: irc.freenode.net #pythonchallenge
</body>
</html>


In [12]:
get_source("http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=12345")

Out[12]:
b'and the next nothing is 44827'
In [13]:
nothing = "12345"
while True:
try:
nothing = re.findall(b"and the next nothing is ([0-9]+)", source)[0].decode()
except:
if source == b"Yes. Divide by two and keep going.":
nothing = int(nothing)//2
else:
print(source)
break

b'peak.html'

In [14]:
# -- 5 --
# problem : http://www.pythonchallenge.com/pc/def/peak.html
# solution : http://www.pythonchallenge.com/pcc/def/channel.html

In [15]:
print_source("http://www.pythonchallenge.com/pc/def/peak.html")

<html>
<title>peak hell</title>
<body>
<center>
<img src="peakhell.jpg"/>
<br><font color="#c0c0ff">
pronounce it
<br>
<peakhell src="banner.p"/>
</body>
</html>

<!-- peak hell sounds familiar ? -->


In [16]:
import pickle

banner

Out[16]:
[[(' ', 95)],
[(' ', 14), ('#', 5), (' ', 70), ('#', 5), (' ', 1)],
[(' ', 15), ('#', 4), (' ', 71), ('#', 4), (' ', 1)],
[(' ', 15), ('#', 4), (' ', 71), ('#', 4), (' ', 1)],
[(' ', 15), ('#', 4), (' ', 71), ('#', 4), (' ', 1)],
[(' ', 15), ('#', 4), (' ', 71), ('#', 4), (' ', 1)],
[(' ', 15), ('#', 4), (' ', 71), ('#', 4), (' ', 1)],
[(' ', 15), ('#', 4), (' ', 71), ('#', 4), (' ', 1)],
[(' ', 15), ('#', 4), (' ', 71), ('#', 4), (' ', 1)],
[(' ', 6),
('#', 3),
(' ', 6),
('#', 4),
(' ', 3),
('#', 3),
(' ', 9),
('#', 3),
(' ', 7),
('#', 5),
(' ', 3),
('#', 3),
(' ', 4),
('#', 5),
(' ', 3),
('#', 3),
(' ', 10),
('#', 3),
(' ', 7),
('#', 4),
(' ', 1)],
[(' ', 3),
('#', 3),
(' ', 3),
('#', 2),
(' ', 4),
('#', 4),
(' ', 1),
('#', 7),
(' ', 5),
('#', 2),
(' ', 2),
('#', 3),
(' ', 6),
('#', 4),
(' ', 1),
('#', 7),
(' ', 3),
('#', 4),
(' ', 1),
('#', 7),
(' ', 5),
('#', 3),
(' ', 2),
('#', 3),
(' ', 5),
('#', 4),
(' ', 1)],
[(' ', 2),
('#', 3),
(' ', 5),
('#', 3),
(' ', 2),
('#', 5),
(' ', 4),
('#', 4),
(' ', 3),
('#', 3),
(' ', 3),
('#', 4),
(' ', 4),
('#', 5),
(' ', 4),
('#', 4),
(' ', 2),
('#', 5),
(' ', 4),
('#', 4),
(' ', 3),
('#', 3),
(' ', 5),
('#', 3),
(' ', 3),
('#', 4),
(' ', 1)],
[(' ', 1),
('#', 3),
(' ', 11),
('#', 4),
(' ', 5),
('#', 4),
(' ', 3),
('#', 3),
(' ', 4),
('#', 3),
(' ', 4),
('#', 4),
(' ', 5),
('#', 4),
(' ', 2),
('#', 4),
(' ', 5),
('#', 4),
(' ', 2),
('#', 3),
(' ', 6),
('#', 4),
(' ', 2),
('#', 4),
(' ', 1)],
[(' ', 1),
('#', 3),
(' ', 11),
('#', 4),
(' ', 5),
('#', 4),
(' ', 10),
('#', 3),
(' ', 4),
('#', 4),
(' ', 5),
('#', 4),
(' ', 2),
('#', 4),
(' ', 5),
('#', 4),
(' ', 2),
('#', 3),
(' ', 7),
('#', 3),
(' ', 2),
('#', 4),
(' ', 1)],
[('#', 4),
(' ', 11),
('#', 4),
(' ', 5),
('#', 4),
(' ', 5),
('#', 2),
(' ', 3),
('#', 3),
(' ', 4),
('#', 4),
(' ', 5),
('#', 4),
(' ', 2),
('#', 4),
(' ', 5),
('#', 4),
(' ', 1),
('#', 4),
(' ', 7),
('#', 3),
(' ', 2),
('#', 4),
(' ', 1)],
[('#', 4),
(' ', 11),
('#', 4),
(' ', 5),
('#', 4),
(' ', 3),
('#', 10),
(' ', 4),
('#', 4),
(' ', 5),
('#', 4),
(' ', 2),
('#', 4),
(' ', 5),
('#', 4),
(' ', 1),
('#', 14),
(' ', 2),
('#', 4),
(' ', 1)],
[('#', 4),
(' ', 11),
('#', 4),
(' ', 5),
('#', 4),
(' ', 2),
('#', 3),
(' ', 4),
('#', 4),
(' ', 4),
('#', 4),
(' ', 5),
('#', 4),
(' ', 2),
('#', 4),
(' ', 5),
('#', 4),
(' ', 1),
('#', 4),
(' ', 12),
('#', 4),
(' ', 1)],
[('#', 4),
(' ', 11),
('#', 4),
(' ', 5),
('#', 4),
(' ', 1),
('#', 4),
(' ', 5),
('#', 3),
(' ', 4),
('#', 4),
(' ', 5),
('#', 4),
(' ', 2),
('#', 4),
(' ', 5),
('#', 4),
(' ', 1),
('#', 4),
(' ', 12),
('#', 4),
(' ', 1)],
[(' ', 1),
('#', 3),
(' ', 11),
('#', 4),
(' ', 5),
('#', 4),
(' ', 1),
('#', 4),
(' ', 5),
('#', 3),
(' ', 4),
('#', 4),
(' ', 5),
('#', 4),
(' ', 2),
('#', 4),
(' ', 5),
('#', 4),
(' ', 2),
('#', 3),
(' ', 12),
('#', 4),
(' ', 1)],
[(' ', 2),
('#', 3),
(' ', 6),
('#', 2),
(' ', 2),
('#', 4),
(' ', 5),
('#', 4),
(' ', 2),
('#', 3),
(' ', 4),
('#', 4),
(' ', 4),
('#', 4),
(' ', 5),
('#', 4),
(' ', 2),
('#', 4),
(' ', 5),
('#', 4),
(' ', 3),
('#', 3),
(' ', 6),
('#', 2),
(' ', 3),
('#', 4),
(' ', 1)],
[(' ', 3),
('#', 3),
(' ', 4),
('#', 2),
(' ', 3),
('#', 4),
(' ', 5),
('#', 4),
(' ', 3),
('#', 11),
(' ', 3),
('#', 4),
(' ', 5),
('#', 4),
(' ', 2),
('#', 4),
(' ', 5),
('#', 4),
(' ', 4),
('#', 3),
(' ', 4),
('#', 2),
(' ', 4),
('#', 4),
(' ', 1)],
[(' ', 6),
('#', 3),
(' ', 5),
('#', 6),
(' ', 4),
('#', 5),
(' ', 4),
('#', 2),
(' ', 4),
('#', 4),
(' ', 1),
('#', 6),
(' ', 4),
('#', 11),
(' ', 4),
('#', 5),
(' ', 6),
('#', 3),
(' ', 6),
('#', 6)],
[(' ', 95)]]
In [17]:
def row_string(list_of_tuples):
return "".join(char*num for char, num in list_of_tuples)
print(*map(row_string, banner), sep = "\n")


#####                                                                      #####
####                                                                       ####
####                                                                       ####
####                                                                       ####
####                                                                       ####
####                                                                       ####
####                                                                       ####
####                                                                       ####
###      ####   ###         ###       #####   ###    #####   ###          ###       ####
###   ##    #### #######     ##  ###      #### #######   #### #######     ###  ###     ####
###     ###  #####    ####   ###   ####    #####    ####  #####    ####   ###     ###   ####
###           ####     ####   ###    ###    ####     ####  ####     ####  ###      ####  ####
###           ####     ####          ###    ####     ####  ####     ####  ###       ###  ####
####           ####     ####     ##   ###    ####     ####  ####     #### ####       ###  ####
####           ####     ####   ##########    ####     ####  ####     #### ##############  ####
####           ####     ####  ###    ####    ####     ####  ####     #### ####            ####
####           ####     #### ####     ###    ####     ####  ####     #### ####            ####
###           ####     #### ####     ###    ####     ####  ####     ####  ###            ####
###      ##  ####     ####  ###    ####    ####     ####  ####     ####   ###      ##   ####
###    ##   ####     ####   ###########   ####     ####  ####     ####    ###    ##    ####
###     ######    #####    ##    #### ######    ###########    #####      ###      ######


In [18]:
# -- 6 --
# problem : http://www.pythonchallenge.com/pc/def/channel.html
# solution : http://www.pythonchallenge.com/pcc/def/oxygen.html

In [19]:
print_source("http://www.pythonchallenge.com/pc/def/channel.html")

<html> <!-- <-- zip -->
<title>now there are pairs</title>
<body>
<center>
<img src="channel.jpg">
<br/>
<!-- The following has nothing to do with the riddle itself. I just
thought it would be the right point to offer you to donate to the
Python Challenge project. Any amount will be greatly appreciated.

-thesamet
-->

<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="item_name" value="Python Challenge donations">
<input type="hidden" name="no_note" value="1">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="tax" value="0">
<input type="hidden" name="bn" value="PP-DonationsBF">
<input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but04.gif" border="0" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>

</body>
</html>


In [20]:
import shutil

# Download the file from url and save it locally under file_name:
with urllib.request.urlopen(url) as response, open(file_name, 'wb') as out_file:
shutil.copyfileobj(response, out_file)


In [21]:
from zipfile import ZipFile

with ZipFile(archive_filename) as archive:
with archive.open(member_filename) as member:


welcome to my zipped list.

hint1: start from 90052
hint2: answer is inside the zip


In [22]:
read_archive_member(archive_filename = "channel.zip", member_filename = "90052.txt")

Out[22]:
'Next nothing is 94191'
In [23]:
nothing = "90052"
while True:
try:
contents = read_archive_member(archive_filename = "channel.zip", member_filename = "{0}.txt".format(nothing))
nothing = re.findall("Next nothing is ([0-9]+)", contents)[0]
except:
print(contents)
break

Collect the comments.

In [24]:
# https://docs.python.org/3/library/zipfile.html#zipfile.ZipFile.comment
with ZipFile("channel.zip") as archive:
print(archive.comment)

b''

In [25]:
# https://docs.python.org/3/library/zipfile.html#zipfile.ZipInfo.comment
archive = "channel.zip"
nothing = "90052"
while True:
try:
member = "{0}.txt".format(nothing)
nothing = re.findall("Next nothing is ([0-9]+)", contents)[0]
except:
break

****************************************************************
****************************************************************
**                                                            **
**   OO    OO    XX      YYYY    GG    GG  EEEEEE NN      NN  **
**   OO    OO  XXXXXX   YYYYYY   GG   GG   EEEEEE  NN    NN   **
**   OO    OO XXX  XXX YYY   YY  GG GG     EE       NN  NN    **
**   OOOOOOOO XX    XX YY        GGG       EEEEE     NNNN     **
**   OOOOOOOO XX    XX YY        GGG       EEEEE      NN      **
**   OO    OO XXX  XXX YYY   YY  GG GG     EE         NN      **
**   OO    OO  XXXXXX   YYYYYY   GG   GG   EEEEEE     NN      **
**   OO    OO    XX      YYYY    GG    GG  EEEEEE     NN      **
**                                                            **
****************************************************************
**************************************************************


In [26]:
print_source("http://www.pythonchallenge.com/pc/def/hockey.html")

it's in the air. look at the letters.


In [27]:
print_source("http://www.pythonchallenge.com/pc/def/oxygen.html")

<html>
<title>smarty</title>
<body>
<br><br>
<center>
<img src="oxygen.png"/>
</body>
</html>


In [28]:
# -- 7 --
# problem : http://www.pythonchallenge.com/pc/def/oxygen.html
# solution : http://www.pythonchallenge.com/pcc/def/integrity.html

In [29]:
download_file("http://www.pythonchallenge.com/pc/def/oxygen.png","oxygen.png")

In [30]:
from PIL import Image
im = Image.open("oxygen.png")
print(im.size, im.mode)

(629, 95) RGBA

In [31]:
chars = []
for x in range(0, 630, 7):
(r, g, b, a) = im.getpixel((x, 43))
if r == g == b:
chars.append(chr(r))
print(*chars, sep = "")

smart guy, you made it. the next level is [105, 110, 116, 101, 103, 114, 105, 116, 121]

In [32]:
print(*map(chr, [105, 110, 116, 101, 103, 114, 105, 116, 121]), sep = "")

integrity

In [33]:
# -- 8 --
# problem : http://www.pythonchallenge.com/pc/def/integrity.html
# solution : http://www.pythonchallenge.com/pcc/return/good.html:huge:file

In [34]:
print_source("http://www.pythonchallenge.com/pc/def/integrity.html")

<html>
<title>working hard?</title>
<body>
<br><br>
<center>
<img src="integrity.jpg" width="640" height="480" border="0" usemap="#notinsect"/>
<map name="notinsect">
<area shape="poly"
coords="179,284,214,311,255,320,281,226,319,224,363,309,339,222,371,225,411,229,404,242,415,252,428,233,428,214,394,207,383,205,390,195,423,192,439,193,442,209,440,215,450,221,457,226,469,202,475,187,494,188,494,169,498,147,491,121,477,136,481,96,471,94,458,98,444,91,420,87,405,92,391,88,376,82,350,79,330,82,314,85,305,90,299,96,290,103,276,110,262,114,225,123,212,125,185,133,138,144,118,160,97,168,87,176,110,180,145,176,153,176,150,182,137,190,126,194,121,198,126,203,151,205,160,195,168,217,169,234,170,260,174,282"
href="../return/good.html" />
</map>
<br><br>
<font color="#303030" size="+2">Where is the missing link?</font>
</body>
</html>

<!--
un: 'BZh91AY&SYA\xaf\x82\r\x00\x00\x01\x01\x80\x02\xc0\x02\x00 \x00!\x9ah3M\x07<]\xc9\x14\xe1BA\x06\xbe\x084'
pw: 'BZh91AY&SY\x94$|\x0e\x00\x00\x00\x81\x00\x03$ \x00!\x9ah3M\x13<]\xc9\x14\xe1BBP\x91\xf08'
-->


In [35]:
# The server reports that it is from inflate.
# Opposite of "inflate" -- "compress"
# un -- (u)ser(n)ame
# pw -- (p)ass(w)ord

import codecs

source = get_source("http://www.pythonchallenge.com/pc/def/integrity.html")
# http://stackoverflow.com/a/37059682
# http://stackoverflow.com/a/23151714
comment = codecs.escape_decode(re.findall(b"<!--(.*?)-->", source, flags = re.DOTALL)[0])[0]
un = re.findall(b"\nun: '(.*?)'", comment)[0]
pw = re.findall(b"\npw: '(.*?)'", comment)[0]

In [36]:
# https://en.wikipedia.org/wiki/List_of_file_signatures
# bz2 -- Compressed file using Bzip2 algorithm -- BZh
import bz2
bz2.decompress(un)

Out[36]:
b'huge'
In [37]:
bz2.decompress(pw)

Out[37]:
b'file'
In [ ]:
# -- 9 --