### Perl Weekly Challenge: Week 123

#### Challenge 1:

**Ugly Numbers**

You are given an integer

`$n`

>= 1.Write a script to find the $nth element of Ugly Numbers.

Ugly numbers are those number whose prime factors are 2, 3 or 5. For example, the first 10 Ugly Numbers are 1, 2, 3, 4, 5, 6, 8, 9, 10, 12.

##### Example

```
Input: $n = 7
Output: 8
Input: $n = 10
Output: 12
```

Prime factors have come up before in the Weekly Challenge so I got to reuse some code which I wrote for week 23 (and originated even earlier in week 12 but I wasn't blogging back then.) So see the blog for that one for discussion of how I got prime factors.

Once we have the list of prime factors we can check that it only contains 2, 3, and 5. I used `.grep()`

for
this even though Raku's set support would have been more elegant because I am still having problems getting the
latter to work properly. I really need to update my Raku version to something vaguely current but I just haven't
had the time. Still, the present approach works and that's the main thing. If the grep results in a list of
prime factors other than 2, 3, or 5, the number is not ugly and a false value is returned otherwise true is returned.

```
sub isUgly(Int $n) {
my @primeFactors;
factorize($n, @primeFactors);
return @primeFactors.grep({ $_ != 2 && $_ != 3 && $_ != 5 }).elems == 0;
}
```

The `MAIN()`

driver is simple. We start from 1 and count upwards in a loop. (Could have used a `while`

loop but did it this way on a whim.) There is a count of ugly numbers found and when that number reaches `$n`

, we print the last ugly number found and exit the loop and thus, the script.

```
my $number = 1;
my $uglies = 0;
loop {
if isUgly($number) {
$uglies++;
}
if $uglies >= $n {
say $number;
last;
}
$number++;
}
```

The Perl version not only needs code for prime factors but for calculating if a number is prime in the first place. (Raku has a method for that bit.) Luckily, that code was already written. Again, see week 23 for discussion.

For Perls' version of `isUgly()`

there is no question of using anything but the grep method.

```
sub isUgly {
my ($n) = @_;
my @primeFactors;
factorize($n, \@primeFactors);
return (scalar grep { $_ != 2 && $_ != 3 && $_ != 5 } @primeFactors) == 0;
}
```

The main code works exactly the same as Raku. Too much the same. I actually am using
`while`

so I could have done `while ($uglies < $n)`

but didn't.

```
my $number = 1;
my $uglies = 0;
while(1) {
if (isUgly($number)) {
$uglies++;
}
if ($uglies >= $n) {
say $number;
last;
}
$number++;
}
```

#### Challenge 2:

**Square Points**

You are given coordinates of four points i.e. (x1, y1), (x2, y2), (x3, y3) and (x4, y4).

Write a script to find out if the given four points form a square.

##### Example

```
Input: x1 = 10, y1 = 20
x2 = 20, y2 = 20
x3 = 20, y3 = 10
x4 = 10, y4 = 10
Output: 1 as the given coordinates form a square.
Input: x1 = 12, y1 = 24
x2 = 16, y2 = 10
x3 = 20, y3 = 12
x4 = 18, y4 = 16
Output: 0 as the given coordinates doesn't form a square.
```

This one is really easy. You just compare the x coordinates of opposing sides to see if the two sides are equal and then do the same to the y coordinates of opposing sides. If both pairs are equal you have a square. The code is almost exactly the same in Perl and Raku minus minor syntactical differences.

```
say (abs($x1 - $x3) == abs($x2 - $x4) && abs($y1 - $y2) == abs($y3 - $y4)) ?? 1 !! 0;
```

```
say 0+(abs($x1 - $x3) == abs($x2 - $x4) && abs($y1 - $y2) == abs($y3 - $y4)) ? 1 : 0;
```

Ahh maybe this was deceptively too easy! As I write this, it has just occurred to me that the code as written above actually determines if the points make a rectangle. True, a square is a type of rectangle but if I really wanted to be faithful to the spec and find squares only I should also have checked the x-sides against the y-sides to see if they are equal too.