Reputation: 43
How to write a logic using for
loop or while
loop for printing Armstrong numbers?
Someone kindly explain how to print Armstrong numbers between 1 to 1,00,00,000.
This the algorithm that I followed
step 1 : initializing variable min,max,n,sum,r,t
step 2 : my $n = <>;
step 3 : to find base of $n
step 4 : using for loop
( for (n = min; n < max ; n++ )
step 5 : some logic like
n=t,sum =0,r=t%10,t=n/10,
step 6 :
sum = sum + (n ^ base );
step 6 :
if ( sum == num ) print Armstrong numbers else not.
I tried to code this my code look like this
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
my $n;
chomp($n);
my $min = 1;
my $max = 10000000
my $r;
my $sum;
my $t;
my $base = length($n);
print "base is $base\n";
for ($n = $min; $n <= $max; $n++) {
$t = $n;
$sum = 0;
while ($t != 0) {
$r = $t % 10;
$t = $t / 10;
{
$sum = $sum + ($base * $r);
}
if ($sum == $n) {
print "$n\n";
}
}
}
Upvotes: 0
Views: 1885
Reputation: 107060
Several things:
my
until you need it.split
.Here's my attempt. I use split
to split up my digits into an array of digits. This is a lot easier than dividing constantly by ten. I can get the number of digits by simply taking the scalar value of my @digits
array.
I can then loop through @digits
, taking each one to the power of $power
and adding it to sum
. I use the map
command for this loop, but I could have used another for
loop too.
#! /usr/bin/env perl
#
use strict;
use warnings;
use feature qw(say);
use constant {
MIN => 1,
MAX => 1_000_000,
};
for my $number ( (+MIN..+MAX) ) {
my @digits = split //, $number;
my $power = @digits;
my $sum = 0;
map { $sum += $_**$power } @digits;
if ( $sum == $number ) {
say "$number is an Armstrong number";
}
}
And my output:
1 is an Armstrong number
2 is an Armstrong number
3 is an Armstrong number
4 is an Armstrong number
5 is an Armstrong number
6 is an Armstrong number
7 is an Armstrong number
8 is an Armstrong number
9 is an Armstrong number
153 is an Armstrong number
370 is an Armstrong number
371 is an Armstrong number
407 is an Armstrong number
1634 is an Armstrong number
8208 is an Armstrong number
9474 is an Armstrong number
54748 is an Armstrong number
92727 is an Armstrong number
93084 is an Armstrong number
548834 is an Armstrong number
Took a bit over five seconds to run.
Instead of map
, I could have done this loop:
for my $digit ( @digits ) {
$sum = $sum + ( $digit ** $power);
}
Upvotes: 1
Reputation:
Your code seems to be right, but you have some kind of problems with your start. For example you dont read from STDIN
or from @ARGV
. Would you do that, you just have a small problem with your calculating of the exponential calculation. In most Programming Languages, the syntax for a exponential calculation is **
or a pow()
function.
I really dont understand, for what this part is:
while ($t != 0) {
$r = $t % 10;
$t = $t / 10;
{
$sum = $sum + ($base * $r);
}
if ($sum == $n) {
print "$n\n";
}
}
For what is the naked block? Why do you use the modulus? .. Well i give you a small code for calculating the armstrong numbers with bases of 1..100
, between 0 and 10million:
#!/usr/bin/perl
use strict;
use warnings;
foreach my $base (0..100) { # use the foreach loop as base
for my $num (0..10_000_000) { # and use numbers between this range
my $ce=0; # ce = calculated exp.
foreach my $num2 (split //,$num ) { # split each number for calc each
$ce += $num2 ** $base; # exp. and adding it (see algorithm)
}
if ($num == $ce) { # when the exp. num and the number
print "$base => $num\n"; # itself equals, its a armstrong number
} # print that
}
}
Upvotes: 0
Reputation: 15043
I dug out the one I made in C and converted it to perl for you (it may not be the best way to do this, but it is the way I did it):
#!/usr/bin/env perl
use strict;
use warnings;
my $min = 1;
my $max = 10000000;
for (my $number = $min; $number <= $max; $number++) {
my @digits = split('', $number);
my $sum = 0;
foreach my $digit (@digits) {
$sum += $digit**length($number);
}
if ($sum == $number) {
print "$number\n";
}
}
(Demo - 1 to 9999 due to execution time limit)
Upvotes: 0