LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Printing Armstrong numbers from 1 to 500. (C Programming) (https://www.linuxquestions.org/questions/programming-9/printing-armstrong-numbers-from-1-to-500-c-programming-466789/)

duffmckagan 07-23-2006 10:05 AM

Printing Armstrong numbers from 1 to 500. (C Programming)
 
Code:

/*
Write a program to print out all Armstrong numbers between 1 and 500.
If sum of cubes of each digit of the number is equal to the number itself,
then the number is called an Armstrong number.
For example,
153 = (1*1*1) + (5*5*5) + (3*3*3)
*/


#include<stdio.h>
main()
{
        int number, temp, digit1, digit2, digit3;

        printf("Printing all Armstrong numbers between 1 and 500:\n\n");

        number = 001;

        while (number <= 500)
        {
                digit1 = number%10;
                digit2 = (number%100) - ((number/100)*10);
                digit3 = number%1000;

                temp = (digit1*digit1*digit1) + (digit2*digit2*digit2) + (digit3*digit3*digit3);

                if (temp == number)
                {
                        printf("\nAmstrong Number:%d", temp);
                }

                number++;
        }
}


Whats wrong with the program?

It does not give a single number in the output!

michaelk 07-23-2006 10:25 AM

Per the rules:
Do not expect LQ members to do your homework - you will learn much more by doing it yourself.

However, providing hints is acceptable.
Have you verified that digit1, digit2 and digit3 equations actually produce the correct values of your number?

duffmckagan 07-23-2006 10:27 AM

Hey..i was not expecting you to do my homework!!

I worked all the way upto this step..and still the program is not working..so I asked for help!

well.I changed the Digit Extraction scheme and it worked :)

Changed it to this:

Code:

digit1 = number - ((number / 10) * 10);
digit2 = (number / 10) - ((number / 100) * 10);
digit3 = (number / 100) - ((number / 1000) * 10);


michaelk 07-23-2006 10:38 AM

Well done.

graemef 07-23-2006 12:32 PM

Just to comment on what you have done, Whilst your second approach is correct, it is a little ungainly, the first approach to get the digits actually had some merit. With a little more thought, you can make that code much cleaner.

And for the moment I'll leave it there as a poser... :)

Lalit Yogi 06-11-2017 12:22 AM

slightly alternate solution-
 
#include<stdio.h>
void main()
{
int number,temp,digit1,digit2,digit3;

for(number=001;number<=500;number++)
{
digit1 = number - ((number/10)*10);
digit2 = (number - ((number/100)*100))/10;
digit3 = number/100;
temp = (digit1*digit1*digit1) + (digit2*digit2*digit2) + (digit3*digit3*digit3);
if(temp==number)
printf("\nArmstrong number: %d",temp);
}
}

Here in my code, digit2 and digit3 values are a little different-

digit1 = number - {(number/10)*10}
digit2 = {number - ((number/100)*100)}/10
digit3 = number / 100

astrogeek 06-11-2017 01:42 AM

Welcome to LQ!

You have posted to an 11 year dead thread, best to leave them at rest! Please start your own threads for your own questions.

See the LQ posting guidelines foru guidance in posting your questions as well.

And when you post code, please place your code snippets inside [CODE]...[/CODE] tags for better readability. You may type those yourself or click the "#" button in the edit controls.

GazL 06-11-2017 10:10 AM

I'm glad he did, I enjoyed having a go at that one. :)

BTW, watch out for those leading zeros!
Code:

for(number=001;number<=500;number++)
It doesn't matter in this case, but leading zeros signify octal!

danielbmartin 06-11-2017 03:56 PM

Quote:

Originally Posted by GazL (Post 5721578)
I'm glad he did, I enjoyed having a go at that one. :)

Me too. Just for fun I wrote a non-C solution.
This code ...
Code:

seq -w 500  \
|awk -F "" '{if ($1^3+$2^3+$3^3==$0) print}'

... produced this result ...
Code:

001
153
370
371
407

Daniel B. Martin

danielbmartin 06-12-2017 10:13 AM

Execution time is always of interest.

The original problem statement (in post #1) is ...
Code:

Write a program to print out all Armstrong numbers between 1 and 500.
If sum of cubes of each digit of the number is equal to the number itself, then the number is called an Armstrong number.
For example, 153 = (1*1*1) + (5*5*5) + (3*3*3)

Post #9 offered this concise non-C solution ...
Code:

echo "Method #1 of LQ Member danielbmartin."
seq -w 500  \
|awk -F "" '{if ($1^3+$2^3+$3^3==$0) print}' >$OutFile

Consider a means to reduce execution time. Since the largest number must be less than 501, each of the individual terms $1^3, $2^3, and $3^3 must be less than 501.

The command seq -w 500 creates a stream of lines in the form
Code:

001
002
003
 ...
498
499
500

8^3=512 and 9^3=729, so the stream may be "pruned" to eliminate all lines which contain an 8 or a 9, in this manner.
Code:

echo "Method #2 of LQ Member danielbmartin."
seq -w 500      \
|egrep -v '[89]' \
|awk -F "" '{if ($1^3+$2^3+$3^3==$0) print}' >$OutFile

Pruning reduces the stream from 500 to 320 lines which leaves less work for the awk to do. This might seem like an improvement but it isn't, as shown below.

Now, another surprise. A solution which uses only awk looks verbose and clumsy but turned out to be the fastest of the three.
Code:

echo "Method #3 of LQ Member danielbmartin."
awk 'BEGIN{for (j=1;j<=500;j++)
          {k="00"j;
    a=substr(k,length(k)-2,3);  # a = j with leading zeros
    h=substr(a,1,1);  # h = hundreds
    t=substr(a,2,1);  # t = tens
    u=substr(a,3,1);  # u = units
    if (h^3+t^3+u^3==j) print a}}' >$OutFile

A measurement of each solution executed 1000 times produced this result ...
Code:

Method #1 of LQ Member danielbmartin, repeated 1000 times.
real    0m2.356s
user    0m0.060s
sys    0m0.160s

Method #2 of LQ Member danielbmartin, repeated 1000 times.
real    0m2.649s
user    0m0.064s
sys    0m0.260s

Method #3 of LQ Member danielbmartin, repeated 1000 times.
real    0m1.779s
user    0m0.060s
sys    0m0.088s

Perhaps the awk-savvy reader will know a better way to produce the three-digit lines 001,002, ... etc.

Daniel B. Martin

KenJackson 06-12-2017 11:05 AM

Yeah, this is fun. Didn't time it.
Code:

awk 'BEGIN{for (h=0;h<8;h++)
            for (t=0;t<8;t++)
            for (u=0;u<8;u++)
              if ((h||t||u) && (h^3+t^3+u^3==h*100+t*10+u)) print h t u}'


ntubski 06-12-2017 11:24 AM

Quote:

Originally Posted by danielbmartin (Post 5721930)
Perhaps the awk-savvy reader will know a better way to produce the three-digit lines 001,002, ... etc.

"Better" might be subjective, but some shorter ways are:

Code:

BEGIN{for (j=1;j<=500;j++) {
        h=int(j/100);    # h = hundreds
        t=int(j/10) % 10; # t = tens
        u=j % 10;        # u = units
        if (h^3+t^3+u^3==j) print j}}

Code:

BEGIN{for (j=1;j<=500;j++) {
        split(sprintf("%03d", j), digits, "");
        if (digits[1]^3+digits[2]^3+digits[3]^3==j) print j}}


danielbmartin 06-12-2017 02:48 PM

Timings ...

Code:

Method #1 of LQ Member danielbmartin, repeated 1000 times.
real        0m2.388s
user        0m0.040s
sys        0m0.184s

Method #2 of LQ Member danielbmartin, repeated 1000 times.
real        0m2.709s
user        0m0.084s
sys        0m0.232s

Method #3 of LQ Member danielbmartin, repeated 1000 times.
real        0m1.803s
user        0m0.056s
sys        0m0.096s

Method #1 of LQ Member KenJackson, repeated 1000 times.
real        0m1.418s
user        0m0.048s
sys        0m0.096s

Method #1 of LQ Senior Member ntubski, repeated 1000 times.
real        0m1.388s
user        0m0.056s
sys        0m0.096s

Method #2 of LQ Senior Member ntubski, repeated 1000 times.
real        0m2.437s
user        0m0.052s
sys        0m0.104s

Nice ideas from everyone. Thank you!

Daniel B. Martin

Laserbeak 06-12-2017 02:59 PM

There's two basic approaches -- try to calculate every Armstrong number between 1 and 500 or check every number between 1 and 500 to see if it's an Armstrong number. I assume this has already been made clear.

Which is faster would need testing.

danielbmartin 06-12-2017 03:36 PM

Quote:

Originally Posted by Laserbeak (Post 5722030)
There's two basic approaches -- try to calculate every Armstrong number between 1 and 500 or check every number between 1 and 500 to see if it's an Armstrong number. I assume this has already been made clear.

Which is faster would need testing.

calculate every Armstrong number between 1 and 500
... this requires an algorithm. Do you know one?

check every number between 1 and 500 to see if it's an Armstrong number
... this is exhaustive enumeration and is the basis of all solutions posted so far. Granted, avoiding 8s and 9s is a small shortcut but all the posted solutions fall into the Brute Force category.

Daniel B. Martin


All times are GMT -5. The time now is 04:27 PM.