Python/2.7 simple coding(+ c++)

hack this site Programming missions : Parse an XML file

qkqhxla1 2015. 4. 10. 14:17

https://www.hackthissite.org/missions/prog/4/


시작하면 시간이 2분이 주어진다. 2분이 주어진다는건 프로그래밍 과정중 하나쯤은 프로그래밍을 

안하고 손으로 노가다해도 된다는 의미이다.(난 마지막에 나온 숫자들을 판별하는것에 시간을 썼다. 즉 결과가 나오면 보고 직접 타이핑했다는 의미) 들어가면 랜덤하게 xml파일이 하나 나오고, 그 xml파일대로

선과 호를 그린 후 파랑,녹색,빨강,노랑,검정(원래는 흰색인데 내가 흰색대신 검정으로 바꿈.) 순서대로 읽어서 '파랑,녹색,빨강,노랑,검정' 과 같은 형식으로

보내면 통과이다. python의 matplotlib을 참조했다. 이것은 파이썬에서 매트랩을 쓸수 있는 모듈이다.


하는 방법은. http://matplotlib.org/users/screenshots.html

해당 모듈을 다운받아서 대충 사용법을 안 후, 


https://www.hackthissite.org/missions/prog/4/info.html

에 나와있는 설명처럼 호와 선분을 그리는 방법을 알아둔다.

예시 사진.


이제 시작하면 된다. 랜덤으로 생성되는 bz2를 다운받아서 plotMe.xml.bz2를 압축푼다. 그 후에 xml을 알아서 잘 파싱해서 (난 앞에서 네이버 음악 다운로드를 할때 썼던 lxml모듈을 썼다.) 해당 정보들을 저장 후, matplotlib으로 그래프를 그린다. 그다음에 출력된 그래프에서 답 순서대로 빨리 메모장에서 적어서 낸다.


프로그래밍을 잘 했다면 아래와 같은 실행 결과가 나타난다.







내 소스코드.

# -*- encoding: cp949 -*-
from pylab import *
from lxml import etree
import numpy
import bz2
import urllib2

def download_photo(filename):
    file_path = "%s%s" % ("C:\\Users\\Ko\\Documents\\Visual Studio 2012\\Projects\\PythonApplication37\\", filename)
    downloaded_image = file(file_path, "wb")
     
    req = urllib2.Request('https://www.hackthissite.org/missions/prog/4/XML')
    req.add_header('Cookie','PHPSESSID=id5f9iq24h42heb361p9offhg4')
    image_on_web = urllib2.urlopen(req)
    while True:
        buf = image_on_web.read()
        if len(buf) == 0:
            break
        downloaded_image.write(buf)
     
    downloaded_image.close()
    image_on_web.close()
    return file_path

filepath = 'plotMe.xml.bz2'
download_photo(filepath) #다운로드.
zipfile = bz2.BZ2File(filepath) # bz2의 압축을 푸는 코드. stackoverflow에서 복사해옴.
data = zipfile.read() # get the decompressed data
newfilepath = filepath[:-4] # assuming the filepath ends with .bz2
open(newfilepath, 'wb').write(data) # write a uncompressed file

pi = 3.141592
def plot_arc(_x,_y,r,first,end,color): #호를 그리는 코드.
    ThetaDeg = arange(first,first+end,0.01)
    xData = r * cos(ThetaDeg * pi/180) + _x
    yData = r * sin(ThetaDeg * pi/180) + _y
    plot(xData,yData,color);
    grid()
def plot_line(x1,y1,x2,y2,color): #직선을 그리는 코드.
    if x2-x1==0:
        yData = arange(y1,y2,0.01)
        xData = numpy.repeat([x1],yData.size)
    else:
        xData = arange(x1,x2,0.01)
        if x1>x2:
            xData = arange(x2,x1,0.01)
        yData = ((float(y2)-y1)/(float(x2)-x1))*(xData-x1)+float(y1)
    plot(xData,yData,color);
    grid()

parser = etree.XMLParser(remove_blank_text=True,recover=True)  #xml파싱용 코드.
root = etree.XML(open('plotMe.xml','r').read(),parser)  #다운받은 plotMe.xml을 파싱한다.
before = ''; count = 0; x1=0; y1=0; x2=0; y2=0; color=''; r=0

for element in root.iter("*"):  #문제 푸는 알고리즘. 귀찮아서 설명은 안씀.
    if element.tag=='Line' or element.tag=='Arc': 
        if before=='Line' and count==5:
            plot_line(x1,y1,x2,y2,'black')
        elif before=='Arc' and count==6:
            plot_arc(x1,y1,r,x2,y2,'black')
    if element.tag=='Line' or element.tag=='Arc':
        if before=='Line' and count==6:
            plot_line(x1,y1,x2,y2,color)
        elif before=='Arc' and count==7:
            plot_arc(x1,y1,r,x2,y2,color)
    if element.tag=='Line' or element.tag=='Arc':
        before = element.tag
        count = 0
    if before == 'Line':
        if element.tag== 'XStart':
            x1 = float(element.text)
        if element.tag== 'YStart':
            y1 = float(element.text)
        if element.tag== 'XEnd':
            x2 = float(element.text)
        if element.tag== 'YEnd':
            y2 = float(element.text)
        if element.tag== 'Color':
            color = element.text
        count += 1
    if before == 'Arc':
        if element.tag== 'XCenter':
            x1 = float(element.text)
        if element.tag== 'YCenter':
            y1 = float(element.text)
        if element.tag== 'Radius':
            r = float(element.text)
        if element.tag== 'ArcStart':
            x2 = float(element.text)
        if element.tag== 'ArcExtend':
            y2 = float(element.text)
        if element.tag== 'Color':
            color = element.text
        count += 1

show()