30 comments

[ 3.1 ms ] story [ 57.2 ms ] thread
I'm getting bigger numbers from a very quick script -- am I missing something?

digitalsum(999^75) = 999

  999^75 = 927708673390001466432161699937587612771693772928727827334425528520027513591277141564708297244305734237029149442895264407211992619276548532187236223108524403378301874096420069132958960388059297398105903507708174617522225074999

  def test(x, y, debug=True):
      num = x**y
      digitalsum = sum(int(a) for a in str(num))
      if x == digitalsum and debug:
          print x, y, num
      return x == digitalsum
  
  for i in range(1,1000):
      for j in range(1,100):
          if test(i, j):
              print i, j
After you calc X^Y, when you will calc X^(Y+1), doesn't it worth to calc using the previous result (X^Y)*X instead of another power X^(Y+1) ?
(comment deleted)
You will find here that the run-time is swamped by the digit breakdown and summing, so that exponentiation versus accumulated product doesn't make a palpable difference.
TXR lisp:

  This is the TXR Lisp interactive listener of TXR 203.
  Quit with :quit or Ctrl-D on empty line. Ctrl-X ? for cheatsheet.
  1> (each ((x (range 2 1000))) ;; 1 is uninteresting
       (each ((y (range 1 100)))
         (let ((z (expt x y)))
           (when (= x (sum (digits z)))
             (put-line `@x @y`)))))
  2 1
  3 1
  4 1
  5 1
  [...]                                                                
  963 69
  964 75
  964 78
  991 71
  999 75
Using successive multiplication instead of exponent operation:

  6> (each ((x (range 2 1000)))
       (each ((y (range 1 100)) ;; needed just for the put-line
              (z [giterate true (op * x) x]))
         (when (= x (sum (digits z)))
           (put-line `@x @y`))))
(Makes no difference; run time is vastly dominated by the contribution of the (sum (digits z)) business.)
@pavel_lishin what algorithm did you use to find these results?
(comment deleted)
All multiples of 9 have digits that add up to 9. This is something kids learn. Why does it work? 9 is 10 - 1, so every time you add another nine the tens digit goes up by one and the ones digit down by one, maintaining the sum of digits. Similar thing happens at three digits, four digits, etc, because 9 < 10, no digit other than the ones digit ever goes up by more than 1, and a 9 becomes a 0 when you carry a one.

That this pattern didn’t swamp the results makes me wonder what kind of bug the author has in the scanning code.

[edit: seems I forgot about situations like 9 x 11 x N, where the digits can add up to 18, 27, etc due to all the 8 and 9 digits, so the algorithm will only find multiples of 9 with lots of small digits in it.]

But not all of the numbers are multiples of 9
The digits add to 0 in mod 9 and he's looking for precisely 9. eg. the sum of digits for 9^3 = 18. That's why you don't see 9's everywhere.
Something lie that happens in all bases e.g. in base 8 all multiples of 7 add up to 7 (if you keep adding), in hex all multiples of f add up to f, and in binary everything eventually adds up to 1 (except zero).

Similarly, in base 8 7^2 is 61 and in hex f^2 is e1.

(n-1)^2 = n^2 - 2*n + 1 = n(n-2) + 1 which in base n is written with n-2 as the fist digit and 1 as the second digit.

The omission is that it's simply recursive.

You might add the digits up to 36, whose digits then add up to 9. Simply reapply to the sum if the sum has more than 1 digit, and you'll still arrive at 9.

Neat, but why is for example 163^16 such a coincidence? It's not that unlikely for digits to add up to 163, and given that you can choose both a base and an exponent, there's bound to be many that work out like this. 163^16 has 36 digits, so expected sum (average expected value of a random digit 0-9 being 4.5) be 162. So that's even pretty close to 163.

Also, why limit this to base 10? Anything with base 10 digits is not the purest possible math imho because it depends on the arbitrary value 10 while you could generalize to any other value.

You can speed up brute force search by starting somewhere before where log10(x^y) * 4.5 is roughly equal to x. For example 2222^140 is 2110 which is close to 2222. Then brute force search from there and you get:

2222 ^ 145

How much does this speed up brute force search, though? You have to actually compute the exponent and digit sums. If I iterate over the powers of N from N^I to N^J, I do something like O((J-I)^2*log N) work doing multiplications the naive way.
Rewrite

    log(x^y)*4.5 = x
    y*log(x)*4.5 = x
    y = x/(4.5*log x)
So picking a random number like 234, we get y=21.94819 and the digit sum of 234^22 == 234. In this case we actually just had to compute one exponent and one digit sum.
Hint: try checking other numbers.
I think one reason to limit to base 10 is because we don't have an arbitrary number of digits, we only have maybe 36 if we use the full alphabet. And it will be difficult for people to follow along with if it's something they aren't used to calculating in. But I'm also guessing the results will become a lot less "rare" which is part of the cool factor here.
Omg, you're not thinking he's done all this by hand, right? People here can code such simple things. And you don't need no specific symbols, just arrays of ints (or any suitable type).
(comment deleted)
That was a pretty great post, if only for this line:

> Extra credit: explain why nobody cares.

(comment deleted)
Just curious how fast brute force search is. Found some larger numbers like 7793^451. Computing the exponents in base 10 seems to be a fairly fast way of doing things, since this is not very hard and radix conversion is a comparatively slow operation.
Hacker News paydirt!

Nerdy enough (and well written enough) that I'll add this blog to my RSS reader. 2019 is off to a good start!