[QUIZ] Happy Numbers (#93)

Since the order of digits in the number doesn't matter, here's code to
generate digits whose numbers are in nondecreasing order. This makes the
"happiest number" test finish almost instantly when the numbers are
generated this way:

   #generates all numbers in the given range whose digits are in
   #nondecreasing order. the order in which the numbers are generated is
   #undefined, so it's possible for 123 to appear before 23, for
   #example.
   def nondec_digits(range,&b)
      yield 0 if range.first<=0
      (1..9).each { |x| noninc_digits_internal(x,x,range,&b) }
   end

   def nondec_digits_internal(last,accum,range,&b)
      (last..9).each do |x|
   iaccum=accum*10+x
   b.call(iaccum) if range.include?(iaccum)
   noninc_digits_internal(x,iaccum,range,&b) if iaccum<=range.last
      end
   end

···

On Sun, 03 Sep 2006 14:31:09 +0000, Ken Bloom wrote:

On Fri, 01 Sep 2006 22:01:41 +0900, Ruby Quiz wrote:

The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this quiz until
48 hours have passed from the time on this message.

2. Support Ruby Quiz by submitting ideas as often as you can:

http://www.rubyquiz.com/

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone
on Ruby Talk follow the discussion. Please reply to the original quiz message,
if you can.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

by Shane Emmons

Write a program that tells whether a given integer is happy. A happy number is
found using the following process: Take the sum of the squares of its digits,
and continue iterating this process until it yields 1, or produces an infinite
loop.

For example the number 7:

  7^2 = 49
  4^2 + 9^2 = 97
  9^2 + 7^2 = 130
  1^2 + 3^2 + 0^2 = 10
  1^2 + 0^2 = 1

If a number is not happy than it is obviously unhappy. Now that you have this
program, what is the largest happy number you can find? What is the happiest
number between 1 and 1,000,000. I define the happiest number as the smallest
number that finds the most other happy numbers with it, i.e. 7 found four other
numbers (49, 97, 130, and 10) making it a rank 4 in happiness.

If you find all these examples trivial, write you program so that it will find
happy numbers in other bases such as base 2 or 16. From there you can extend the
program so that it finds happy bases (other than 2 and 4). A happy bases is a
base where all numbers are happy. Good luck.

require 'enumerator'
require 'jcode'

module Happy
  #1 is a success terminator, from Wolfram's MathWorld
  FAIL_TERMINATORS=[0, 4, 16, 20, 37, 42, 58, 89, 145]

  def internal_happy? number
    return 0 if number==1
    return false if FAIL_TERMINATORS.include? number
    it=Enumerable::Enumerator.new(number.to_s,:each_char)
    newnumber=it.inject(0) { |partial_sum,char| partial_sum+(char.to_i)**2 }
    x=happy?(newnumber)
    return x+1 if x
    return false
  end

  @@memo=Hash.new

  def happy? number
    return @@memo[number] || @@memo[number]=internal_happy?(number)
  end
end

include Happy

#there is no largest happy number because any 10**n is happy for any n.
#since ruby can represent all integers, there's no "largest number I can
#find" (given enough RAM)

#to find the happiest number between 1 and 1_000_000, we use the
#following code (which takes advantage of the memoization that I have
#included)

minhappy=
1_000_001.times do |n|
  puts "Progress #{n}" if n%1000==0
  if x=happy?(n)
    if minhappy==nil or minhappy>n
      minhappy=n
    end
  end
end

puts minhappy.last

#after a long time running, this prints that
#the happiest number is 78999

#by clearing the memoization hash and adding a strategically placed
#puts, I can see this computes happiness for the following
#numbers: [78999, 356, 70, 49, 97, 130, 10, 1]

--Ken Bloom

--
Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/

      return false if (self ^ 4).zero?
      return true if (self ^ 1).zero?

Okay, these two lines were silly; replace with:

return false if self == 4
return true if self == 1

Doesn't this mean that all numbers are happy?

Roland Swingler wrote:

Sorry, should have been 7 ** 2 :slight_smile:

Out of interest, any mathmaticians care to enlighten me as to whether
happy numbers are in any way "useful"?

Considering this thread and the quiz question, I think maybe a psychologist
might be a better person to ask. :slight_smile:

In my experience, "real" mathematicians shudder at the thought that a result
might prove useful.

···

--
Paul Lutus
http://www.arachnoid.com

Out of interest, any mathmaticians care to enlighten me as to whether
happy numbers are in any way "useful"?

As has been said, "real mathematicians" shudder that their work might be useful.

In actuality, sometimes things like this aren't, and sometimes they
are years later. Prime numbers never had much use until recent years,
where they have become very important for encryption.

Maybe happy numbers have a use... just no one knows it yet!

Sander Land wrote:

class Array
  def sum
    inject(0){|a,b| a+b}
  end
end

For a little more speed, try instead:

class Array
  def sum
    inject{ |a,b| a+b }
  end
end

Peter Hickman wrote:

Doesn't this mean that all numbers are happy?

Do it by hand for 3...

Here's some further reading for those still confused:

James Edward Gray II

···

On Sep 1, 2006, at 8:41 AM, Peter Hickman wrote:

Doesn't this mean that all numbers are happy?

Matthew Moss wrote:

Out of interest, any mathmaticians care to enlighten me as to whether
happy numbers are in any way "useful"?

As has been said, "real mathematicians" shudder that their work might be
useful.

In actuality, sometimes things like this aren't, and sometimes they
are years later. Prime numbers never had much use until recent years,
where they have become very important for encryption.

Another example is non-Euclidean geometry, which was an impractical, exotic
plaything for about 100 years, until general relativity came along and
required it. Without non-Euclidean geometry, Einstein wouldn't have been
able to express GR at all.

Prior to that, few would have guessed that the universe isn't Euclidean.

···

--
Paul Lutus
http://www.arachnoid.com

thread about it, was there not :wink:

class Array
  def sum
     s=0
     each{ | e | s+= e }
     s
  end
end

Cheers
Robert

···

On 9/3/06, Phrogz <gavin@refinery.com> wrote:

Sander Land wrote:
> class Array
> def sum
> inject(0){|a,b| a+b}
> end
> end

For a little more speed, try instead:

class Array
  def sum
    inject{ |a,b| a+b }
  end
end

The following is about three times faster on my box (there was a recent

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

Is that really so much faster? Worth breaking on empty arrays?
Just had to test if there was any performance difference, results:

      user system total real
inject(0) 20.320000 5.430000 25.750000 ( 34.486938)
inject 20.450000 5.350000 25.800000 ( 30.152165)
inject &:+ 37.860000 5.690000 43.550000 ( 45.670349)
each 11.130000 3.460000 14.590000 ( 15.042142)
C 0.020000 0.000000 0.020000 ( 0.019815)

so inject(0) vs inject doesn't really matter.
code: http://pastie.caboo.se/11534 (and yes i know the C code doesn't
handle bignums)

@Robert: you mean the thread "for performance, write in C" ? :wink:

···

On 9/3/06, Phrogz <gavin@refinery.com> wrote:

Sander Land wrote:
> class Array
> def sum
> inject(0){|a,b| a+b}
> end
> end

For a little more speed, try instead:

class Array
  def sum
    inject{ |a,b| a+b }
  end
end

3^2=9
9^2=81
8^2+1^2=65
6^2+5^2=61
6^2+1^2=37
3^2+7^2=58
5^2+8^2=89
8^2+9^2=145
1^2+4^2+5^2=42
4^2+2^2=20
2^2+0^2=4
4^2=16
1^2+6^2=37
We just started a loop here since 37 has already been found.

···

On 9/1/06, James Edward Gray II <james@grayproductions.net> wrote:

On Sep 1, 2006, at 8:41 AM, Peter Hickman wrote:

> Doesn't this mean that all numbers are happy?

Here's some further reading for those still confused:

http://mathworld.wolfram.com/HappyNumber.html

James Edward Gray II

--
--- Shane Emmons <semmons99@gmail.com>

Problem is that from the quiz it states that you either get a 1 or an infinite loop and that an unhappy number is "obvious". Which is a sign that something has not been explained clearly. Given that the Wolfram page was clearer than the quiz at to what constitutes happy don't be surprised if some people go off down the wrong path.

James Gray wrote:

···

On Sep 1, 2006, at 8:41 AM, Peter Hickman wrote:

Doesn't this mean that all numbers are happy?

Here's some further reading for those still confused:

http://mathworld.wolfram.com/HappyNumber.html

James Edward Gray II

Wow. Lots of strategy on that page. Almost like cheating :wink:

On a side note... Did anyone NOT calculate 3 by hand? Heh.

--
Posted via http://www.ruby-forum.com/\.

Paul Lutus wrote:

Another example is non-Euclidean geometry, which was an impractical,
exotic
plaything for about 100 years, until general relativity came along and
required it. Without non-Euclidean geometry, Einstein wouldn't have been
able to express GR at all.

Prior to that, few would have guessed that the universe isn't Euclidean.

Wait, are you suggesting that in a hundred years, Happy Numbers could
prove the universe is... Happy?

···

--
Posted via http://www.ruby-forum.com/\.

Nope not quite :slight_smile:
I forgot the thread, but as far as I remember nobody wanted to hear about
"each"
I think inject is overused - en vogue - like if it were the only tool
for me the code
def sum
    s = 0
    each { |e| s += e }
    s
end

is robust, readable and rubish, as performance was an issue there was no
need to try to be clever and use a *nice* feature like inject.

I would use inject e.g. wait, let me see, dunno :wink:
if performance does not matter of course

def sum
   inject(0){ ...
end

is the choice, but as you pointed out if you want better performance go
*all* the way.

Cheers
Robert

···

On 9/3/06, Sander Land <sander.land@gmail.com> wrote:

On 9/3/06, Phrogz <gavin@refinery.com> wrote:
> Sander Land wrote:
> > class Array
> > def sum
> > inject(0){|a,b| a+b}
> > end
> > end
>
> For a little more speed, try instead:
>
> class Array
> def sum
> inject{ |a,b| a+b }
> end
> end

Is that really so much faster? Worth breaking on empty arrays?
Just had to test if there was any performance difference, results:

      user system total real
inject(0) 20.320000 5.430000 25.750000 ( 34.486938)
inject 20.450000 5.350000 25.800000 ( 30.152165)
inject &:+ 37.860000 5.690000 43.550000 ( 45.670349)
each 11.130000 3.460000 14.590000 ( 15.042142)
C 0.020000 0.000000 0.020000 ( 0.019815)

so inject(0) vs inject doesn't really matter.
code: http://pastie.caboo.se/11534 (and yes i know the C code doesn't
handle bignums)

@Robert: you mean the thread "for performance, write in C" ? :wink:

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

Sander Land wrote:

Just had to test if there was any performance difference, results:

      user system total real
inject(0) 20.320000 5.430000 25.750000 ( 34.486938)
inject 20.450000 5.350000 25.800000 ( 30.152165)
inject &:+ 37.860000 5.690000 43.550000 ( 45.670349)
each 11.130000 3.460000 14.590000 ( 15.042142)
C 0.020000 0.000000 0.020000 ( 0.019815)

so inject(0) vs inject doesn't really matter.

Interesting! Thanks for sharing. I'm surprised that #each with += is so
much faster.

/me sheepishly raises his hand

I didn't use my hands, just my head. :frowning:

Jacob Fugal

···

On 9/1/06, William Crawford <wccrawford@gmail.com> wrote:

On a side note... Did anyone NOT calculate 3 by hand? Heh.

Sorry, I should have clarified that a Happy number results in 1, and an
Unhappy number results in an infinite loop.

···

On 9/1/06, William Crawford <wccrawford@gmail.com> wrote:

James Gray wrote:
> On Sep 1, 2006, at 8:41 AM, Peter Hickman wrote:
>
>> Doesn't this mean that all numbers are happy?
>
> Here's some further reading for those still confused:
>
> Happy Number -- from Wolfram MathWorld
>
> James Edward Gray II

Wow. Lots of strategy on that page. Almost like cheating :wink:

On a side note... Did anyone NOT calculate 3 by hand? Heh.

--
Posted via http://www.ruby-forum.com/\.

--
--- Shane Emmons <semmons99@gmail.com>

One note of advice - the operator to use is actually ** not ^ as might
be expected:

7 ^ 2 # Gives 5
7 ** 49 # Gives 49

Cheers,
Roland