[그림 01] Problem 009 문제
문제 이름 : 특별한 피타고라스 정리
문제 내용 : 피타고라스 정리의 삼각형에서 세 개의 자연수에 대한 설정은 a < b < c이며, a^2 + b^2 = c^2입니다. 예를들면 3^2 + 4^2 = 9 + 16 = 25 = 5^2라고 할 수 있습니다. 그렇다면, a + b + c = 1000일 때 위의 정의에 맞는 a, b, c를 구하고 그의 곱인 a*b*c를 구하시오.
우리는 다음과 같은 조건이 있다는 것을 알 수 있습니다.
1. a < b < c가 성립되어야 함
2. a^2 + b^2 = c^2이 되어야 함
3. a + b + c = 1000이 되어야 함
무작정 소스코드를 작성함에 있어서 많은 어려움이 있습니다...
먼저 손으로 구해본 결과 어떻게 해야할지 몰라서... BruteForcing을 해야 하나 하며 고민한 결과 정말로 BruteForcing을 하기로 했습니다. ㅎㅎ
첫번째 버전의 소스는 다음과 같습니다.
#Problem 009 #Python 3 version source #a + b + c = 1000 def findPythagorean(Limit): a = 3 b = 4 c = 5 for i in range(a, Limit): for j in range(b, Limit): for k in range(c, Limit): if k**2 == (i**2 + j**2): print("A : ", i, " B : ", j, " C : ", k, "A+B+C == ", i+j+k) if i+j+k == 1000: print(i, " ", j, " ", k) break
첫번째 버전의 소스로 하면 겁나 오래걸립니다. 나오기는 합니다만, 중복되는 계산이 많아서 꽤 걸립니다.
두번째 버전의 소스로 넘어가 보면 조건을 하나 더 걸어보았습니다.
#Problem 009 #Python 3 version source #a + b + c = 1000 def findPythagorean(Limit): a = 3 b = 4 c = 5 for i in range(a, Limit): for j in range(b, Limit): if j > i: for k in range(c, Limit): if k > j: if k**2 == (i**2 + j**2): print("A : ", i, " B : ", j, " C : ", k, "A+B+C == ", i+j+k) if i+j+k == 1000: print(i, " ", j, " ", k) break
두번째 버전의 소스는 a < b < c 의 조건을 성립시켜주었습니다. 사실 첫번째 소스를 작성할 때 이 조건을 깜빡하고 했습니다. ㅎㅎ
그러나 이렇게 해도 시간은 어어어엄청 걸립니다. a + b + c 의 값이 1000이 되지 않으면 무한 반복이지요...(정확히는 a가 1000이 될 때까지 계속 반복됩니다.)
그렇다면 우리는 시간을 대폭 줄일 필요가 있습니다.
세번째 소스로 보겠습니다.
#Problem 009 #Python 3 version source #a + b + c = 1000 def findPythagorean(Limit): half = Limit / 2 a = 0 b = 0 c = 0 while(a < half): a += 1 b = half - a while(b < half): c = Limit - (a + b) if c < (a+b) and a**2 + b**2 == c**2: print("A : ", a, " B : ", b, " C : ", c, " A*B*C : ", a*b*c) b = Limit + 1 a = b b += 1 if __name__ == "__main__": Main_LimitNumber = 1000 findPythagorean(Main_LimitNumber)
반복구간을 결정할 필요가 있습니다.
먼저 a, b, c를 선언하고 초기화 해주고 다음으로 넘어갑시다.
a의 검색 구간을 전체의 반으로 줄여서 1부터 500으로 만들어서 그 반복을 설정합니다.
또한 b는 설정구간을 (절반 - a)로 지정해줍니다.
그 다음 while문으로 넘어가 b가 절반보다 작을 때 조건문을 실행합니다.
<조건문>
1. 삼각형의 기본적인 조건인 가장 큰 변이 두 변의 합보다 작아야 함.
2. 주어진 조건인 a^2 + b^2 = c^2
위의 두 조건이 만족할 때 a, b, c를 각각 출력합니다. 그리고 적절하게 빠져나갈 수 있도록 길을 만들어놓습니다.
만약 위의 조건문이 실행되지 않을 시 b += 1을 실행해주고, while문을 반복합니다.
이렇게 되면 a의 범위 b의 범위 c의 범위 1000 * 1000 * 1000이 아닌 (500 * 501) / 2 * 500으로 빠르게 해결할 수 있습니다.
물론 그 사이사이의 조건 계산과 값 계산을 뺀다면 더욱 빠르게 할 수 있다는 것을 의미합니다.
1초에 할 것을 0.062초만에 하는 것입니다.
저보다 겁나 뛰어난 분의 소스를 가져와보도록 합시다.
for a in range(1, 1000): for b in range(a, 1000): c = 1000 - a - b if c > 0: if c*c == a*a + b*b: print(a*b*c) break
겁나게 굉장합니다.
범위를 절반이 아닌 전체로한 것 이외에 조건은 똑같습니다.... 우왕...
'PYTHON > Project Euler(프로젝트 오일러)' 카테고리의 다른 글
Problem_012_Highly divisible triangular number (0) | 2017.01.30 |
---|---|
Problem_011_Largest product in a grid (0) | 2017.01.26 |
Problem_010_Summation of primes (0) | 2017.01.20 |
Problem_008_Largest product in a series (0) | 2017.01.09 |
Problem_007_10001st prime (0) | 2017.01.09 |
Problem_006_Sum square difference (0) | 2017.01.07 |
Problem_005_Smallest Multiple (0) | 2017.01.06 |
Problem_004_Largest palindrome product (0) | 2017.01.03 |