1. Approach ¶
๋งจ ์ฒ์์ ๋ฌธ์ ๋ฅผ ์ฝ๊ณ ๋๋ต ์ฐ์ต์ฅ์ ๋ฌธ์ ์์ ๊ฐ ๋ณ์๋ค์ด ๋ ๋งํ ๋ถ๋ถ๋ค์ ๋ณด์๋ค. ์ผ๋จ ์์๋ค์ ํฉ์ด๋ผ ํ๊ณ , 4์๋ฆฌ์ ํฉ์ด๋ผ๊ณ ํ๋ค. ๋๋ต pseudo code ๋ฅผ ๋ค์์ ๊ฐ์ด ์์ฑํด๋ณด์๋ค.
~cpp
for eachGenNumberFour in GenNumbersFour
isAllPrimeNumber:
print eachGenNumberFour
return
print "impossible"
GenNumbersFour = ํฉ์ด x ์ธ ์ ์กฐํฉ๋ฆฌ์คํธ
ํฉ์ด x ์ธ ์ ์กฐํฉ๋ฆฌ์คํธ์ ๋ํด ์ด๋ป๊ฒ ๊ตฌํ ๊น ๊ถ๋ฆฌํ๋์ค, ์์๋ฆฌ์คํธ๋ฅผ ๋จผ์ ๋ง๋ค๊ณ ์์๋ฆฌ์คํธ์์ 4๊ฐ๋ฅผ ๊ณจ๋ผ์ ํฉ์ ๊ตฌํ ๊ฒฐ๊ณผ๊ฐ n ์ธ์ง๋ฅผ ๋น๊ตํ๋ ๋ฐฉ๋ฒ์ด ๋ ๋นจ๋ฆฌ ๊ตฌํํ ์ ์๊ฒ ๊ตฌ๋๋ผ๋ ์๊ฐ์ด ๋ค์๋ค. ์ด์ ๋ํด์ TDD๋ก ์งํ.
~cpp
class PrimeNumberList:
def __init__(self,aNum):
self.size = aNum
self.resultTable = []
self.createList()
def createList(self):
for i in range(2,self.size+1):
if self.isPrimeNumber(i):
self.resultTable.append(i)
def isPrimeNumber(self,aNum):
for eachValue in self.resultTable:
if aNum % eachValue == 0:
return False
return True
def getList(self):
return self.resultTable
class PrimeNumberTest(unittest.TestCase):
def testPrimeNumber(self):
self.assertEquals([2,], PrimeNumberList(2).getList())
self.assertEquals([2,3], PrimeNumberList(3).getList())
self.assertEquals([2,3,5], PrimeNumberList(5).getList())
self.assertEquals([2,3,5,7,11], PrimeNumberList(12).getList())
self.assertEquals([2,3,5,7,11,13,17,19], PrimeNumberList(20).getList())
๊ทธ๋ฆฌ๊ณ ์์๋ฆฌ์คํธ๋ก๋ถํฐ 4๊ฐ๋ฅผ ๊ตฌํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์๊ฐํ๋ค. ๋งจ ์ฒ์์ ๋ํด์๋ ์ค๋ณต์ ํ์ฉํ๋ฉด ์๋๋ ์ค ์๊ณ ๊ตฌํํ์๋ค. ๊ทธ๋ฌ๋ค๊ฐ ๋ฌธ์ ์์ ์ค๋ณต์ ํ์ฉํ๋ค๋ ์ฌ์ค์ ์๊ณ ๋ค์ ๊ตฌํ.~cpp
def selectionFour(aList):
sizeOfList = len(aList)
for i in range(sizeOfList):
for j in range(sizeOfList):
for k in range(sizeOfList):
for l in range(sizeOfList):
yield [aList[i],aList[j],aList[k],aList[l]]
2. full source ¶
~cpp
from __future__ import generators
import psyco
class PrimeNumberList:
def __init__(self,aNum):
self.size = aNum
self.resultTable = []
self.createList()
def createList(self):
for i in range(2,self.size+1):
if self.isPrimeNumber(i):
self.resultTable.append(i)
def isPrimeNumber(self,aNum):
for eachValue in self.resultTable:
if aNum % eachValue == 0:
return False
return True
def getList(self):
return self.resultTable
def selectionFour(aList):
sizeOfList = len(aList)
for i in range(sizeOfList):
for j in range(sizeOfList):
for k in range(sizeOfList):
for l in range(sizeOfList):
yield [aList[i],aList[j],aList[k],aList[l]]
def main():
n = int(raw_input('input number : '))
primeNumberList = PrimeNumberList(n)
for eachPrimeNumberSeq in selectionFour(primeNumberList.getList()):
if sum(eachPrimeNumberSeq) == n:
print eachPrimeNumberSeq
return
print "Impossible"
if __name__=="__main__":
#unittest.main(argv=('','-v'))
psyco.full()
main()
3. ๋ฌธ์ ์ - 4์ด ์ด๋ด์ ๋ต์ด ๋์ค์ง ์๋๋ค. ¶
์คํ์ 10000000 ๊ฐ ๋ด์์ 4์ด ์ด๋ด์ ๋ต์ด ๋์์ผ ํ๋ค. ์ด์ ๋ํด์ ํ์ฌ์ ๋ณ๋ชฉ์ง์ ์ ๋ํด profiling ์ ํด ๋ณด์๋ค.
PrimeNumber๋ฅผ ์ฐธ๊ณ , ์ต์ ํ๋ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์์ ํ์๋ค. ๊ทธ๋ฆฌ๊ณ ์ญ์ psyco ๋ฅผ ์ด์ฉํ์๋ค. ๊ทธ ๊ฒฐ๊ณผ, 10000000 ๊ธฐ์ค 10์ด. ๊ธฐ์กด ์๊ณ ๋ฆฌ์ฆ์ ๊ฒฝ์ฐ 50000๋ฒ ๊ธฐ์ค 24์ด ์ด์.
~cpp
C:\WINDOWS\system32\cmd.exe /c python SummationOfFourPrimes.py
input number : 10000
[2, 2, 23, 9973]
21065 function calls in 6.387 CPU seconds
Random listing order was used
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.075 0.075 1.201 1.201 summationoffourprimes.py:13(createList)
0 0.000 0.000 profile:0(profiler)
1 5.103 5.103 6.387 6.387 summationoffourprimes.py:88(main)
1 0.000 0.000 1.201 1.201 summationoffourprimes.py:8(__init__)
9999 1.126 0.000 1.126 0.000 summationoffourprimes.py:18(isPrimeNumber)
1 0.000 0.000 0.000 0.000 summationoffourprimes.py:24(getList)
11061 0.083 0.000 0.083 0.000 summationoffourprimes.py:79(selectionFour)
1 0.000 0.000 6.387 6.387 <string>:1(?)
~cpp
C:\WINDOWS\system32\cmd.exe /c python SummationOfFourPrimes.py
input number : 50000
[2, 2, 3, 49993]
60269 function calls in 24.926 CPU seconds
Random listing order was used
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.428 0.428 19.348 19.348 summationoffourprimes.py:13(createList)
0 0.000 0.000 profile:0(profiler)
1 5.492 5.492 24.923 24.923 summationoffourprimes.py:88(main)
1 0.000 0.000 19.348 19.348 summationoffourprimes.py:8(__init__)
49999 18.920 0.000 18.920 0.000 summationoffourprimes.py:18(isPrimeNumber)
1 0.000 0.000 0.000 0.000 summationoffourprimes.py:24(getList)
10265 0.083 0.000 0.083 0.000 summationoffourprimes.py:79(selectionFour)
1 0.003 0.003 24.926 24.926 <string>:1(?)
Hit any key to close this window...
๋๋ถ๋ถ์ ์๊ฐ์ ์์ํ
์ด๋ธ์ ์์ฑํ๋ ๋ถ๋ถ์ด ๋๋ค. ๊ทธ๋์ ์ด ๋ถ๋ถ์ ๋ํด์ ~cpp
C:\WINDOWS\system32\cmd.exe /c python SummationOfFourPrimes.py
input number : 10000
[2, 2, 23, 9973]
11067 function calls in 5.417 CPU seconds
Random listing order was used
ncalls tottime percall cumtime percall filename:lineno(function)
0 0.000 0.000 profile:0(profiler)
1 0.000 0.000 0.000 0.000 summationoffourprimes.py:48(getList)
1 0.000 0.000 5.417 5.417 <string>:1(?)
1 0.000 0.000 0.013 0.013 summationoffourprimes.py:36(createList)
1 0.000 0.000 0.013 0.013 summationoffourprimes.py:31(__init__)
11061 0.094 0.000 0.094 0.000 summationoffourprimes.py:103(selectionFour)
1 5.309 5.309 5.416 5.416 summationoffourprimes.py:112(main)
1 0.013 0.013 0.013 0.013 summationoffourprimes.py:8(prime2)
Hit any key to close this window...
~cpp
C:\WINDOWS\system32\cmd.exe /c python SummationOfFourPrimes.py
input number : 50000
[2, 2, 3, 49993]
10271 function calls in 7.878 CPU seconds
Random listing order was used
ncalls tottime percall cumtime percall filename:lineno(function)
0 0.000 0.000 profile:0(profiler)
1 0.000 0.000 0.000 0.000 summationoffourprimes.py:48(getList)
1 0.002 0.002 7.878 7.878 <string>:1(?)
1 0.002 0.002 0.090 0.090 summationoffourprimes.py:36(createList)
1 0.000 0.000 0.090 0.090 summationoffourprimes.py:31(__init__)
10265 0.098 0.000 0.098 0.000 summationoffourprimes.py:103(selectionFour)
1 7.688 7.688 7.876 7.876 summationoffourprimes.py:112(main)
1 0.088 0.088 0.088 0.088 summationoffourprimes.py:8(prime2)
Hit any key to close this window...
์ต์ ํ ์ดํ 50000๋ฒ ๊ธฐ์ค์ผ๋ก๋ ๋ณ๋ชฉ์ ๋ํ ๋ณ๋ณ๋ ฅ์ด ์๋ค.~cpp
C:\WINDOWS\system32\cmd.exe /c python SummationOfFourPrimes.py
input number : 1000000
[2, 2, 13, 999983]
470994 function calls in 26.768 CPU seconds
Random listing order was used
ncalls tottime percall cumtime percall filename:lineno(function)
0 0.000 0.000 profile:0(profiler)
1 0.000 0.000 0.000 0.000 summationoffourprimes.py:48(getList)
1 0.040 0.040 26.768 26.768 <string>:1(?)
1 0.062 0.062 2.708 2.708 summationoffourprimes.py:36(createList)
1 0.000 0.000 2.708 2.708 summationoffourprimes.py:31(__init__)
470988 5.244 0.000 5.244 0.000 summationoffourprimes.py:103(selectionFour)
1 18.777 18.777 26.728 26.728 summationoffourprimes.py:112(main)
1 2.646 2.646 2.646 2.646 summationoffourprimes.py:8(prime2)
Hit any key to close this window...
์ฌ๊ธฐ์ selectionFour ์ ๊ฒฝ์ฐ๋ percall ์ ๊ฑธ๋ฆฌ๋ ์๊ฐ์ ์ ๋ค. ํ์ง๋ง, call ํ์ ์์ฒด๊ฐ 470988 ๋ฒ์ผ๋ก ๋ง๋ค. ์ด ๋ถ๋ถ์ ๋ํด์ ์ผ์ข
์ inlining ์ ํ์๋ค.
~cpp
C:\WINDOWS\system32\cmd.exe /c python SummationOfFourPrimes.py
input number : 1000000
(2, 2, 13, 999983)
6 function calls in 16.671 CPU seconds
Random listing order was used
ncalls tottime percall cumtime percall filename:lineno(function)
0 0.000 0.000 profile:0(profiler)
1 0.000 0.000 0.000 0.000 summationoffourprimes.py:48(getList)
1 13.736 13.736 16.540 16.540 summationoffourprimes.py:121(main2)
1 0.067 0.067 2.804 2.804 summationoffourprimes.py:36(createList)
1 2.738 2.738 2.738 2.738 summationoffourprimes.py:8(prime2)
1 0.131 0.131 16.671 16.671 <string>:1(?)
1 0.000 0.000 2.804 2.804 summationoffourprimes.py:31(__init__)
Hit any key to close this window...
10000000 ๊ฑด์ ๋ํด์๋ 7.49 ์ด ๊ธฐ๋ก (profiler ๋ฅผ ์ด์ฉํ ๊ฒฝ์ฐ ์๋์ ํ๊ฐ ์๊ธฐ ๋๋ฌธ์ profiler ๋ฅผ ๋๊ณ psyco ๋ง์ผ๋ก ์คํ)4. ์ต์ ํ 2์ฐจ : ๋ฌธ์ ์์ญ์ ์ค์ด๊ธฐ ¶
๋น๋ก inlining ์ ์์ผฐ์ง๋ง ์ฌ์ ํ ๊ฒ์ selectionFour ๋ถ๋ถ์ด๋ค. selectionFour ๊ฐ ์คํ๋๋ ๊ฒฝ์ฐ์ ์ต์
์ ๊ฒฝ์ฐ๋ (n ๊น์ง์ ์์๊ฐฏ์)^4 ๊ฐ ๋๋ค. ์ด๋ฅผ ์ข ๋ smart ํ๊ฒ ํ ๋ฐฉ๋ฒ์ด ์์๊น.
์์์ ๊ด๋ จํ์ฌ ์ข ๋ ๋๋ํ๊ฒ ๊ฒ์ํ ๋ฐฉ๋ฒ์ด ์กด์ฌํ๋ฆฌ๋ผ ์๊ฐํ๋ค.
๊ฐ์ฅ ๊ฐ๋จํ ์์ด๋์ด๋ก, 4๋ฒ์งธ ๊ฐ์ ๋ํด์๋ ๋ฐ๋ก ๊ณ์ฐ์ ํ ์๊ฐ ์๊ฒ ๋ค.
์์์ ๊ด๋ จํ์ฌ ์ข ๋ ๋๋ํ๊ฒ ๊ฒ์ํ ๋ฐฉ๋ฒ์ด ์กด์ฌํ๋ฆฌ๋ผ ์๊ฐํ๋ค.
๊ฐ์ฅ ๊ฐ๋จํ ์์ด๋์ด๋ก, 4๋ฒ์งธ ๊ฐ์ ๋ํด์๋ ๋ฐ๋ก ๊ณ์ฐ์ ํ ์๊ฐ ์๊ฒ ๋ค.
selectionFour ๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์์ ํ์๋ค.
~cpp
def selectionFour(aList,aNum):
sizeOfList = len(aList)
for i in range(sizeOfList):
for j in range(sizeOfList):
for k in range(sizeOfList):
for l in range(sizeOfList):
expectedLastValue = aNum-(aList[i]+aList[j]+aList[k])
if expectedLastValue in aList:
yield [aList[i],aList[j],aList[k],expectedLastValue]
else:
break
inlining ์ ํ์ง ์์์์๋ 6.4์ด๋๋ฅผ ๊ธฐ๋กํ์๋ค. inlining ์ ํ๋ฉด 5.7์ด๋๋ฅผ ๊ธฐ๋กํ๋ค.5. ์ต์ ํ 3์ฐจ : PyRex ¶
PyRex ๋ Python ์ฝ๋๋ฅผ C ์ฝ๋๋ก ์ ํํด์ค๋ค. ์ด๋ฅผ ์ด์ฉ, C ๋ชจ๋๋ก ๋ง๋ค์ด ์ปดํ์ผํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์คํ. ์์ธ๋ก 7.x ๋๋ก, PsyCo ๋ฅผ ์ผ์๋๋ณด๋ค ์คํ๋ ค ์ฑ๋ฅ์ด ๋จ์ด์ก๋ค. C ์ฝ๋๋ฅผ ๋ณด๋ ์ฌ๊ฑธ. ์ ํ ์์๋ณผ์๊ฐ ์๋ ์ฝ๋๋ค. ์ฐจ๋ผ๋ฆฌ ๊นจ๋ํ๊ฒ ์ง์ ์์ฑํด์ฃผ๋๊ฒ ์ฑ๋ฅํฅ์ ์์ผ๋ก๋ ์ ๋ฆฌํ๊ฒ ๋ค๋ ์๊ฐ.
6. ํ ์ผ ๋๋น ๋๋์ ¶
- ์ด์ ์๋ ๋๋ ์ ์ด์ง๋ง, ํ๊ฐ์ง ๋ฌธ์ ๋ฅผ ์์ฃผ ๊น๊ฒ ํ์ด๋ณด๋ ค๊ณ ํ๋ ๊ฒ๋ ์ฌ๋ฌ๊ฐ์ง๋ก ํ์ต์ด ๋๋ค.
- ๊ณผ์ ์ ๋ํ ๊ธฐ๋ก. ๋ฌด์ธ๊ฐ ์ ๊ด๋ฆฌ๊ฐ ์๋๋ ์ํฉ์ด ์ค๋๋ ๋, ํ ์ผ๋ค๊ณผ ์ฌ์ค๋ค์ ๊ธฐ๋กํด๋ณด๋ ๊ฒ์ ์๋นํ ๋์์ด ๋๋ค.
7. ๋ ํ์์ผ๋ฉด ํ๋ ์ . ๋ณด์ ¶
- PrimeNumber ์ ์ต์ ํ์ ๋ํด์. ๊ธฐ์กด์ ์๋ ์๊ณ ๋ฆฌ์ฆ์ด ์๋, ์ง์ ์ต์ ํ๋ฅผ ์๋ํด๋ณด๋ ๊ฒ์ผ๋ก ๋ ๋ง์ ๊ฒ์ ํ์ตํ ์ ์์ผ๋ฆฌ๋ผ. ์ด๋ฒ์ ๊ฒฝ์ฐ๋ 2์๊ฐ ์์
์ผ๋ก ๊ณํ์ ์ก์๋ ๊ด๊ณ๋ก.
- ์ด๋ฌํ ๋ฌธ์ ์ ๊ฒฝ์ฐ ํน์ ์๊ณ ๋ฆฌ์ฆ์ ์์ฃผ ์ต์ ํ ๋ ๊ฒฐ๊ณผ๋ฌผ์ด ๋ต์ด๊ธฐ ๋ณด๋ค๋, ๋ฌด์ธ๊ฐ ๋ค๋ฅธ ์ฐจ์์์ ๋ดค์๋ ๋๋ฌด๋ ๋นจ๋ฆฌ ๋ต์ด ๋์ค๊ฒ ๋๋ ๊ฒฝ์ฐ์ผ๊ฒ์ด๋ผ ์ถ์ธก. ์ ํ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ดํ๋ก์น๋ ์๊ฐํด๋ณด๊ณ ์ถ๋ค.










