Hacker News new | ask | show | jobs
by nonsequitur 5128 days ago
Take some of that time to figure out the math and the code becomes trivial:

  for (n = 1; n <= 20; n++) {
    window.alert(n << (n-1))
  }
A short explanation: http://mathbin.net/98435
2 comments

A shorter explanation with no binomial coefficients in it: Write down those 2^n numbers once in order, and once in reverse order, and pair them off. Note that each x gets paired with 2^(n-1) XOR x. So each number and its partner have exactly n 1-bits between them. In other words, twice the number we're looking for is 2^n.n; so the number we're looking for is 2^(n-1).n.

(More informally: Each bit is 0 half the time and 1 half the time, because you can pair off x and 2^(n-1) XOR x. Therefore the total number of 1-bits is half the total number of bits, QED.)

Dude, thanks for that! I really enjoyed the closed form solution, though there is absolutely no way I could have come up with that under time-pressure in a codesprint.

My solution was rather trivial: The base case is 2 bit numbers, which are 00,01,10 and 11. The total number of one-bits is 0+1+1+2 = 4.

From then on, I just used recursion.

3 bit numbers are really 2 bit numbers with a '0' prefixed half the time, '1' prefixed the other half of the time. There are 8 3 bit numbers, so you are tacking on the '1' 8/2 = 4 times. So 4 + twicetwobits = 4+2 x 4 = 12.

4 bit numbers are really 3 bit numbers with a '0' prefixed half the time, '1' prefixed the other half of the time. There are 16 4 bit numbers, so you are tacking on the '1' 16/2 = 8 times. So 8 + twicethreebits = 8+2 x 12 = 32

If you write out the recurrence relation, it looks like:

f(n) = 2^(n-1) + 2 x f(n-1)

This seems silly since you can neither define f(n) nor recursively call f(n-1) in Blockly just yet. But if you memoize the f(n-1) results in a list, the recurrence is computable by straight iteration - which is exactly my Blockly solution.