### Perl Weekly Challenge: Week 133

#### Challenge 1:

**Integer Square Root**

You are given a positive integer

`$N`

.Write a script to calculate the integer square root of the given number.

Please avoid using built-in function. Find out more about it here.

##### Examples

```
Input: $N = 10
Output: 3
Input: $N = 27
Output: 5
Input: $N = 85
Output: 9
Input: $N = 101
Output: 10
```

The wikipedia link provided gives an algorithm and example C code for solving this problem and my solution is just a straight translation. Here's the Perl version:

```
sub squareRoot {
my ($n) = @_;
my $firstTry = $n >> 1;
if ( $firstTry ) {
my $nextTry = ( $firstTry + $n / $firstTry) >> 1;
while ( $nextTry < $firstTry) {
$firstTry = $nextTry;
$nextTry = ( $firstTry + $n / $firstTry) >> 1;
}
return $firstTry;
} else {
return $n;
}
}
```

And this is the Raku version. The funky right bit shift operator `+>`

was the only stumbling block.

```
sub squareRoot(Int $n) {
my $firstTry = $n +> 1;
if $firstTry {
my $nextTry = ( $firstTry + $n / $firstTry) +> 1;
while $nextTry < $firstTry {
$firstTry = $nextTry;
$nextTry = ( $firstTry + $n / $firstTry) +> 1;
}
return $firstTry;
} else {
return $n;
}
}
```

#### Challenge 2:

**Smith Numbers**

Write a script to generate first 10

`Smith Numbers`

in base 10.According to Wikipedia:

In number theory, a Smith number is a composite number for which, in a given number base, the sum of its digits is equal to the sum of the digits in its prime factorization in the given number base.

I love the challenges where we can reuse code from previous weeks. I used the code I developed for prime factorization most recently
in Challenge 123 but it goes way back before that. It
is used to create an `isSmith()`

function that return true or false if its' input is a Smith Number. In Perl looks it like this:

```
sub isSmith {
my ($n) = @_;
my @digits = split //, $n;
my @primeFactors;
factorize($n, \@primeFactors);
```

If we only have 1 prime factor or 0 (can that actually happen?) it's not going to be a Smith number so we can just stop
here. Because Perl doesn't have actual true and false literals, we return `undef`

to signify false.

```
if (scalar @primeFactors < 2) {
return undef;
}
```

Initially I got some weird answers and then I realized that if the prime factors themselves have multiple digits, they also have
to be summed. The line below takes care of that. Incidently, `sum()`

is another function I had created earlier and reused.

```
@primeFactors = map { my @d = split //, $_; sum(\@d); } @primeFactors;
return sum(\@digits) == sum(\@primeFactors);
}
```

This is the Raku version. The `[+]`

hyperoperator for summing a list or array is one of my favorite features of the language.

```
sub isSmith($n) {
my @digits = $n.comb;
my @primeFactors;
factorize($n, @primeFactors);
if @primeFactors.elems < 2 {
return;
}
@primeFactors = @primeFactors.map({ [+] $_.comb; });
if ([+] @digits) == ([+] @primeFactors) {
take $n;
}
}
```

Initially I wrote this to return true or false like the Perl version and it worked but was slower than Perl. (Though not too shabby I must say.) I took another stab at it and refactored it to use `take`

to return valid Smith numbers. This can be used together
with `gather`

like this:

```
my @smiths = lazy gather {
for 1 .. * -> $n {
isSmith($n)
}
}
@smiths[^10].join(', ').say;
```

...to create a lazy list. This actually runs faster than Perl, the first time I've seen non-trivial Raku code do that.