# Happy/unhappy numbers

Let the sum of the square of the digits of a positive integer S0 be represented by S1. In a similar way, let the sum of the squares of the digits of S1 be represented by S2 and so on. If Si = 1 for some i >= 1, then the original integer S0 is said to be Happy number. A number, which is not happy, is called Unhappy number. For example 7 is a Happy number since 7 -> 49 -> 97 -> 130 -> 10 -> 1 and 4 is an Unhappy number since 4 -> 16 -> 37 -> 58 -> 89 -> 145 -> 42 -> 20 -> 4.

Input

The input file, called test.dat, will consist of several test cases, the number of which you are given in the first line of the input. Each test case consists of one line containing a single positive integer N.

Output

For each test case, you must print one of the following messages:

Case #p: N is a Happy number.

Case #p: N is an Unhappy number.

Here p stands for the case number (starting from 1). You should print the first message if the number N is a happy number. Otherwise, print the second line.

===== Sample input data =============================================

4

7

4

13

5

===== End of input data / Start of corresponding output data ========

Case #1: 7 is a Happy number.

Case #2: 4 is an Unhappy number.

Case #3: 13 is a Happy number.

Case #4: 5 is an Unhappy number.

===== End of output data ============================================

After all that, I managed to create the following code...

// happy numbers by Justin Tom

import java.io.*; // to get file input

public class Happynumbers {

public static void main(String args[]) {

try {

FileReader reader = new FileReader("test.dat");

// read from the file test.dat

BufferedReader comingin = new BufferedReader(reader); // begin reading

// defining variables

int n;

String input;

int casenumber = 1;

while ((input = comingin.readLine()) != null) {

// keep reading from test.dat line by line until there is nothing left to read

// note: incoming input is read line by line from test.dat as a string

n = Integer.parseInt(input); // converts string into integer

int sum = 0; // initialize the sum as zero when dealing with a number from the incoming data

int digit, x;

while (n>0)// loop as long as the original number is greater than zero

{

digit = n%10;// this will yield a single digit from the number

x = n/10;// divide the original number by 10 to remove the last digit

sum = sum + digit * digit;// the sum plus the square of its digit

}

x = sum;

if (sum == 1)

{ System.out.println("Case #" + casenumber + ": " + n + " is a Happy number."); // display the case number and the Happy number

casenumber++; // increment the casenumber

}

if (sum != 1 && casenumber != 1 )

{

System.out.println("Case #" + casenumber + ": " + n + " is an Unhappy number."); casenumber++; // display the case number and the Unhappy number

}

}}

catch (IOException e) // captures errors if any errors occur

{System.out.println(e); // display a message if an error occured

}}}

I tried putting in another while loop for taking the sum of the square of the digits but nothing will show up either. What did I do wrong? PLEASE FOR THE LOVE OF GOD HELP ME!!!

Ranch Hand

So, a few things ...

1) Did it clarify things to break out the loops? Did you see the one I added? YOu have to keep looping through the sum of squares stuff until you find a reason to quit.

2) There are two reasons to quit. One is you hit 1 and have a happy number. The other is you do the sum of squares and get one you already had. That means the loop will run forever unless you're checking.

3) The trick of doing something like getNumber() before the loop and again in the loop is not the loveliest thing in the world but it's a practical thing to remember. In my COBOL days we caleld it a "primer read" to prime the pump and make a while condition work.

A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi

Ranch Hand

The stuff I wrote was not exactly Java. I left out the scope like public or private and the return types, so it was more a psuedocode sketch than real code. If you didn't know I was taking liberties like that it was probably pretty confusing.

You've probably made some of these:

This is a method like any other in Java. The only special thing about it is that when you run JavaC and tell it a class name, the JVM looks for a main method to run.

The "real" method signatures might be more like:

// No argument, returns the next int to work on

public int getNumber()

// One int argument, no return

public void tryOneNumber( int number )

// One int argument, returns another int

public int sumOfSquares( int number )

Take a shot at how you think the Java would look. We like to keep you doing the bulk of the work here at the Ranch. Go in very small steps to give yourself intermediate successes. For example, maybe just work out the getNumber() method.

Post some code to show us how it's going. That's the best way for us to see where you are stuck. Use the "CODE" button below the editor to preserve your indenting and spacing.

BTW: The "collection" business is making a place to keep the numbers you have tried. Look at Collection in the JavaDoc. Follow the links to Set and HashSet. JavaDoc: http://java.sun.com/j2se/1.5/docs/api/

Keep having fun! You're starting on a great journey!

A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi

import java.io.*; // to get file input

public class Happynumbers {

public static void main(String args[]) {

try {

FileReader reader = new FileReader("test.dat");

// read from the file test.dat

BufferedReader comingin = new BufferedReader(reader); // begin reading

// defining variables

int n;

String input;

while ((input = comingin.readLine()) != null) {

// keep reading from test.dat line by line until there is nothing left to read

// note: incoming input is read line by line from test.dat as a string

n(Integer.parseInt(input)); // converts string into integer

}}

catch (IOException e) // captures errors if any errors occur

{System.out.println(e); // display a message if an error occured

}

}

public static void n(int n1)

{

int originaln = n1;

int digit, x;

int casenumber = 1;

do {

int sum = 0; // initialize the sum as zero when dealing with a number from the incoming data

while (n1>0 )

{

digit = n1%10;// this will yield a single digit from the number

n1 = n1/10; // divide the original number by 10 to remove the last digit

sum = sum + digit * digit;// the sum plus the square of its digit

}

n1 = sum;

if (sum == 1) { break;}

if (sum == originaln) {break;}

if (sum == 1)

{

System.out.println("Case #" + casenumber + ": " + originaln + " is a Happy number."); // display the case number and the Happy number

casenumber++; // increment the casenumber

}

if (sum != 1 ) // as long as it is not the first case and the sum is not equal to one

{

System.out.println("Case #" + casenumber + ": " + originaln + " is an Unhappy number."); // display the case number and the Unhappy number

casenumber++;

}

}

while (n1 != originaln);

}

}

import java.io.*;

class HappyNumber

{

public static void main(String[] args) throws IOException

{

try

{

FileReader reader = new FileReader("test.txt"); // read from the file test.dat

BufferedReader comingin = new BufferedReader(reader); // begin reading

int n; // defining variables

String input;

// keep reading from test.dat line by line until there is nothing left to read

// note: incoming input is read line by line from test.dat as a string

int counter=0; //this counter corresponds to the case number

while ((input = comingin.readLine()) != null)

{

Calc1(Integer.parseInt(input),counter); // converts string into integer

counter++;

}

}

catch (IOException e) // captures errors if any errors occur

{

System.out.println(e); // display a message if an error occured

}

}

static void Calc1(int n,int c)

{

int caseno=c;

int originalno=n;

int sum=0;

while (!(sum==1||sum==originalno)) //the method will stop doing the

//summing unless sum=1 or sum=original no

{

n=Calc2(n); //call the Calc2 method to calculate the sum of squares of digits

sum=n;

}

//printing the result

if (sum==1)

{

System.out.println("Case#"+caseno+":"+originalno+"is a Happy Number");

}

else

{

System.out.println("Case#"+caseno+":"+originalno+"is a Not a Happy Number");

}

}

//this method will calculate the sum of squares of digits of any no & will return the value

static int Calc2(int a)

{

int digit;

int s=0;

while (a>0)

{

digit = a%10; // this will yield a single digit from the number

a= a/10; // divide the original number by 10 to remove the last digit

s = s + digit * digit; // the sum plus the square of its digit

}

return s;

}

}

Thank you guys!!!

Warmest wishes and thanks,

Justin Tom

you rewrote my while condition to this:

while (!(sum == 1 || sum == originalno)) //the method will stop doing the

//summing unless sum=1 or sum=original no

in the code three posts up from this one.

Now why is the ! ("not" symbol) thingie is outside of the inner brackets? shouldn't it be

while (sum != 1 || sum != originalno)

or is that just saying the same thing with a matter of difference in style of writing the code?

Ranch Hand

Here's something I learned as DeMorgan's Theory in Boolean Algebra but I think that DeMorgan covers a lot more rules. Google and see Anyhow:

not ( a or b ) == ( not a and not b )

not ( a and b ) == ( not a or not b )

so

!(sum == 1 || sum == originalno) == ( sum != 1 && sum != originalno )

Sometimes you have to put this stuff in English. Either Sum == OR sum == original is sufficient to make you stop. So to keep going sum can't be 1 AND it can't be original.

Which form is clearer is probably personal. If things get much more complicated than this I try to break it into smaller chunks again.

A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi

In your revised code of mine, it does not output anything beyond 4 numbers. Example, if test.txt had

4

7

4

13

5

the program outputted

Case#0:4is a Not a Happy Number

Case#1:7is a Happy Number

Case#2:4is a Not a Happy Number

Case#3:13is a Happy Number

Since number 4 is not a happy number and it is the first case, it shouldn't be displayed, as described in my very first post. And second, anything beyond the fourth number, in this case, the number 5 is not displayed at all. I read your code over and over again and it "seems" perfect...? and it can't be about anything about cutting off any unhappy numbers after the last happy number since I just tried ending it with another happy number 13 and it still doesn't work. Weird? I tried to revise it again and now I'm having more problems... lol...seriously, will the original problem be solved? I tried adding more comments to help myself and maybe to help explain what's going on in my code.

In my new code, it's output was:

Case#2: 7 is a Happy Number

Case#3: 4 is an Unhappy Number

Case#4: 13 is a Happy Number

and the input file test.dat was:

4

7

4

13

5

13

Help again!!! I thought it was solved!!! ( and yes I tried fixing it, and I really should be doing other homework but this is the better kind of work)

Ranch Hand

Here's where we need that collection to keep track of all the numbers we have tried so far. If any of them shows up again then the pattern will repeat forever. Here's the sequence for 5. What happens next?

5 25 29 85 89 145 42 20 4 16 37 58 ...

BTW: Why are you checking for case #1?

[ May 02, 2006: Message edited by: Stan James ]

89 145 42 20 4 16 37 58 89 145 42 20 4 16 37 58 89 145 42 20 4 ...

thus after the sum becums 4 then 4 16 37 58 89 145 42 20 4 these nos keep repeating as we know that 4 is an Unhappy no i.e.Si=original number

Hence the for 5 the the sum never bcums equal to 1 or 5 itself i.e.compiler keeps moving between 4 16 37 58 89 145 42 20 4 ,this also happens for other nos like 8, 6 becuase at some point the sum bcums 4 & hence compiler keeps running between the value of 4.i.e.4 16 37 58 89 145 42 20 4

I didn get you why y asked that "why r u taking case#1?"

Originally posted by venkatesh pendharkar:

...

I didn get you why y asked that "why r u taking case#1?"

He asked that question because it is an unnecessary check. If you keep track of all the numbers produced and stop when a duplicate is made, the loop will terminate sooner or later for any number. You don't really need to make Si==1 a special case. You need to keep track of what the repeat number is to determine the happy/unhappy status of the original number, but you don't really need to check for 1 specifically.

And, if I understand correctly, the reason venkatesh added that test is because that's how the problem is stated. Specifically, if Si==1 there is no reason to calculate S(i+1) -- as soon as Si is 1 we can exit the loop and call S0 Happy.

...or am I stating the obvious?

As some of you said, the loop should stop when you hit 1, which means that you have a happy number.But, the other condition should be that you went back to any of the numbers already tried, not necessarily case#1.Because, as you can see from tryin with number 5, the loop would enter a closed cycle once it hits 4.

I suggest that you keep track of all the numbers already tried, something like:

while((n!=1) && !(list.contains(n)))

I used an ArrayList for that and it works perfectly.

Good luck to everyone!

Well, what if I recorded the number of steps it took to find the sum and then limit the number of steps? Maybe I could limit the number of steps to 1000?

ex.

4 -> 16 -> 37 -> 58 -> 89 -> 145 -> 42 -> 20 -> 4 -> 16 -> 37 -> 58 -> 89 -> 145 -> 42 -> 20 -> ... and so it will never reach one but it'll EVENTUALLY have to be terminated since I limited it to 1000 steps.

Now I rewrote my code by adding another method to keep the count of the number of steps:

The "new" problem: I tried keeping track of the number of steps it takes to sum up the square of the digits but something isn't right with my code, as it ruined my output. I outputted x and all I got was 1's and 2's and occassionally a 3... I need help with that.

Btw: that thingie about that extra case number 1 condition, I kept it in there because if and only if the first case is unhappy, ignore it and print out the next line (as stated in the original problem). Hopefully that'll clarify what I tried to do.

I'm chewing off more than I can bite. More help plz?

(Java code and the logic behind this would help a lot)

(more people the better )

Originally posted by Justin Tom:

I thought about trying to keep track of the numbers that are used, but then the array would eventually become way too big (stack overflow !!!).

Well - how big is your stack? Do you know?

How many numbers could be put into the array?

The CalculateSquares method returns a bigger value for 99 than 100, because 9*9=81 => 2*81 > 1+0+0.

The biggest Integer is made of 10 digits, starting with 21.

The biggest number calculated by the method has to be 1 999 999 999.

To estimate the result I replace lazily 9 with 10, and get 10*10=100 for each 9 which is 901 in total.

So we know that the biggest number in step 2 is below 901 - let's assume it is 899.

That will return (lazily calculated) 100*3 which is 300.

No number bigger than 1000 will be calculated from an Integer.

So adding those numbers to a Set is no problem, while stopping recalcalculation after 1000 steps isn't false.

I didn't quite get the reason why u r using counter?

But, all this code:

could be replaced by:

You still didn't address the real problem, which is breaking out of the loop when you encounter a number for the second time.Instead of encountring the original number, which will not always happen(for example when the original number is 5).

You could use ArrayList because, unlike arrays, you don't have to know before hand the size of your arraylist and they have a convenient method to add more objects and a more convenient one to check if an arraylist contains a certain value.

You could take a look at the code that I came up with if you want. I used a totally different approach.And instead of getting the input from a file, this program just prints out the happy numbers between 1 and 1000.

Good luck!

My finalized code (hopefully no more errors, but I seriously don't see any left) :

Thank you guys so much! Especially in the beginning when I struggled and you guys helped! (yes!!! I avoided stacking and the use of arrays ) And the best part is that you guys helped me with the code following it my way!

Hugs and thank you's!

Justin Tom

P.S. I'll still be back, maybe in other topics unless I find another error or if you guys see another error... lol... but I think it's pretty much "fail-proof" since it works for all conditions.

Ranch Hand

I thought about trying to keep track of the numbers that are used, but then the array would eventually become way too big (stack overflow !!!).

I tried this from 0 to 500,000 and the longest chain of tries was 20 for 15,999. All of my happy numbers terminated in 6 or less. I was rather surprised at that!

[ May 03, 2006: Message edited by: Stan James ]

Did you see how Paul cut 87% off of his electric heat bill with 82 watts of micro heaters? |