본문 바로가기
Algorithm/WarGame - The Python Challenge

The Python Challenge 5

by 꼬부기가우는소리 2016. 9. 7.
728x90

작성 일자 : 2016. 09. 07

재작성 일자 : 2018. 08. 01


참고 사이트 :

[docs.python] 11.1. pickle — Python object serialization

- [위키백과] 윈도우 파워셸


- [docs.python] 12.1. pickle — Python object serialization







python challenge 5단계이다.

title은 "peak hell", 그리고 힌트는 "pronounce it".

어디에 적용해야 할지 확인하기 위해 F12를 눌러 소스 코드를 확인해 보도록 한다.





페이지에는 드러나지 않은 peakhell 영역이 존재하고 이는 banner.p와 연결되어 있음을 확인할 수 있다.

또한 앞서 발견했던 힌트, "pronounce it"과 연관된 힌트 "peak hell sounds familiar?" 라는 문구를 확인할 수 있다.


banner.p 페이지로 이동해 보자.





(lp0

(lp1

(S' '

p2

I95

tp3

aa(lp4

(g2

I14

...(생략)... 



숫자와 기호가 반복되어 나오며 일반적으로 우리가 이해할 수 없는 형태로 되어 있다.

이 외에 더 숨겨져 있는 힌트는 없는 것 같다.


다시 처음의 힌트로 돌아가 보자.

출제자는 peak hell의 발음을 강조하고 있다.

peak hell은 한글 발음으로 "피켈", "피클" 등으로 표기가 가능하다.

검색을 통해 이와 유사한 python 모듈에는 pickle(피클)이 있음을 확인할 수 있다.





정확한 표기로 검색하여 모듈 pickle에 대한 정보를 확인한다.



12.1. pickle — Python object serialization

The pickle module implements a fundamental, but powerful algorithm for serializing and de-serializing a Python object structure. “Pickling” is the process whereby a Python object hierarchy is converted into a byte stream, and “unpickling” is the inverse operation, whereby a byte stream is converted back into an object hierarchy. Pickling (and unpickling) is alternatively known as “serialization”, “marshalling,” or “flattening”, however, to avoid confusion, the terms used here are “pickling” and “unpickling”.



주어진 데이터는 일반적인 방식으로 읽지 못하도록 "피클링(Pickling)" 되어 있음을 추측해 볼 수 있다.

해당 데이터를 우리가 읽을 수 있는 값으로 변환하기 위한 "언피클링(Unpickling)" 과정을 거쳐 이 추측이 맞는지 확인해 보도록 한다.


import urllib.request
import re
import pickle

html = urllib.request.urlopen("http://www.pythonchallenge.com/pc/def/banner.p").read()
print(pickle.loads(html))


pickle은 파일을 읽어올 때 loads 함수를 이용한다.

단, pickle 모듈로 파일을 저장하거나 불러올 때는 문자열 형식이 아닌 바이트 형식을 사용해야 한다.


해당 코드를 실행시키면 아래와 같이 출력된다.



[[(' ', 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)]] 



규칙적으로 ' ' 또는 '#'와 쌍을 이루는 숫자가 있음을 확인할 수 있다.

즉, 해당 데이터가 피클링 되어 있었음을 확인할 수 있다.


각각의 쌍은 또다시 대괄호([])안에 쌓여있다.

대괄호 안에 쌓여있는 숫자를 계산해 보면 각각 숫자의 합은 95로 일정한 것을 확인할 수 있다.

혹 대괄호가 한 줄을 뜻하고, 각 문자를 숫자 만큼씩 출력을 해 보면 그림으로 문자가 나타나는 것이 아닐까.


이를 확인하기 위해 출력해 보도록 한다.


import urllib.request
import re
import pickle

html = urllib.request.urlopen("http://www.pythonchallenge.com/pc/def/banner.p").read()
data = pickle.loads(html)

for line in data:
    result = ""
    for i in range(len(line)):
        char = line[i][0]
        for n in range(line[i][1]):
            result += char
    print(result)




위와 같이 정확하게 문자를 이루는 것을 확인할 수 있다.

결과값은 channel.

즉, "www.pythonchallenge.com/pc/def/channel.html" 가 python challenge 5단계의 정답이 된다.




+ 추가 (2018. 08. 01 작성)

(참고 : Level5 해설)


해설을 확인하면, 우리가 for 문을 이용하여 문자를 반복적으로 출력한 것을 아래와 같이 단 두 줄로 간단하게 표현한 것을 확인할 수 있다.


for line in data:
print("".join([k * v for k, v in line]))




'Algorithm > WarGame - The Python Challenge' 카테고리의 다른 글

The Python Challenge 4  (0) 2016.08.31
The Python Challenge 3  (0) 2016.08.29
The Python Challange 2  (0) 2016.08.29
The Python Challenge 1  (0) 2016.08.29
The Python Challenge warming up  (0) 2016.08.29

댓글