In short, because my English is terrible; -)
Forall n >= 1, C(n) = n/2 if n even, 3*n + 1 if n odd
You can calculate several consecutive iterations at once.
kth iteration of a number ending in k 0
bits:
C^k(a*2^k) = a
(2k) th iteration of a number ending in k 1
bits:
C^(2k)(a*2^k + 2^k - 1) = a*3^k + 3^k - 1 = (a + 1)*3^k - 1
Cf. formula for Wikipedia article (in French) ; see also my site (in French) and the tnp1 module in my Python DSPython package.
Combine the following code with the memoization technique explained by Niklas B:
#!/usr/bin/env python # -*- coding: latin-1 -*- from __future__ import division # Python 3 style in Python 2 from __future__ import print_function # Python 3 style in Python 2 def C(n): """Pre: n: int >= 1 Result: int >= 1""" return (n//2 if n%2 == 0 else n*3 + 1) def Ck(n, k): """Pre: n: int >= 1 k: int >= 0 Result: int >= 1""" while k > 0: while (n%2 == 0) and k: # n even n //= 2 k -= 1 if (n == 1) and k: n = 4 k -= 1 else: nb = 0 while (n > 1) and n%2 and (k > 1): # n odd != 1 n //= 2 nb += 1 k -= 2 if n%2 and (k == 1): n = (n + 1)*(3**(nb + 1)) - 2 k -= 1 elif nb: n = (n + 1)*(3**nb) - 1 return n def C_length(n): """Pre: n: int >= 1 Result: int >= 1""" l = 1 while n > 1: while (n > 1) and (n%2 == 0): # n even n //= 2 l += 1 nb = 0 while (n > 1) and n%2: # n odd != 1 n //= 2 nb += 1 l += 2 if nb: n = (n + 1)*(3**nb) - 1 return l if __name__ == '__main__': for n in range(1, 51): print(n, ': length =', C_length(n))
source share