[그림 01] Problem 010 문제
문제 설명
문제 이름 : 소수의 합
문제 내용 : 10 이하의 소수들의 합을 보면 2 + 3 + 5 + 7로 17이 나옵니다. 그렇다면 2,000,000 미만의 소수들의 합은 무엇입니까?
우리는 조건이 매우 간단하다는 것을 알 수 있습니다. 저도 그렇게 생각했습니다.
그러나... 저는 이 간단함에 여유를 부리고 시간을 매우 소비할 뻔 했습니다.
1. 소수 리스트를 구해야 함
2. 구해진 소수 리스트를 통해 모든 합을 구함
이제 소스를 작성해보도록 합시다.
소수를 구하는 방법이 이 문제의 핵심이라고 생각됩니다.
먼저 제가 가장 빠르다고 생각했던 소수 구하는 방법으로 작성해보았습니다.
소스코드
- vol01
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#Problem 010 #Python 3 version source #Get the sum of all the primes below 2,000,000 def getPrime(Number): primeList = [ 2 ] num = 3 count = 100000 while (num < Number): for x in primeList: if num % x = = 0 : break elif x = = primeList[ - 1 ]: primeList.append(num) break if num = = count: print (primeList) count + = 100000 num + = 1 return primeList if __name__ = = "__main__" : Main_primeList = getPrime( 2000000 ) sum = 0 for i in Main_primeList: sum + = i print ( sum ) |
간단하게 getPrime으로 작성해보았습니다. 지금까지 제가 애용하던 소수 구하기입니다.
count는 그냥 100,000씩 끊어서 체크해보기 위함입니다. 하하..
시간은 1시간 정도 걸리려나요..? 1분동안 돌려보았지만 400,000까지는 해보았습니다. 그 이상은 하지 못했지요.(너무 오래걸려서..)
저는 여기서 getPrime함수의 한계를 느꼈습니다.
이제 진정한 에라스토테네스의 함수로 넘어가볼까요???
먼저 다음 소스를 확인해주시기 바랍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#Sieve Test import time def sieve(Limit): prime = set () not_prime = set () for i in range ( 2 , Limit + 1 ): if i not in not_prime: prime.add(i) for j in range (i * i, Limit + 1 , i): not_prime.add(j) return prime start_time = time.time() primeList = sieve( 2000000 ) print ( len (primeList)) end_time = time.time() print ( "Time : " , end_time - start_time) |
위의 소스는 에라스토테네스의 체를 시험한 것입니다.
참고 URL : http://ledgku.tistory.com/61
위의 URL은 에라스토테네스의 정리를 프로그램적으로 잘 설명해주셨습니다.
시간은 엄청 짧습니다!!
제 태블릿, limit == 2,000,000을 기준으로 1.27초 가량 걸렸습니다.
그렇다면 저 함수를 이용하여 온전한 primeList를 가져오면 좋을 것 같습니다.
- vol 02
두번째 버전의 소스입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#Problem 010 #Python 3 version source def sieve(Limit): prime = set () not_prime = set () for i in range ( 2 , Limit + 1 ): if i not in not_prime: prime.add(i) for j in range (i * i, Limit + 1 , i): not_prime.add(j) return prime if __name__ = = "__main__" : Main_primeList = sieve( 2000000 ) sum = 0 for i in Main_primeList: sum + = i print ( sum ) |
이 함수를 이용하면 2초 가량 걸립니다용. 이번에는 나름 뿌듯합니다.
물론 sieve라는 건 살짝 답안지를 볼까 하는 욕구에서 비롯된 것이지만, 힌트를 얻고 답안지를 안 봤으니 나름 스스로 토닥토닥해줄 수 있지용.
이제 제가 답안지라고 생각하는 소스를 참고해봅시다.
참고 URL : http://www.s-anand.net/euler.html
1 2 3 4 5 6 7 8 9 |
sieve = [ True ] * 2000000 # Sieve is faster for 2M primes def mark(sieve, x): for i in range (x + x, len (sieve), x): sieve[i] = False for x in range ( 2 , int ( len (sieve) * * 0.5 ) + 1 ): if sieve[x]: mark(sieve, x) print ( sum (i for i in range ( 2 , len (sieve)) if sieve[i])) |
sieve 전역 변수는 True로 2,000,000개를 초기화해놓은 배열입니다.
mark함수는 초기화된 sieve와 배수로 지정할 소수를 넘겨줍니다.
그리고 모두 종료되면 모든 합을 구합니다.
일단 대단하다고 느껴집니당. 대단하지만, 이제는 조금 경쟁심이 생기네요 *^^*
'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_009_Special Pythagorean triplet (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 |