### Perl Weekly Challenge: Week 72

#### Challenge 1:

Trailing zeroes

You are given a positive integer `\$N (<= 10)`.

Write a script to print number of trailing zeroes in `\$N!`.

##### Example 1

Input: \$N = 10

Output: 2 as \$N! = 3628800 has 2 trailing zeroes

##### Example 2

Input: \$N = 7

Output: 1 as \$N! = 5040 has 1 trailing zero

##### Example 3

Input: \$N = 4

Output: 0 as \$N! = 24 has 0 trailing zero

In Raku this is basically a one liner though my solution has some additional code for validation.

There are several ways we can compute factorials but I chose to use the `[*]` reduction metaoperator which multiplies all the elements in a range. The resulting number is matched against a regular expression and the trailing 0's are extracted as a string. The length of that string is printed out.

`````` (([*] 1 .. \$N) ~~ / <(0+)> \$ / // q{}).chars.say;
``````

(Full code on Github.)

Perl doesn't have all those fancy operators so we calculate the factorial by starting with a base of 1 and repeatedly multiplying from `2 .. \$N`.

`````` my \$factorial = 1;

for my \$i (2 .. \$N) {
\$factorial *= \$i;
}
``````

Then again the trailing o's are captured in a regex.

`````` \$factorial =~ /(0+)\$/;
``````

One problem is that if there are no trailing 0's, the capture (`\$1`) will be undefined so if have to explicitly set it to 0 in that case. . say length \$1 // 0;

(Full code on Github.)

#### Challenge 2:

Lines Range

You are given a text file name `\$file` and range `\$A``\$B` where `\$A <= \$B`.

Write a script to display lines range `\$A` and `\$B` in the given file.

##### Example

Input:

`````` \$ cat input.txt
L1
L2
L3
L4
...
...
...
...
L100
``````

\$A = 4 and \$B = 12

Output:

`````` L4
L5
L6
L7
L8
L9
L10
L11
L12
``````

In Raku this is another one-liner (again minus the validation code.) `IO.lines()` returns a "lazy" list of lines which won't actually exist unless referenced. So it is more efficient than it looks. Because lists are indexed starting from 0, both `\$A` and `\$B` have to be decremented by 1 to get the propper range.

`````` .say for \$file.IO.lines[\$A - 1 .. \$B - 1];
``````

(Full code on Github.)

Perl once again is more verbose.

We start by setting up a counter for line numbers.

``````  my \$linenumber = 0;
``````

This is the standard best practice way to open a file in Perl.

``````  open my \$fn, '<', \$file or die "\$OS_ERROR\n";
``````

Then we read each line in the file. and increment `\$linenumber` so lines will be numbered starting from 1 instead of 0.

``````  while (my \$line = <\$fn>) {
\$linenumber++;
``````

If the line number is greater than `\$B` we are at the end of the range so we can stop reading and break out of the loop.

``````      if (\$linenumber < \$A) {
next;
}
``````

If the line number is less than `\$A` we haven't reached the beginning of the range so we can skip further processing and go to the next line in the next iteration of the loop.

``````      if (\$linenumber > \$B) {
last;
}
``````

At this point we must still be in the range so we can print the line.

``````      print \$line;
}
``````

Finally, we mustn't forget to close the file handle.

``````  close \$fn;
``````

(Full code on Github.)