Advertisement
eXFq7GJ1cC

Untitled

Apr 2nd, 2012
162
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.56 KB | None | 0 0
  1. # http://projecteuler.net/problem=145
  2. #
  3. # 20 reversible numbers with 2 digits
  4. # 100 reversible numbers with 3 digits
  5. # 600 reversible numbers with 4 digits
  6. # 0 reversible numbers with 5 digits
  7. # 18000 reversible numbers with 6 digits
  8. # 50000 reversible numbers with 7 digits
  9. # 540000 reversible numbers with 8 digits
  10. # 608720 total reversible numbers
  11.  
  12. # 14s
  13.  
  14. def rev(num, base):
  15.     'Returns num reversed, where base is 10**(num_digits-1)'
  16.     rev = 0
  17.     while num:
  18.         rev += (num % 10) * base
  19.         num /= 10
  20.         base /= 10
  21.     return rev
  22.  
  23. def all_odd(num):
  24.     'Returns 1 if all digits of num are odd, else 0'
  25.     while num:
  26.         if num % 2 == 0:
  27.             return 0
  28.         num /= 10
  29.     return 1
  30.  
  31. def count_reversibles(ndig):
  32.     '''Counts number of reversible numbers are in the range [ 10^ndig-1 , 10^ndig ), ndig >= 2
  33.    
  34.       Optimizations:
  35.       - A candidate number must have an odd digit in the leftmost place and an even digit in the rightmost,
  36.         or vice versa.  odd/odd or even/even would produce an even digit in the ones column of the sum.
  37.       - You only have to check half of the candidate space, because of symmetry.  Consider only candidates
  38.         with an odd digit in the leftmost place and even in the rightmost, and then double the count.
  39.       - You don't have to bother checking candidates with 0 in the ones place, because that would result
  40.         in a reversed number with a leading zero, which per the rules is to be ignored.
  41.       - Incrementing the ones digit results in the sum increasing by 1 + base, e.g.
  42.           1001 + 1001 = 2002
  43.           1002 + 2001 = 3003 = 2002 + 1 + 1000
  44.         This allows computing the reverse once for each group of 10, and then adding. This can be unrolled
  45.         for speed.
  46.    '''
  47.     count = 0
  48.     base = 10**(ndig-1)
  49.     incr = base * 2 + 2
  50.  
  51.     for leftmost_digit in (1, 3, 5, 7, 9):
  52.         i = base * leftmost_digit + 2       # rightmost digit = 2
  53.         stop = base * (leftmost_digit + 1)
  54.         while i < stop:
  55.             sum = i + rev(i, base)
  56.  
  57.             count += all_odd(sum)           # 2
  58.             sum += incr
  59.             count += all_odd(sum)           # 4
  60.             sum += incr
  61.             count += all_odd(sum)           # 6
  62.             sum += incr
  63.             count += all_odd(sum)           # 8
  64.  
  65.             i += 10
  66.    
  67.     return count * 2
  68.  
  69. total = 0
  70. for ndig in range(2, 9):
  71.     c = count_reversibles(ndig)
  72.     total += c
  73.     print c, "reversible numbers with", ndig, "digits"
  74.  
  75. print total, "total reversible numbers"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement