### Perl Weekly Challenge: Week 137

#### Challenge 1:

**Long Year**

Write a script to find all the years between

`1900`

and`2100`

which is a`Long Year`

.A year is Long if it has 53 weeks.

**[UPDATED][2021-11-01 16:20:00]:** For more information about `Long Year`

, please refer to wikipedia.

Expected Output

```
1903, 1908, 1914, 1920, 1925,
1931, 1936, 1942, 1948, 1953,
1959, 1964, 1970, 1976, 1981,
1987, 1992, 1998, 2004, 2009,
2015, 2020, 2026, 2032, 2037,
2043, 2048, 2054, 2060, 2065,
2071, 2076, 2082, 2088, 2093,
2099
```

Calendrical calculations are a keen interest of mine. In this case the solution was quite straightforward because the referenced Wikipedia page already has a formula you can use. So the code shown below is merely a translation of that without further embellishment.

These two functions represent the Wikipedia formula. One thing that was not readily apparent from reading that page was that the
formula uses integer division. In raku this means using the `div`

operator not the normal `/`

which I initially employed. `/`

uses
floating point which caused all kinds of puzzling off by one errors until I figured out that I was using the wrong operator.

```
sub p(Int $year) {
return (($year + ($year div 4) - ($year div 100) + ($year div 400)) % 7);
}
sub isLongYear(Int $year) {
return p($year) == 4 || p($year - 1) == 3;
}
```

Once I had the `isLongYear()`

function, all I had to do is `.grep()`

through all the years between 1900 to 2100 looking
for long years and then joining the list together with commas and printing it.

```
(1900 .. 2100)
.grep({ isLongYear($_); })
.join(q{, })
.say;
```

This is the Perl version. Perl doesn't have `div`

like Raku but we can simulate it with a combination of normal `/`

division and the
`int()`

function.

```
sub p {
my ($year) = @_;
return (($year + int($year / 4) - int($year / 100) + int($year / 400)) % 7);
}
sub isLongYear {
my ($year) = @_;
return (p($year) == 4 || p($year - 1) == 3);
}
say join q{, }, grep { isLongYear($_); } (1900 .. 2100);
```

#### Challenge 2:

**Lychrel Number**

You are given a number, 10 <=

`$n`

<= 1000.Write a script to find out if the given number is Lychrel number. To keep the task simple, we impose the following rules:

```
a. Stop if the number of iterations reached 500.
b. Stop if you end up with number >= 10_000_000.
```

**[UPDATED][2021-11-01 16:20:00]:** If you stop because of any of the above two rules then we expect `1`

as an output.

According to wikipedia:

A Lychrel number is a natural number that cannot form a palindrome through the iterative process of repeatedly reversing its digits and adding the resulting numbers.

##### Example 1

```
Input: $n = 56
Output: 0
After 1 iteration, we found palindrome number.
56 + 65 = 121
```

##### Example 2

```
Input: $n = 57
Output: 0
After 2 iterations, we found palindrome number.
57 + 75 = 132
132 + 231 = 363
```

##### Example 3

```
Input: $n = 59
Output: 0
After 3 iterations, we found palindrome number.
59 + 95 = 154
154 + 451 = 605
605 + 506 = 1111
```

Here is the important part of my Raku solution:

```
sub lychrel(Int $n) {
my $i = $n;
```

Strictly speaking this should be an infinite loop but the spec says we can stop after 500 iterations. for 1 .. 500 {

We reverse the number by splitting it into a list of individual digits with `.comb()`

, reversing that list and then joining it
back up again. Too late, I've just remembered that Raku has `.flip()`

which would have reversed the number without all this extra work.

```
my $r = $i.comb.reverse.join;
```

This is added to I to form the number to be checked for palindromeness (palindromosity?)

```
$i = $i + $r;
```

Again I could have used `.flip()`

here. If the number is a palindrome (i.e. it is the same as its' reverse,) we are done and
0 is returned.

```
if $i == $i.comb.reverse.join {
return 0;
}
```

The spec says we can stop if the number is greater than 10,000,000. In this case we return 1.

```
if $i > 10_000_000 {
return 1;
}
}
```

If we have done more than 500 iterations without finding a palindrom we also return 1. These two conditions make our code a lot
easier but we get a lot of false positives as a result. This code detected 52 Lychrel numbers but most (perhaps all of these?) could
have ended up as palindromes if `$i`

was allowed to grow big enough or enough iterations were performed.

```
return 1;
}
```

This is the Perl version. There's no `.flip()`

in Perl so split, reverse and join was the right thing to do here.

```
sub lychrel {
my ($n) = @_;
my $i = $n;
for (1 .. 500) {
my $r = join q{}, (reverse split //, $i);
$i = $i + $r;
if ($i == join q{}, (reverse split //, $i)) {
return 0;
}
if ($i > 10_000_000) {
return 1;
}
}
return 1;
}
```