[그림 01] Problem 008 문제


문제 이름 : 가장 큰 곱(product)

문제 내용 : 네 개의 가장 인접한 숫자들로 이루어진 천의 자리 가장 큰 곱은 9 * 9 * 8 * 9 = 5832입니다. 즉, 위의 숫자 나열 중에 9989라고 연속되어 있는 숫자가 있고, 이 숫자들의 곱이 4개의 숫자 중 가장 큰 것이라는 의미입니다. 그렇다면, 열 세 개의 숫자가 나열되어 있는 것들 중 가장 큰 곱을 가지고 있는 것은 무엇입니까?

위의 문제는 4개의 연속된 숫자 중 가장 큰 곱이 나올 숫자를 찾아보니 9989라는 숫자로 9 * 9 * 8 * 9가 되어 5832라고 하였습니다.

그렇다면 우리는 13개의 연속된 숫자 중 가장 큰 곱이 나올 숫자를 찾아 그 값을 출력해야 합니다.


우리는 다음과 같은 조건이 부여된 것입니다.

1. 13자리 자리씩 끊어서 가장 큰 곱이 나오는 것을 찾도록 해야 함

1. 13자리를 각각 곱해야 함



#Problem 008
#Python 3 version source
 
import operator
 
Number = """7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"""
 
NumberList  = list(Number) #Number List
ProductDict = {}           #New dictionary type
position    = 0
num         = 1
 
while(position+13 < len(NumberList)):
  for i in range(position, position+13):
    num *= int(NumberList[i])
  ProductDict[num] = Number[position:position+13]
  num = 1
  position += 1
   
sorted_ProductDict = sorted(ProductDict.items(), key=operator.itemgetter(1)) #key 값으로 정렬
#sorted_ProductDict = sorted(ProductDict.items(), key=operator.itemgetter(0)) #value 값으로 정렬
print(sorted_ProductDict)


이제 소스코드를 작성해보도록 하겠습니다.

위와 같이 Number에 숫자를 모두 넣어주고 13칸 씩 이동하면서 각 숫자를 모두 더하여, 가장 큰 숫자를 프린트하도록 합니다.

ProductList는 13개의 숫자를 곱하여 나온 값을 하나하나 List로 저장하는 것이고, 이를 sort()함수로 정렬한 뒤, 가장 큰 숫자를 출력하도록 했습니다.

메모리적 이득을 보기 위해서는 set()을 쓰는 것도 괜찮은 방법이라고 생각합니다.


또한 소스에서 21번째 라인을 보시게 되면 key 값으로 정렬하지 않고 value 값으로도 정렬할 수 있습니다.


이제 저보다 겁나 잘하는 사람의 소스를 가져와서 비교해보도록 할 것입니다.

마음의 준비를 해야겠네요..


s = '7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450'
n = 0
for i in range(0, len(s)-4):
    p = 1
    for j in range(i,i+5):
        p = p * int(s[j])
    if p > n: n = p
 
print(n)



이 소스는 13개의 숫자가 아니라 5개의 숫자를 곱한 값을 구하는 공식입니다.

확실히 더 효율적으로 보입니다.

굳이 List에 저장할 필요 없이 더 크면 저장하고 크지 않으면 저장하지 않는 알고리즘이 더 메모리를 아낄 수 있는 것 같습니다.



[그림 01] Problem 007 문제


문제 이름 : 10001번째 소수

문제 내용 : 처음 6개의 소수가 2, 3, 5, 7, 11, 13이라고 할 때, 6번째 소수는 13이라는 걸 알 수 있습니다. 그렇다면 10001번째의 소수는 무엇입니까?


우리는 간단하게 다음과 같은 조건을 만족하는 소스를 작성해봅시다.

1. 소수를 구하는 함수

2. 소수 리스트의 길이가 10001이 될 때까지 반복

3. 마지막 소수를 출력


이제 소스를 작성해봅시다.





#Problem 007
#Python 3 version source

#By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
#What is the 10 001st prime number?

def getPrime():    #소수 구하는 함수
	primeList = [2]  #소수 첫번째 리스트
	num = 3          #두 번째 소수 비교하는 수
	
	while(len(primeList) < 10001):    #primeList가 10001번째보다 작으면 계속 반복
		for x in primeList:        
			if(num % x == 0):
				break
			elif(x == primeList[-1]):
				primeList.append(num)
				break
		num += 1
		
	return primeList

if __main__ = "__name__":
	Main_primeList = getPrime()
	
	print(Main_primeList[-1]) #마지막 소수 리스트의 숫자를 출력

getPrime 함수는 소수를 구하는 함수이고, 이 함수는 primeList의 길이가 10001번째가 아니면 계속 반복하여 구하는 구조입니다.

그리고 모두 구한 후, main에 있는 변수로 리턴해주고, 이 중 마지막 리스트를 출력합니다.


이제 저보다 잘하는 사람의 소스를 참고해봅시다.

두근두근...!!

#python 2 version source
import prime
print prime.prime(10000)

오... 신이시여... 이럴수가...

위의 소스는 prime이라는 모듈을 다운받아야 실행이 되는 것 같습니다.

저는 다운받는데 실패했습니다.

흑흑.... 그냥 저 위의 소스를 활용하렵니다.

[그림 01] Problem 006 문제


문제 이름 : 합해서 제곱과 제곱해서 합하는 것의 차이

문제 내용 : 1,2,3,4 ... 10을 각각 제곱해서 더하면 385입니다. 그리고 1,2,3,4 ... 10을 미리 더한 후 제곱을 하면 55의 제곱이고 이는 3025입니다. 그리고 그 차이는 2640입니다. 그렇다면 이 범위를 100으로 넓히고 그 차이는 얼마입니까?


우리는 여기서 다음과 같은 조건을 알 수 있습니다.

1. 1~100의 각각의 제곱을 더해야 하는 값이 필요함

2. 1~100을 모두 더한 후 제곱을 하는 값이 필요함

3. 위의 둘의 차이를 구함


굉장히 간단합니다.

다짜고짜 소스를 작성했습니다.

#Problem 006
#Python 3 version source

def getSquaresOfFirstHundred(Range_Num):
	#1**2 + 2**2 + 3**2 + 4**2 + 10**2 = 385
	num = 0
	for i in range(1, Range_Num+1):
		num += i**2
	return num
	
def getSumOfTheFirstHundred(Range_Num):
	#(1+2+3+...10)**2 = 55**2 = 3025
	num = 0
	for i in range(1, Range_Num+1):
		num += i
	return num**2

if __name__ == "__main__":
	Main_Range = 100
	Main_SquaresOfFirstHundred = getSquaresOfFirstHundred(Main_Range)
	Main_SumOfTheFirstHundred  = getSumOfTheFirstHundred(Main_Range)
	
	print(Main_SumOfTheFirstHundred - Main_SquaresOfFirstHundred)

위의 소스는 단순합니다.

getSquareOfTheFirstHundred와 getSumOfTheFirstHundred함수를 각각 선언하고, 두 값을 구합니다.

그리고 이 둘을 뺀 값을 출력합니다.


저보다 굉장히 잘하는 분이 작성하신 소스코드는 다음과 같습니다.

r = range(1, 101)
a = sum(r)
print a * a - sum(i*i for i in r)

이런 간단한 문제에서도 격이 느껴지네요.

저는 아직까지 Python의 장점을 제대로 활용하고 있지 않은 것 같습니다.

좀 더 활용할 수 있도록 간단한 소스를 작성할 수 있도록 해야 할 것 같습니다. ㅎㅎ



[그림 01] Problem 005 문제


문제 제목 : 가장 작은 최소공배수

문제 내용 : 2520은 1이상 10이하로 모두 나누어지는 숫자 중 가장 작은 값(최소공배수)입니다. 그렇다면, 1이상 20이하의 최소공배수(모두 나누어지는 가장 작은 수)

※ evenly divisible : 고르게, 골고루 나누어 질 수 있는


우리는 다음과 같은 조건을 알 수 있습니다.

1. 최소공배수가 되는 녀석을 알아내야 함

2. 소수는 다 들어 있을 것임


위의 조건으로 먼저 손으로 풀어보니(노가다가 좀 있었습니다), 5 * 7 * 9 * 11 * 13 * 16 * 17 * 19이 정답이 되었습니다.

그런데 이걸 어떻게 규칙으로 만들어야 하나.... 손으로 많은 고민을 해본 결과 다음과 같은 규칙을 알게 되었습니다.

일단 소수를 모두 구한 후, 소수가 아닌 녀석들을 한 번 보았습니다.


소수 : 2, 3, 5, 7, 11, 13 ,17, 19

소수가 아닌 값 : 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20


그리고 정답의 9와 16을 보니, 20보다 작은 소수의 제곱이었습니다.

9는 3^2, 16은 2^4입니다.

그리고 나머지 소수는 제곱만 해도 20을 넘기 때문에 제외되는 것이었습니다.


이제 위의 내용을 통해 소스 코드를 작성해보도록 합시다.


#Problem 005
#Python 3 version source

#answer = 5*7*9*11*13*16*17*19

def getPrime(primeRange):
	primeList = [2] #소수 리스트
	number = 3      #소수 시작 숫자
	
	while(number <= primeRange):
		for i in primeList:
			if(number % i == 0):      #기존의 소수로 나누어지면 소수가 아님
				break
			elif(i == primeList[-1]): #마지막 소수로도 안 나눠지면 소수 
				primeList.append(number)
				break
		number += 1
	
	return primeList
	
if __name__ == "__main__":
	Main_Smallest_Num_Range = 20
	Main_primeList = getPrime(Main_Smallest_Num_Range)
	Main_elseList = list()
	Main_Answer = 1
	Main_Exception = set([2,3])
	
	#Main_Smallest_Num_Range를 넘지 않을 때까지 제곱을 함
	for i in Main_primeList:
		num = i
		while True:
			if num * i > Main_Smallest_Num_Range:
				break
			num *= i
			
		Main_elseList.append(num)
	
	#Main_Set은 최소공배수에 들어갈 최종 리스트들임
	#Main_primeList : 소수들의 리스트
	#Main_elseList  : 소수가 아닌 것들의 제곱 리스트
	#Main_Exception : 2와 3은 제외되기 때문에 제외시킬 리스트
	#Main_Answer    : 최소공배수 값(답)
	Main_Set = set(Main_elseList + Main_primeList) - Main_Exception
	
	#최소공배수를 만드는 함수
	for i in Main_Set:
		Main_Answer *= i
	
	print("Set List : ", Main_Set)
	print("Answer   : ", Main_Answer)

소스 못 쓸 줄 알았는데 다행이 써지네요.

신난다요.


이제 저보다 잘하는 사람의 답을 가져와보도록 합시다.

def gcd(a,b): return b and gcd(b, a % b) or a
def lcm(a,b): return a * b / gcd(a,b)

n = 1

for i in range(1, 21):
    n = lcm(n, i)
print(n)

아....!

[그림 02] 마...맞다....! gcd... lcm은 또 뭐지..!?



겁나 잘하네요... 저는 gcd, lcm의 존재를 모르고 있었습니다...

이번에는 나름 멋지게 짠 거라고 생각했거늘, 버젓이 gcd, lcm이라는 기능이 있었네요 헿.


gcd는 최대공약수 함수이며, lcm은 최소공배수 함수입니다.

gcd(a, b) : a와 b의 최대공약수를 구하여 return함

lcm(a, b) : a와 b의 최소공배수를 구하여 return함


gcd와 lcm을 만들어서 활용할 수 있는 방향도 있군요..!

P.S. python에서는 gcd와 lcm을 지원하지 않습니다. 때문에 두 번째 소스에서는 gcd와 lcm을 맞춤형으로 선언한 것을 알 수 있습니다.



[그림 01] Problem 004 문제


문제를 살펴보면 다음과 같습니다.

문제 이름 : 가장 큰 데칼코마니 숫자

문제 내용 : Palindromic 숫자란 앞으로 읽나 뒤로 읽나 같은 숫자를 의미합니다. 두 자리 숫자 두 개로 만들어진 가장 큰 Palindromic 숫자는 9009 = 91 x 99입니다. 그렇다면 세 자리 숫자 두 개로 이루어진 Palindromic 숫자 중 가장 큰 숫자를 찾으십시오.

※ palindrome 이란 앞에서부터 읽나 뒤에서부터 읽나 똑같은 것을 의미함(madam, nurse run 과 같은 것)


우리는 다음과 같은 조건을 가진다는 것을 알 수 있습니다.

1. 3자리 숫자 두 개를 곱해서 생성된 숫자를 Palindromic 숫자인지 구분해야 함

2. 범위는 999 * 999의 가지 수를 가짐


이제 소스코드를 작성해보도록 합시다.

뭔가 발코드인 느낌도 나고... 아니면 괜히 복잡하게 작성한 것 같을 수 있습니다.


def judgePalindromic(palinNum):
	palinNumList = list(str(palinNum))#palindromic 숫자를 확인하기 위한 숫자 구분
	palinNumLen  = len(palinNumList)  #palindromic 숫자의 길이
	
	for i in range(int(palinNumLen / 2)):
		#palindromic 숫자의 맨 앞과 맨 끝의 숫자를 비교함(길이가 홀수/짝수 상관 없음)
		if palinNumList[i] != palinNumList[-(i+1)]:
			return 0
	return palinNum
	
if __name__ == "__main__":
	Main_PalindromicNumber = 0
	Main_Digits = [999, 999]     #999 * 999의 가지 수
	Main_LimitRange = 0          #999 ~ LimitRange를 정해줌
	
	#Main_Digits[0] x Main_Digits[1]의 곱을 이중 for문으로 작성
	for i in range(Main_Digits[0], Main_LimitRange, -1):
		for j in range(Main_Digits[1], Main_LimitRange, -1):
			num = i * j
			
			#Palindromic숫자고, 이전의 Palindromic숫자보다 크면 Main_PalindromicNumber에 저장함
			if judgePalindromic(num) and Main_PalindromicNumber < num:
				Main_PalindromicNumber = num
	
	print(Main_PalindromicNumber)


judgePalindromic(숫자) 함수는 Palindromic 숫자임을 확인해주는 함수입니다.

main함수에서는 세 자리 숫자의 두 개를 곱하여 Palindromic 숫자임을 확인하는 이중 for문을 작성하였고, if를 통해 (0이 아닌 값이 반환) and (이전의 숫자보다 크면 Main_PalindromicNumber에 저장)합니다.

이 모든 것들이 완료되면 출력하게 됩니다.


저보다 잘하는 사람은 겁나 많습니다.

사실 이쯤되면 조금 분하기도 합니다. 저는 겁나 길게 작성했는데 이 소스는 겁나 짧네요.

출처 : http://www.s-anand.net/euler.html

n = 0
for a in range(999, 100, -1):
    for b in range(a, 100, -1):
        x = a * b
        if x > n:
            s = str(a * b)
            if s == s[::-1]:
                n = a * b
print(n)

맞다.... 그랬습니다. string값을 뒤집어서 그 값이랑 기존의 값이랑 비교하면 되는 것이었습니다.

굉장하다 이 소스...!!!

저는 바보같이 그것을 일일이 비교하였습니다.

s == s[::-1]은 기존의 string == 반대로 string입니다.


참고 URL


<Python 버전 기준>

Python 2.7.13

Python 3.6.0


파이썬 3은 C:\ 바로 및에 Python3이 설치가 되지 않는 것을 보고 어떻게 해야 할지 막막했는데 참고 출처를 보고 설정할 수 있었습니다.

먼저 Python 3을 설치하고 Python 2를 설치했기 때문에 제가 설치했던 방식대로 설명을 진행하겠습니다.


Python 3.6.0(포스트 기준 버전) 설치 -> Python 2.7.13(포스트 기준 버전)설치


[그림 01] Python 2, 3 설치 후 환경변수 모습


[그림 01]의 환경변수에는 Python27밖에 없는 것을 볼 수 있습니다.

Python 3을 설치할 때는 [환경변수에 추가하시겠습니까]와 같은 설정을 추가하라고 되어 있습니다.

그러면 환경변수에는 추가가 되었다는 말인데... 어디있는치 찾아보니 [그림 02]와 같이 사용자 변수에 존재했습니다.

[그림 02] 사용자 변수에 존재하는 Python3


사용자 변수에는 Python 3의 위치가 존재하는데, 위치는 다음과 같습니다.

%USERPROFILE%\AppData\Local\Programs\Python\Python36-32


아무런 설정 없이 python 2.7과 python 3을 구분하는 것은 cmd 명령으로 다음과 같이 구분되어 있습니다.


 python 2 실행 

 python 

 python 2 백그라운드 실행 

 pythonw

 python 3 실행

 py

 python 3 백그라운드 실행

 pyw


다음 명령을 실행하는 것은 C:\Windows에 다음과 같은 파일이 있기 때문입니다.

그렇다면 우리는 C:\Windows 아래에 있는 파일을 다음과 같이 수정해줄 수 있습니다.


python.exe => python2.exe

pythonw.exe => pythonw2.exe


py.exe => python3.exe

pyw.exe => pythonw3.exe


만약 다음과 같은 파일이 없다면 mklink로 파일을 생성해줄 수 있습니다.

mklink c:\Windows\python2.exe [파이썬 2폴더에 python.exe가 있는 위치]

mklink c:\Windows\python3.exe [파이썬 3폴더에 python.exe가 있는 위치]

[그림 03] python2, python3 명령 실행


저는 python2와 python3를 구분하기 위해서 가능하면 cmd로 실행합니다... 구분을 쉽게 하고 명확하게 하기 위합입니다. *^^*




[그림 01] Problem 003 문제


문제를 살펴보면 다음과 같습니다.

문제 이름 : 가장 큰 소수는?

문제 내용 : 13195의 소수들은 5, 7, 13 그리고 29로 이루어져 있습니다. 즉, 5*7*13*29가 13195라는 것입니다. 그렇다면 600851475143에서 가장 큰 소수는 무엇입니까?


우리는 다음과 같은 조건을 가진다는 것을 알 수 있습니다.

1. 600851475143이라는 숫자는 소수의 곱으로만 이루어져 있음

2. 소수를 구하여 위의 숫자를 나누어주고, 그 중 가장 큰 녀석을 찾아내야 함


이제 소스코드를 작성해보도록 합시다.

#Project Euler Problem 003
#Python 3 version source

#13195 는 5 x 7 x 13 x 29라는 소수로 이루어져 있다. 600851475143에서 가장 큰 소수는 무엇인가?

#getPrime == 소수 구하기 함수
def GetPrimeAndDivision(Value):
	primeList = [2]           #소수 리스트 생성
	divideList = list()       #나누어지는 소수의 리스트
	num = 3                   #3부터 소수인지 검사함
	
	while(num <= Value):
		for x in primeList:
			if(num % x == 0):         #소수로 나누었을 대 나누어지면 소수 아님
				break
			elif(x == primeList[-1]): #소수리스트의 끝원소로도 나누어지지 않으면 소수
				primeList.append(num)	            #구한 소수를 소수 리스트에 추가
				if Divide_LimitValue(num, Value): #참 값이 반환되면 실행
					divideList.append(num)
					Value = Value / num
				break
		num += 1
	
	return divideList
	
def Divide_LimitValue(PrimeNum, LimitValue): #소수로 값을 나눠보도록 함
	Answer = LimitValue % PrimeNum
	if Answer == 0: #소수가 나누어 떨어지면 나누어지는 소수 값을 반환
		return PrimeNum
	else:
		return 0
		
if __name__ == "__main__":
	Main_LimitValue = 600851475143
	Main_FactorList = list()
	i = 0
	
	Main_PrimeList, Main_DivideList = GetPrimeAndDivision(Main_LimitValue)
	print("Main Divided List : ", Main_DivideList)


메인에서는 소수로 곱해진 값을 정의해주었고, 함수를 하나 실행할 뿐입니다.

그리고 GetPrimeAndDivision에서는 한계값을 받아오고, 그 값보다 작은 소수를 찾아내어 Divide_LimitValue를 통해서 나누어떨어지는지 확인합니다.

확인이 완료되면, 그 값을 divideList에 append해주고, 600851475143을 나누어지는 소수로 나누어 다음 값을 알아내도록 합니다.

완료가 되면, Main_DivideList로 받아 출력하도록 하였습니다.


저보다 굉장한 사람은 늘 있습니다.

참고하고자 소스를 가져왔습니다.. 흑흑 비교가 많이 되지만 이를 참고하여 점점 더 발전해야지요.

출처 : http://www.s-anand.net/euler.html

n = 600851475143
i = 2

while i * i < n:
    while n % i == 0:
        n = n / i
    i = i + 1
    
print(n)

막상 보니까 겁나 짧네요. 헛웃음이 슬쩍 저를 찌르고 들어갑니다.

저는 비로소 이 소스를 보고 이렇게 될 뿐이었습니다.

생각해보니 그렇습니다.

어차피 n에 저장되어 있는 값은 소수들의 곱으로 이루어져 있습니다. 즉, 나누어 떨어진다면, 그 숫자는 소수라는 것입니다.

그렇다면, 그냥 나누어 떨어지기만 하는 것을 쭉 골라내고, 만약 더 이상 나누어지지 않으면 출력하면 됩니다.

헉헉... 쩐당... 기존의 조건을 활용하다니. 닫인 머리뚜껑을 열어야 합니다 흑흑!!!


[그림 01] Problem 002 문제

문제를 살펴보면 다음과 같습니다.

문제 이름 : 짝수 피보나치 숫자들

문제 내용 : 각 단계마다 피보나치가 생성되는데, 피보나치의 다음 단계는 두 개의 단계(번째)를 더하여 생성됩니다. 1과 2로 시작하여 10단계를 생성해보면 다음과 같이 생성됩니다.

1, 2, 3, 5, 8, 13, 21, 34, 55, 89 ....

이제 이를 고려하여 4,000,000(4백만, 4million)을 넘지 않는 각 단계를 계속 생성할 때, 생성된 값이 짝수들인 단계를 모두 더한 값을 구하십시오.


우리는 다음과 같은 조건을 가진다는 것을 알 수 있습니다.

1. 피보나치의 원리를 이용하여 다음 단계를 계속 생성함

2. 생성된 단계가 400만을 넘지 않아야 함

3. 생성된 값 중 짝수인 것을 모두 더해야 함


이제 소스코드를 작성해보도록 합시다.


#Project Euler Problem 002
#Python 3 version source
#even-valued terms' Sum value --> 짝수의 값으로 나오는 term을 모두 더함

def Define_Fibonacci(ex_number, number):	#피보나치 생성함수
	next_number = ex_number + number
	return number, next_number

def Even_Value_Sum(Fibo_list):		        #짝수 값을 구분하여 더함
	Even_Fibo_Sum = 0
	for i in range(len(Fibo_list)):
		if Fibo_list[i] % 2 == 0:
			Even_Fibo_Sum += Fibo_list[i]
	return Even_Fibo_Sum

if __name__ == "__main__":
	Fibonacci_Limit = 4000000       #피보나치 값이 넘지 않아야 할 한계값
	Fibonacci_Sum = 0               #피보나치 짝수 값을 더할 변수
	Fibonacci_List= [1,2]           #피보나치 배열
	i = 0
	
	while True:
		main_num, main_next_num = Define_Fibonacci(Fibonacci_List[i],Fibonacci_List[i+1])
		if main_next_num <= Fibonacci_Limit: #피보나치 값이 한계값을 넘지 않으면 피보나치 배열에 추가함
			Fibonacci_List.append(main_next_num)
		else:	                               #400만을 넘는 값이 생성되면 출력하고 종료
			print("Even Fibo Sum : ", Even_Value_Sum(Fibonacci_List))
			break
		i += 1                 #While문의 횟수를 표시
	#print(Fibonacci_List)   #피보나치 배열을 출력할 수 있음

위의 소스는 문제를 해결하는 소스입니다.

먼저 메인에서는 한계값을 지정한 변수, 더해줄 변수, 피보나치 배열을 선언합니다.

그리고 While 무한 반복으로 피보나치 단계 중 400만이 넘는 값이 나오기 전까지 반복해줍니다.

Define_Fibonacci를 통해 다음 피보나치 단계를 생성하고, Even_Value_Sum을 통해 피보나치 리스트에 있는 값 중 짝수 값을 골라 더해주고, 이를 반환해줍니다.


그리고 이외에 홀수, 그리고 피보나치 배열의 모든 값을 더하는 기능을 추가한 소스는 다음과 같습니다.


#Project Euler Problem 002
#Python 3 version source
#even-valued terms' Sum value --> 짝수의 값으로 나오는 term을 모두 더함

def Define_Fibonacci(ex_number, number):
	next_number = ex_number + number
	return number, next_number

def Even_Value_Sum(Fibo_list):
	Even_Fibo_Sum = 0
	for i in range(len(Fibo_list)):
		if Fibo_list[i] % 2 == 0:
			Even_Fibo_Sum += Fibo_list[i]
	return Even_Fibo_Sum

def Odd_Value_Sum(Fibo_list):
	Odd_Fibo_Sum = 0
	for i in range(len(Fibo_list)):
		if Fibo_list[i] % 2 == 1:
			Odd_Fibo_Sum += Fibo_list[i]
	return Odd_Fibo_Sum
	
def Whole_Value_Sum(Fibo_list):
	Whole_Fibo_Sum = 0
	for i in Fibo_list:
		Whole_Fibo_Sum += i
	return Whole_Fibo_Sum
	
if __name__ == "__main__":
	Fibonacci_Limit = 4000000
	Fibonacci_Sum = 0
	Fibonacci_List= [1,2]
	i = 0
	
	while True:
		main_num, main_next_num = Define_Fibonacci(Fibonacci_List[i],Fibonacci_List[i+1])
		if main_next_num <= Fibonacci_Limit:
			Fibonacci_List.append(main_next_num)
		else:
			print("Even Fibo Sum : ", Even_Value_Sum(Fibonacci_List))
			print("Odd Fibo Sum  : ", Odd_Value_Sum(Fibonacci_List))
			print("Whole Fibo Sum: ", Whole_Value_Sum(Fibonacci_List))
			break
		i += 1
	#print(Fibonacci_List)	


늘 느끼는 거지만, 저보다 잘하는 사람은 늘 있습니다.
출처 : http://www.s-anand.net/euler.html


cache = {}     #dict == dictionary 형태의 타입 // type(cache) == 'dict'
def fib(n):
	cache[n] = cache.get(n, 0) or (n <= 1 and 1 or fib(n-1) + fib(n-2))
	return cache[n]

n = 0
i = 0

while fib(i) <= 4000000:
    if not fib(i) % 2: n = n + fib(i)
    i = i + 1

print(n)


[그림 01] Problem 001의 문제


문제를 살펴보면 다음과 같습니다.


문제 이름 : 3과 5의 배수

문제 내용 : 만약 10 미만의 숫자 중에서 3이나 5의 배수인 것을 골라보았을 때, 우리는 3, 5, 6 그리고 9를 얻을 수 있습니다. 그리고 그들의 합은 23입니다. 3과 5의 배수 중 1000 미만의 숫자를 골라서 그들의 합을 구하십시오.


즉 우리는 다음과 같은 조건을 가진다는 것을 알 수 있습니다.

1. 3과 5의 배수를 모두 골라내야 함

2. 골라낸 배수들을 모두 더해야 함

3. 골라낸 배수들은 절대 1000이상이 되어서는 안 됨


이제 소스를 작성해보도록 합시다.

#project euler Problem 001
#python 3 version source
def find_multiples(number): #3과 5의 배수를 구하는 함수
	temp01 = number % 3
	temp02 = number % 5
	
	if temp01 == 0 or temp02 == 0:
		return number
	else:
		return 0

if __name__ == "__main__":
	limit = 1000 #한계 범위
	answer = 0
	
	for i in range(3,limit): #3에서부터 한계범위
		answer += find_multiples(i)
		
	print(answer)

find_multiples 함수는 숫자를 인자값으로 받아서 이 값이 3의 배수이거나 5의 배수인지를 검사한 후 만약 참일 때 리턴하여 더할 수 있도록 하였고, 만약 거짓일 경우 0을 더하는(더하나 마나 하는 행위) 기능을 합니다.

그리고 모두 더해진 값을 print()로 출력하게 됩니다.


저보다 잘한 사람은 늘 있습니다.

저는 그 분들의 소스를 참고하고자 합니다.

출처 : http://www.s-anand.net/euler.html

n = 0
for i in range(1,1000):
	if not i % 5 or not i % 3:
		n = n + i
print(n)


맞아..! not이 있었어어어...!!!

P.S python 3.0에서는 xrange가 사라졌습니당. 기존의 range()의 범위가 들쭉날쭉하던 것을 python 3.x에서는 xrange == range로 바꾸었습니다.


+ Recent posts