### 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++;
}
``````

(Full code on Github.)

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++;
}
``````

(Full code on Github.)

#### 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;
``````

(Full code on Github.)

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

(Full code on Github.)

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.