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

The Python Challange 2

by 꼬부기가우는소리 2016. 8. 29.
728x90

작성 일자 : 2016. 08. 29

재작성 일자 : 2018. 07. 31


http://www.pythonchallenge.com/pc/def/ocr.html





python challenge 2단계이다.

힌트는 "recognize the characters. maybe they are in the book, but MAYBE they are in the page source."

문자를 기억하라 하며 페이지의 소스를 언급한다.

"the book"에서 얼핏 페이지의 그림에 나오는 책을 연상시키도록 하지만 말 그대로 책만 있을 뿐 더 이상의 힌트를 얻을 수 없다.

"the page source"란 말에 따라 F12 (크롬 개발자 도구)를 눌러 소스 코드를 확인해 보도록 하자.





위와 같이 주석으로 처리된 부분이 나오는 것을 확인할 수 있다.

주어진 또 다른 힌트, "find rare characters in the mess below"를 기억해 두고 길게 주석처리 되어있는 부분을 살펴보자.




<!--

%%$@_$^__#)^)&!_+]!*@&^}@[@%]()%+$&[(_@%+%$*^@$^!+]!&_#)_*}{}}!}_]$[%}@[{_@#_^{*

@##&{#&{&)*%(]{{([*}@[@&]+!!*{)!}{%+{))])[!^})+)$]#{*+^((@^@}$[**$&^{$!@#$%)!@(&

+^!{%_$&@^!}$_${)$_#)!({@!)(^}!*^&!$%_&&}&_#&@{)]{+)%*{&*%*&@%$+]!*__(#!*){%&@++

!_)^$&&%#+)}!@!)&^}**#!_$([$!$}#*^}$+&#[{*{}{((#$]{[$[$$()_#}!@}^@_&%^*!){*^^_$^

]@}#%[%!^[^_})+@&}{@*!(@$%$^)}[_!}(*}#}#___}!](@_{{(*#%!%%+*)^+#%}$+_]#}%!**#!^_

)@)$%%^{_%!@(&{!}$_$[)*!^&{}*#{!)@})!*{^&[&$#@)*@#@_@^_#*!@_#})+[^&!@*}^){%%{&#@

@{%(&{+(#^{@{)%_$[+}]$]^{^#(*}%)@$@}(#{_&]#%#]{_*({(])$%[!}#@@&_)([*]}$}&${^}@(%

(%[@%!}%*$}(*@)}){+@(%@*$&]*^*}*]&$[}*]%]+*}^!}*$^^_()#$^]++@__){&&+((#%+(&+){)$

%&&#($[[+##*%${)_!+{_[})%++)$#))]]]$]@]@($+{&%&%+!!!@]_]+])^*@$(@#${}}#}{%}#+{(@

#__+{{]${]!{(%${%%^)(_*_@+)$]$#_@$)]](}{}$(}*%+!}#+)$%$}+#@*&^{##}+@(%[*@_}{(^]^

+_*{@+[$!!@%$+{_&(#^(([&[][[&@#+}_]&&]}^*&$&)#_^$@$((%)}+{}$#+{+^}&[#[#_+${#[#]{

(@@[%}[}$%+*#$+[%(**!$+@$@&+$_$#!_&&&&{***+)}][}#^!%#&$*)$!%}*&#}}##(^_%^]{+]&&]

}^]#^(}@]&$]*_][])$]{_+})^_}]))()^&)(!*![!&}{][(]})[(*^}$&$_@^$)#${%[$_]!^]}}}*+

......(생략)......




내용이 너무 많기에 생략하였다.

힌트에 의해 문제를 풀자면 이 많은 내용들 중에서 문자를 찾아야 한다.

일일이 확인하면서 풀 수도 있지만 그러기에는 눈도 아프고 피로하기만 하다.

파이썬을 이용해 문제를 풀어보도록 하자.



파이썬으로 코딩하면 아래와 같다.


cList = "abcdefghijklmnopqrstuvwxyz"
# 문자열에서 원하는 문자 찾는 함수
def findChar(f):
while True:
# 한 줄씩 읽어들임
line = f.readline()
# 문장이 아닌 경우 종료
if not line:
break
for c in line:
# 해당 문자가 cList 안에 존재하는 경우 출력
if cList.find(c) >= 0:
print(c, end="")
# 파일 불러와 열기
f = open("temp.txt", 'r')
findChar(f)
f.close()


python challenge 1단계와 비슷한 방식으로 풀 수 있다.

문자열을 저장해 놓은 cList에서 해당하는 문자가 존재하는 경우, 즉 반환값이 -1이상인 경우 문자를 출력하도록 함수를 정의한다.


확인해야 할 문장은 굉장히 길기 때문에 앞서 사용했던 방식처럼 일일이 문자열로 저장하기는 힘들다.

따라서, 텍스트 파일로 확인해야 할 문자열을 저장하도록 한다.

python이 실행되고 있는 위치에 문자열을 저장한 temp.txt 파일을 이동시키고 실행시키도록 한다.

또는 절대 경로를 이용하여도 상관없다. (Ex: f = open("C:\\temp.txt", 'r'), '\' 기호는 연속으로 두번 사용해 주어야 한다.)


파일 객체 = open(파일 이름, 파일 열기 모드) 

* 파일 열기 모드: r - 읽기모드 / w - 쓰기모드 / a - 추가모드


open을 이용하여 얻은 파일 객체를 정의한 findChar 함수로 보내어 결과값을 얻어내면 된다.


만약 찾아야 할 알파벳이 cList에 저장된 소문자가 아닌 대문자의 경우, 검색 되지 않는다.

이 문제에서는 소문자만 나왔기 때문에 상관이 없지만 그 경우 대소문자로 변환하는 과정을 거쳐주어야 한다.



실제 결과값은 equality이다.

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




+ 추가1: isalpha

해당 코드가 알파벳이 맞는지 확인하기 위해 리스트를 사용하였다.
리스트 대신, isalpha 함수를 사용할 수 있다.



+ 해설: requests & re 모듈 (Level2 해설)

필요한 부분을 직접 텍스트 파일에 옮기는 것이 아니라 직접 html 파일을 읽어오는 방법을 사용하도록 하자.
requests 모듈을 이용하면 해당 페이지의 모든 소스 코드를 받아올 수 있다.

import urllib.request
html = urllib.request.urlopen("http://www.pythonchallenge.com/pc/def/ocr.html").read().decode()

이제 필요한 부분만 잘라내도록 한다.
re 모듈은 정규 표현식을 이용하여 이것이 가능하게 해준다.
re 모듈의 함수 findall는 조건에 해당하는 모든 값을 찾아주는 함수이다.

import urllib.request
import re

html = urllib.request.urlopen("http://www.pythonchallenge.com/pc/def/ocr.html").read().decode()
comments = re.findall("<!--(.*?)-->", html, re.DOTALL)

comments는 주석으로 처리된 부분을 가지게 된다.
우리가 신경써야할 부분은 마지막으로 주석처리된 부분이므로 이부분만 다시 가져와주도록 한다.
여기서 이제 한문자씩 살펴보며 알파벳인지를 확인해도 되지만, 이번에도 간편하게 findall을 사용하여 알파벳에 해당하는 모든 문자를 가져오도록 한다.

import urllib.request
import re

html = urllib.request.urlopen("http://www.pythonchallenge.com/pc/def/ocr.html").read().decode()
comments = re.findall("<!--(.*?)-->", html, re.DOTALL)
data = comments[-1]
result = "".join(re.findall("[A-Za-z]", data))

앞서 코드에서는 글자를 하나하나 비교해가며 원하는 문자가 맞는지를 확인해보았다.
하지만 re 모듈을 이용하여 정규표현식을 사용하면 훨씬 간편하게 확인할 수 있다.
찾고자 하는 문자는 대문자나 소문자와 관련 없이 알파벳이기만 하면 되므로, [A-Za-z]로 조건을 주어 찾아주면 된다.
findall을 통해 반환된 값은 list 타입이므로 join 함수를 이용하여 한 문장으로 만들어 주도록 한다.

이를 조금 더 다듬어 주면 아래와 같은 깔끔한 결과가 나오게 된다.

import urllib.request
import re

html = urllib.request.urlopen("http://www.pythonchallenge.com/pc/def/ocr.html").read().decode()
data = re.findall("<!--(.*?)-->", html, re.DOTALL)[-1]
print("".join(re.findall("[A-Za-z]", data)))



728x90

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

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

댓글