The Bear's Den

Enter at your own risk

Long Loops

TASK #1 › Long Year

Submitted by: Mohammad S Anwar


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

Solution

Here is my solution dated 1 Nov 2021:

#!/usr/bin/perl -s

use v5.16;
use warnings;
use DateTime;

# Maybe I'm missing something: The year's last day's week number is the
# year's week count.
say join ' ', grep DateTime->new(year => $_, month => 12, day => 31,
    time_zone => 'floating')->week_number == 53, 1900 .. 2100;

TASK #2 › Lychrel Number

Submitted by: Mohammad S Anwar


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

Solution

The given limit for the number of iterations is superfluous. 30 iterations on any number result in a number far beyond 1e7.

Two further test cases:

Perl

use strict;
use warnings;
use experimental 'signatures';
use Math::Prime::Util qw(fromdigits todigits);

sub lychrel ($n) {
    while () {
        my $rev = fromdigits [reverse todigits $n, 10], 10;
        return 0 if $n == $rev;
        return 1 if $n > 1e7;
        $n += $rev;
    }
}

See the full solution to task 2.

J

Defining a helper adverb rev, where u rev applies the verb u between y and the reversed digits of y, i.e. + rev y produces the next value and = rev y checks if y is a palindrome.

The loop will be ended either with a value of 0, signaling a non-Lychrel number, or otherwise without result - which is an error. Catch errors and return 1 in such case.

rev =: [ ` ]: ` (|.&.(10&#.inv)) `: 6

lychrel =: _(adverb define)
  stop =. {{
    _2 Z: 1e7 < y
    (1 Z:~ = rev) y
    0
  }}
  (stop F. (+ rev) :: 1) f. : [:
)

See the full solution.