<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://mediawiki.zeropage.org/index.php?action=history&amp;feed=atom&amp;title=3N%2B1Problem%2FLeonardong</id>
	<title>3N+1Problem/Leonardong - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://mediawiki.zeropage.org/index.php?action=history&amp;feed=atom&amp;title=3N%2B1Problem%2FLeonardong"/>
	<link rel="alternate" type="text/html" href="https://mediawiki.zeropage.org/index.php?title=3N%2B1Problem/Leonardong&amp;action=history"/>
	<updated>2026-05-14T15:05:11Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.8</generator>
	<entry>
		<id>https://mediawiki.zeropage.org/index.php?title=3N%2B1Problem/Leonardong&amp;diff=26780&amp;oldid=prev</id>
		<title>imported&gt;Unknown at 05:22, 7 February 2021</title>
		<link rel="alternate" type="text/html" href="https://mediawiki.zeropage.org/index.php?title=3N%2B1Problem/Leonardong&amp;diff=26780&amp;oldid=prev"/>
		<updated>2021-02-07T05:22:15Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== 첫째 ==&lt;br /&gt;
 class AOI3nPlus1ProblemRunner:&lt;br /&gt;
     def getMaximumCycleLength(self, aFrom, aTo):&lt;br /&gt;
         max = 0&lt;br /&gt;
         for i in range( aFrom, aTo + 1):&lt;br /&gt;
             cycleLength = self.getCycleLength(i)&lt;br /&gt;
             if max &amp;amp;lt; cycleLength:&lt;br /&gt;
                 max = cycleLength&lt;br /&gt;
         return max&lt;br /&gt;
     def getCycleLength( self, aStart ):&lt;br /&gt;
         n = aStart&lt;br /&gt;
         cycleLength = 1&lt;br /&gt;
         while n is not 1:&lt;br /&gt;
             cycleLength = cycleLength + 1&lt;br /&gt;
             if n % 2 is not 0:&lt;br /&gt;
                 n = 3 * n  + 1&lt;br /&gt;
             else:&lt;br /&gt;
                 n = n / 2&lt;br /&gt;
         return cycleLength&lt;br /&gt;
     def run(self):&lt;br /&gt;
         numFrom = input(&amp;quot;&amp;quot;)&lt;br /&gt;
         numTo = input(&amp;quot;&amp;quot;)&lt;br /&gt;
         print self.getMaximumCycleLength(numFrom, numTo)&lt;br /&gt;
         &lt;br /&gt;
 #########################################################################           &lt;br /&gt;
 import unittest&lt;br /&gt;
 &lt;br /&gt;
 class AOI3nPlus1ProblemTestCase(unittest.TestCase):&lt;br /&gt;
     def setUp(self):&lt;br /&gt;
         self.runner = AOI3nPlus1ProblemRunner()&lt;br /&gt;
     def testGetMaximumCycleLength(self):&lt;br /&gt;
         self.assertEquals( 1, self.runner.getMaximumCycleLength( 1, 1 ) )&lt;br /&gt;
         self.assertEquals( 20, self.runner.getMaximumCycleLength( 1, 10 ) )&lt;br /&gt;
         self.assertEquals( 125, self.runner.getMaximumCycleLength( 100, 200 ) )&lt;br /&gt;
         self.assertEquals( 89, self.runner.getMaximumCycleLength( 201, 210 ) )&lt;br /&gt;
         self.assertEquals( 174, self.runner.getMaximumCycleLength( 900, 1000) )&lt;br /&gt;
     def testGetCycleLength(self):&lt;br /&gt;
         self.assertEquals( 1, self.runner.getCycleLength(1) )&lt;br /&gt;
         self.assertEquals( 5, self.runner.getCycleLength(16) )&lt;br /&gt;
         self.assertEquals( 16, self.runner.getCycleLength(22) )&lt;br /&gt;
 &lt;br /&gt;
 #########################################################################&lt;br /&gt;
 if __name__ == &amp;#039;__main__&amp;#039;: &lt;br /&gt;
 ##    unittest.main()&lt;br /&gt;
     AOI3nPlus1ProblemRunner().run()&lt;br /&gt;
&lt;br /&gt;
== 둘째 ==&lt;br /&gt;
 import psyco&lt;br /&gt;
 MAXIMUM = 10000&lt;br /&gt;
 class AOI3nPlus1ProblemRunner:&lt;br /&gt;
     def __init__(self):&lt;br /&gt;
         self.cycleLens = {}&lt;br /&gt;
     def getMaximumCycleLen(self, aFrom, aTo): &lt;br /&gt;
         maximum = 0&lt;br /&gt;
         for i in range( aFrom, aTo + 1):&lt;br /&gt;
             if self.getCycleLen(i) &amp;amp;gt; maximum:&lt;br /&gt;
                 maximum = self.getCycleLen(i)&lt;br /&gt;
             self.cycleLens[i] = maximum&lt;br /&gt;
         return maximum&lt;br /&gt;
     def getCycleLen( self, n ):&lt;br /&gt;
         if n not in self.cycleLens:&lt;br /&gt;
             self.storeCycleLen( n )&lt;br /&gt;
         return self.getStoredCycleLen(n)&lt;br /&gt;
     def run(self): &lt;br /&gt;
         numFrom = input(&amp;quot;&amp;quot;) &lt;br /&gt;
         numTo = input(&amp;quot;&amp;quot;) &lt;br /&gt;
         print self.getMaximumCycleLen(numFrom, numTo)&lt;br /&gt;
 &lt;br /&gt;
     def storeCycleLen(self, aN):&lt;br /&gt;
         n = aN&lt;br /&gt;
         cycleLen = 1&lt;br /&gt;
         while n is not 1: &lt;br /&gt;
             if n in self.cycleLens:&lt;br /&gt;
                 cycleLen  = cycleLen + self.cycleLens[n] - 1&lt;br /&gt;
                 break&lt;br /&gt;
             cycleLen += 1           &lt;br /&gt;
             if n % 2 is not 0: &lt;br /&gt;
                 n = 3 * n + 1 &lt;br /&gt;
             else:&lt;br /&gt;
                 n = n / 2&lt;br /&gt;
         self.cycleLens[aN] = cycleLen&lt;br /&gt;
     def getStoredCycleLen(self, aN):&lt;br /&gt;
         if aN not in self.cycleLens:&lt;br /&gt;
             return 0&lt;br /&gt;
         return self.cycleLens[aN]&lt;br /&gt;
          &lt;br /&gt;
 #########################################################################            &lt;br /&gt;
 import unittest &lt;br /&gt;
  &lt;br /&gt;
 class AOI3nPlus1ProblemTestCase(unittest.TestCase): &lt;br /&gt;
     def setUp(self):&lt;br /&gt;
         self.runner = AOI3nPlus1ProblemRunner() &lt;br /&gt;
     def testGetMaximumCycleLen(self): &lt;br /&gt;
         self.assertEquals( 1, self.runner.getMaximumCycleLen( 1, 1 ) ) &lt;br /&gt;
         self.assertEquals( 20, self.runner.getMaximumCycleLen( 1, 10 ) ) &lt;br /&gt;
         self.assertEquals( 125, self.runner.getMaximumCycleLen( 100, 200 ) ) &lt;br /&gt;
         self.assertEquals( 89, self.runner.getMaximumCycleLen( 201, 210 ) ) &lt;br /&gt;
         self.assertEquals( 174, self.runner.getMaximumCycleLen( 900, 1000) ) &lt;br /&gt;
     def testGetCycleLen(self): &lt;br /&gt;
         self.assertEquals( 1, self.runner.getCycleLen(1) ) &lt;br /&gt;
         self.assertEquals( 5, self.runner.getCycleLen(16) ) &lt;br /&gt;
         self.assertEquals( 16, self.runner.getCycleLen(22) )&lt;br /&gt;
     def testStoreCycles(self):&lt;br /&gt;
         self.assertEquals( 0, self.runner.getStoredCycleLen(0) )&lt;br /&gt;
         self.runner.storeCycleLen(22)&lt;br /&gt;
         self.assertEquals( 16, self.runner.getStoredCycleLen(22) )&lt;br /&gt;
     def testTime(self):&lt;br /&gt;
          # goal = 999,999 in 4 sec&lt;br /&gt;
         self.runner.getMaximumCycleLen(1,MAXIMUM)&lt;br /&gt;
 ##        self.runner.getCycleLen(MAXIMUM)&lt;br /&gt;
         self.runner.storeCycleLen(MAXIMUM)&lt;br /&gt;
 ######################################################################### &lt;br /&gt;
 if __name__ == &amp;#039;__main__&amp;#039;:&lt;br /&gt;
     psyco.full()&lt;br /&gt;
     unittest.main(argv=(&amp;#039;&amp;#039;,&amp;#039;-v&amp;#039;)) &lt;br /&gt;
 ##    AOI3nPlus1ProblemRunner().run() &lt;br /&gt;
&lt;br /&gt;
== 셋째 ==&lt;br /&gt;
 # 45m after tuning&lt;br /&gt;
 # total = 3h 11m 11s&lt;br /&gt;
 import unittest&lt;br /&gt;
 TEST_MAX =  100000&lt;br /&gt;
 MAX =       1000000&lt;br /&gt;
 ##TEST_MAX =  MAX - 1&lt;br /&gt;
 &lt;br /&gt;
 storedCycleLens = [0] * MAX&lt;br /&gt;
 CUTOFF = 100&lt;br /&gt;
 &lt;br /&gt;
 def preProcessing():&lt;br /&gt;
     i = 1&lt;br /&gt;
     cycleLen = 1&lt;br /&gt;
     while i &amp;amp;lt; MAX:&lt;br /&gt;
         storedCycleLens[i] = cycleLen&lt;br /&gt;
         cycleLen += 1&lt;br /&gt;
         i *= 2&lt;br /&gt;
 &lt;br /&gt;
 def getCycleLen(aN):&lt;br /&gt;
     n = aN&lt;br /&gt;
     result = 1&lt;br /&gt;
     while n != 1:&lt;br /&gt;
         result += 1&lt;br /&gt;
         if n % 2 != 0:&lt;br /&gt;
             result += 1&lt;br /&gt;
             n = (3*n+1) / 2&lt;br /&gt;
         else:&lt;br /&gt;
             n /= 2&lt;br /&gt;
             if n &amp;amp;lt; MAX and\&lt;br /&gt;
                storedCycleLens[n] != 0:            &lt;br /&gt;
                 result += storedCycleLens[n] - 1&lt;br /&gt;
                 break&lt;br /&gt;
 ##            if getStoredCycleLen(n) is not 0:&lt;br /&gt;
 ##                return getStoredCycleLen(n) + result - 1&lt;br /&gt;
     return result&lt;br /&gt;
 def storeCycleLen(aN):&lt;br /&gt;
     storedCycleLens[aN] = getCycleLen(aN)&lt;br /&gt;
 &lt;br /&gt;
 def getStoredCycleLen(aN):&lt;br /&gt;
     if aN &amp;amp;lt; 0 or aN &amp;amp;gt;= MAX:&lt;br /&gt;
         return 0&lt;br /&gt;
     return storedCycleLens[aN]&lt;br /&gt;
 &lt;br /&gt;
 def getMaxCycleLen(aStart, aEnd):&lt;br /&gt;
     maximum = 0&lt;br /&gt;
     interval = 1&lt;br /&gt;
     if CUTOFF &amp;amp;lt; aEnd - aStart:&lt;br /&gt;
         interval = 2&lt;br /&gt;
         if aStart % 2 == 0:&lt;br /&gt;
             aStart -= 1&lt;br /&gt;
     for n in range(aStart, aEnd+1, interval):&lt;br /&gt;
         cycleLen = getCycleLen(n)&lt;br /&gt;
         if maximum &amp;amp;lt; cycleLen:&lt;br /&gt;
             maximum = cycleLen&lt;br /&gt;
         storedCycleLens[n] = cycleLen&lt;br /&gt;
     return maximum&lt;br /&gt;
 &lt;br /&gt;
 class MyTestCase(unittest.TestCase):&lt;br /&gt;
     def testGetCycleLen(self):&lt;br /&gt;
         tests = [(1,1), (9,20), (16,5), (MAX-1,259)]&lt;br /&gt;
         for n, expected in tests:&lt;br /&gt;
             self.assertEquals( expected, getCycleLen(n) )&lt;br /&gt;
         for n in range(MAX-1000, MAX):&lt;br /&gt;
             getCycleLen(n)&lt;br /&gt;
     def testgetMaxCycleLen(self):&lt;br /&gt;
         tests = [(1,1,1),  (1,16,20), (900,1000,174), (1,1000,179)]&lt;br /&gt;
         for start, end, expected in tests:&lt;br /&gt;
             self.assertEquals(expected, getMaxCycleLen( start, end ) )&lt;br /&gt;
     def testStoreCycleLen(self):&lt;br /&gt;
         tests = [(1,1),  (16,5),   (MAX-1,259)]&lt;br /&gt;
         for n, expected in tests:&lt;br /&gt;
             storeCycleLen( n )&lt;br /&gt;
             self.assertEquals( expected , getStoredCycleLen(n) )&lt;br /&gt;
     def testTime(self):&lt;br /&gt;
         getMaxCycleLen(1, TEST_MAX)&lt;br /&gt;
 ##        self.assertEquals(525, getMaxCycleLen(1, MAX))&lt;br /&gt;
 if __name__ == &amp;#039;__main__&amp;#039;:&lt;br /&gt;
     preProcessing()&lt;br /&gt;
 ##    unittest.main()&lt;br /&gt;
     timeTest = MyTestCase(&amp;quot;testTime&amp;quot;)&lt;br /&gt;
     runner = unittest.TextTestRunner()&lt;br /&gt;
     runner.run(timeTest)&lt;br /&gt;
     &lt;br /&gt;
== Thread ==&lt;br /&gt;
절대 쉽지 않은 문제였다. 아직 수행시간이 턱없이 길다. 사전형 멤버를 이용해 계산했던 부분은 저장해두어 다시 쓰도록 하였다. 답답하다. PsyCo라는 모듈을 새롭게 알알게되었다. --[[Leonardong]]&lt;br /&gt;
 싸이코? --[[강희경]]&lt;br /&gt;
&lt;br /&gt;
셋째 코드에서 해본 새로운 시도는 다음과 같다.&lt;br /&gt;
* MAX(100000)개의 원소를 가진 리스트에 계산했던 CycleLength를 저장한다.&lt;br /&gt;
* 3n+1은 항상 짝수이므로 짝수 검사를 한 번 건너뛴다.&lt;br /&gt;
* 2의 제곱수들은 CycleLength를 예상할 수 있으므로 입력 받기 전에 미리 계산해둔다. &lt;br /&gt;
* CycleLength를 구하는 과정에서 n이 짝수일 때만 저장된 값이 있는지를 검사한다.&lt;br /&gt;
* 구하는 범위가 Cutoff보다 크면 시작하는 수가 홀수일 때 CycleLength가 클 것이므로 홀수부터 시작해서 짝수는 무시하고 구한다.&lt;br /&gt;
&lt;br /&gt;
파이선만으로 12초가 걸린다. 새로운 걸 한 번씩 시도할 때마다 시간이 줄어들어 신기했다. 중간에 코드를 고치면서 시간 테스트만 돌리다가 답이 잘못 나오는 코드를 가지고 한동안 작업했었다. 새로운 기능을 추가하면 테스트를 전부 돌려야겠다. --[[Leonardong]]&lt;br /&gt;
&lt;br /&gt;
확신이 가지 않는 cutoff부분을 빼더라도 PsyCo를 쓰면 2초 안에 통과한다. 3시간 동안 10초 정도를 줄였는데, 10분만에 10초를 줄였다. 시간을 줄여야 하는데 정말 수가 안 떠오르면 PsyCo가 꽤 도움이 될 것이다. 남용은 조심해야겠다.--[[Leonardong]]&lt;br /&gt;
----&lt;br /&gt;
[[AOI]], [[3N+1Problem]]&lt;br /&gt;
&lt;/div&gt;</summary>
		<author><name>imported&gt;Unknown</name></author>
	</entry>
</feed>