Python/2.7 simple coding(+ c++)

Enigmagroup missions/programming 9

qkqhxla1 2014. 11. 27. 20:49

8번은 뭔지 잘 모르겠다. 9번 같은경우 실행시키면 



요런 이미지가 나오는데. 이 이미지와 숫자의 뜻은 다음과 같다.


1행 : 2*하트+별+사각형 = 1149

2행 : 3*삼각형+원 = 1364

....


1열 : 2*삼각형+사각형+하트 = 1385

2열 : 하트+3*삼각형 = 1525

.....


이런식인데 이걸 연립방정식을 만들어서 각각 하트,삼각형,별,사각형,원 이 5개의 값을 방정식을


푼 뒤에 값을 찾아내서 2초안에 전송하면 성공이다. 미지수는 5개이나 식은 10개가 나오니


반드시 푸는게 가능하다. 풀려면 미지수 5개에 식 5개만 나와도 된다.


단순 프로그래밍만 좋아해서는 몰랐을텐데 이번에 듣는 수업중에 수치해석이라는 수업이 있는데,


해당 수업에서 매트랩으로 해당 미지수의 계수와 해당 값만 알면 구할수 있는 방법을 배웠었다.


예로 미지수가 3개인 방정식


3x^2 + y + 2z = -4

-x + -2y + z = -2

2x + 3y -2z = 5


라는 방정식이 있으면


 3,1,2;                      -4;

-1,-2,1;                    -2;

2,3,-2                       5


과 같이 계수들만 행렬로 변환시킨다. 그리고 왼쪽의 3x3행렬을 a, 오른쪽의 3x1행렬을 b라고하면


a의역행렬*b = 값이 3개 나오는데, 이 3개의 값이 각각 미지수이다.



매트랩 결과. 1,-1,-3이 해이다. 


이 문제도 매트랩을 이용하면 되는데, 파이썬의 numpy모듈을 설치하면 매트랩으로 작업하는것과 


동일하게 할 수 있다. (튜토리얼) 우선 html코드에서 각각 사각형이 몇갠지, 원이 몇갠지, 별이 몇갠지


합이 몇갠지 등등 갯수를 세서 행렬로 만든다음에 파이썬의 numpy모듈을 이용해서 답을 낸 후


그걸 다시 문자열로 가공해서 전송했다. numpy모듈을 처음 써보는데 제대로 잘 작동해서 좋다.


소스. (종종 singular행렬이 나오거나 시간이 초과되서 안될수있으니 여러번 돌려야한다.)

enigmagroup_programming_9.py




import urllib2,re,numpy

req = urllib2.Request('http://www.enigmagroup.org/missions/programming/9/')
req.add_header('cookie','쿠키값')
page = urllib2.urlopen(req).read()
#print page[1200:2000]

imglist = re.findall('<td>(.*?)</td>',page) #<td>태그 사이의 값을 전부 다 가져온다.

for i in range(0,len(imglist)):
    if imglist[i]=='Circle : ': #Circle : 이라는 문자열이 나오면 거기서부터는 필요 없는값이므로 
        imglist = imglist[0:i] #그 이전까지만 가져온다.
        break

for i in range(0,len(imglist)):
    if imglist[i].find('<img src=') != -1: #<img src=로 시작하면 그림중 하나이므로
        imglist[i]=re.findall('<img src="shapes/(.*?)\.png">',imglist[i])[0] #그 안의 글자만 가져온다.
    elif imglist[i].find('<strong>') != -1: #<strong면 숫자이다(문자들의 합) 여기서
        imglist[i]=re.findall('<strong>(\d+)</strong>',imglist[i])[0] #숫자만 빼온다.
#print imglist

heart = square = circle = triangle = star = 0 #각각의 갯수를 저장할 변수
mat = '' #미지수의 계수 관련된 행렬을 만들기 위한 변수
mat2 = '' #미지수의 총 값에 관련된 행렬을 만들기 위한 변수
for i in range(1,len(imglist)+1):
    if i%6==0:
        mat += str(heart)+','+str(square)+','+str(circle)+','+str(triangle)+','+str(star)+';' #행렬을 만들때 이런식으로 만든다... 알아서 찾아보길.
        mat2 += imglist[i-1]+';'
        heart = square = circle = triangle = star = 0
    elif imglist[i-1]=='heart':
        heart += 1
    elif imglist[i-1]=='square':
        square += 1
    elif imglist[i-1]=='circle':
        circle += 1
    elif imglist[i-1]=='triangle':
        triangle += 1
    elif imglist[i-1]=='star':
        star += 1
mat = numpy.matrix(mat[:len(mat)-1]) #최종적으로 계수 관련된 행렬 만들고
mat2 = numpy.matrix(mat2[:len(mat2)-1]) #최종적으로 만들어진 미지수들의 결과값 행렬.
#print re.findall('\[ (\d+).\]',str(numpy.linalg.inv(mat)*mat2))
num = re.findall('\[ (\d+).\]',str(numpy.linalg.inv(mat)*mat2)) #numpy.linalg.inv는 역행렬을 만들어주는 함수이다. 위에서 말했듯이 역행렬*결과값= 답이 나온다.

req = urllib2.Request('http://www.enigmagroup.org/missions/programming/9/',\
    'circle='+num[2]+'&heart='+num[0]+'&square='+num[1]+'&triangle='+num[3]+'&star='+num[4]+'&submit=Submit') #보낼 데이터를 이렇게 만든다. 
#위에서 mat변수로 행렬을 만들때 heart,square,circle,triangle,star순으로 만들어서 순서가 좀 삐둘삐뚤하다.
req.add_header('cookie','쿠키값')
print urllib2.urlopen(req).read()