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: breakinlining μ νμ§ μμμμλ 6.4μ΄λλ₯Ό κΈ°λ‘νμλ€. inlining μ νλ©΄ 5.7μ΄λλ₯Ό κΈ°λ‘νλ€.
5. μ΅μ ν 3μ°¨ : PyRex ¶
PyRex λ Python μ½λλ₯Ό C μ½λλ‘ μ νν΄μ€λ€. μ΄λ₯Ό μ΄μ©, C λͺ¨λλ‘ λ§λ€μ΄ μ»΄νμΌνκ³ κ²°κ³Όλ₯Ό μ€ν. μμΈλ‘ 7.x λλ‘, PsyCo λ₯Ό μΌμλλ³΄λ€ μ€νλ € μ±λ₯μ΄ λ¨μ΄μ‘λ€. C μ½λλ₯Ό 보λ μ¬κ±Έ. μ ν μμλ³Όμκ° μλ μ½λλ€. μ°¨λΌλ¦¬ κΉ¨λνκ² μ§μ μμ±ν΄μ£Όλκ² μ±λ₯ν₯μ μμΌλ‘λ μ 리νκ² λ€λ μκ°.
6. ν μΌ λλΉ λλμ ¶
- μ΄μ μλ λλ μ μ΄μ§λ§, νκ°μ§ λ¬Έμ λ₯Ό μμ£Ό κΉκ² νμ΄λ³΄λ €κ³ νλ κ²λ μ¬λ¬κ°μ§λ‘ νμ΅μ΄ λλ€.
- κ³Όμ μ λν κΈ°λ‘. 무μΈκ° μ κ΄λ¦¬κ° μλλ μν©μ΄ μ€λλ λ, ν μΌλ€κ³Ό μ¬μ€λ€μ κΈ°λ‘ν΄λ³΄λ κ²μ μλΉν λμμ΄ λλ€.
7. λ νμμΌλ©΄ νλ μ . λ³΄μ ¶
- PrimeNumber μ μ΅μ νμ λν΄μ. κΈ°μ‘΄μ μλ μκ³ λ¦¬μ¦μ΄ μλ, μ§μ μ΅μ νλ₯Ό μλν΄λ³΄λ κ²μΌλ‘ λ λ§μ κ²μ νμ΅ν μ μμΌλ¦¬λΌ. μ΄λ²μ κ²½μ°λ 2μκ° μμ
μΌλ‘ κ³νμ μ‘μλ κ΄κ³λ‘.
- μ΄λ¬ν λ¬Έμ μ κ²½μ° νΉμ μκ³ λ¦¬μ¦μ μμ£Ό μ΅μ ν λ κ²°κ³Όλ¬Όμ΄ λ΅μ΄κΈ° 보λ€λ, 무μΈκ° λ€λ₯Έ μ°¨μμμ λ΄€μλ λ무λ 빨리 λ΅μ΄ λμ€κ² λλ κ²½μ°μΌκ²μ΄λΌ μΆμΈ‘. μ ν λ€λ₯Έ λ°©λ²μ μ΄νλ‘μΉλ μκ°ν΄λ³΄κ³ μΆλ€.