PERL WEEKLY CHALLENGE – 069

This is my 39th week participating into the weekly challenge.

TASK #1 › Strobogrammatic Number

Submitted by:Mohammad S Anwar

A strobogrammatic number is a number that looks the same when looked at upside down.

You are given two positive numbers `\$A` and `\$B` such that `1 <= \$A <= \$B <= 10^15`.

Write a script to print all strobogrammatic numbers between the given two numbers.

Example

```Input: \$A = 50, \$B = 100
Output: 69, 88, 96
```

For this challenge I read up on the strobogrammatic number https://en.wikipedia.org/wiki/Strobogrammatic_number.

Then I came up with a simple algorithm to test if a number is a strobogrammatic number.

X is a strobogrammatic number if we remove all numbers that are able to flip be flipped or mirrored. If there are no numbers after the removal process then X is a strobogrammatic number.

First we check for 6 and 9 combinations, then remove 1, 0 and 8’s

For example this is a strobogrammatic number:
66188199
618819
1881
88

This is not:
661858199
6185819
18581
858
5

Because 5 remains

Perl 5 solution

``````#!/usr/bin/perl
# Test: ./ch-1.pl 50 100
use Modern::Perl;

my \$a = shift;
my \$b = shift;

die "Invalid inputs"
if ( !\$a || !\$b || \$a > \$b ||
\$a < 0 || \$b > 10e15 );

# Process each number
for my \$i (\$a .. \$b) {
my \$orig = \$i;

# Check and remove 6/9, 9/6 0/0, 1/1, 8/8 pairs
my \$search_length = length(\$i) / 2;
for (my \$j = 0; \$j < \$search_length; \$j++) {
my \$p1 = substr \$i, \$j, 1;
my \$p2 = substr \$i, length(\$i) - \$j - 1, 1;

if ( (\$p1 == 6 && \$p2 == 9) ||
(\$p1 == 9 && \$p2 == 6) ||
(\$p1 == 0 && \$p2 == 0) ||
(\$p1 == 8 && \$p2 == 8) ||
(\$p1 == 1 && \$p2 == 1)) {
\$i = substr \$i, 1, length(\$i) - 2;
\$j--;
\$search_length--;
} else {
last;
}
}

unless (\$i);
}

say join ', ', @answers;
``````

Output: perl ./ch-1.pl 1 10000

``1, 8, 11, 69, 88, 96, 101, 111, 181, 609, 619, 689, 808, 818, 888, 906, 916, 986, 1001, 1111, 1691, 1881, 1961, 6009, 6119, 6699, 6889, 6969, 8008, 8118, 8698, 8888, 8968, 9006, 9116, 9696, 9886, 9966``

Raku solution

``````# Test: perl6 ch-1.p6
sub MAIN(Int \$a where \$a > 0, Int \$b where \$b < 10e15) {
for (\$a .. \$b) -> \$orig_i {
my \$i = \$orig_i.Str;

# Check and remove 6/9, 9/6 0/0, 1/1, 8/8 pairs
my \$search_length = \$i.chars / 2;
loop (my \$j = 0; \$j < \$search_length; \$j++) {
my \$p1 = \$i.substr(\$j, 1);
my \$p2 = \$i.substr(\$i.chars - \$j - 1, 1);

if ( (\$p1 eq '6' && \$p2 eq '9') ||
(\$p1 eq '9' && \$p2 eq '6') ||
(\$p1 eq '0' && \$p2 eq '0') ||
(\$p1 eq '8' && \$p2 eq '8') ||
(\$p1 eq '1' && \$p2 eq '1')) {
\$i = \$i.substr(1, \$i.chars - 2);
\$j--;
\$search_length--;
} else {
last;
}

unless (\$i);
}
}

say @answers.join(', ' );
}
``````

Output perl6 ch-1.p6

``1, 8, 11, 69, 88, 96, 101, 111, 181, 609, 619, 689, 808, 818, 888, 906, 916, 986, 1001, 1111, 1691, 1881, 1961, 6009, 6119, 6699, 6889, 6969, 8008, 8118, 8698, 8888, 8968, 9006, 9116, 9696, 9886, 9966``

TASK #2 › 0/1 String

Submitted by:Mohammad S Anwar

`0/1 string` is a string in which every character is either 0 or 1.

Write a script to perform `switch` and `reverse` to generate `S1000` as described below:

```switch:

Every 0 becomes 1 and every 1 becomes 0. For example, “101” becomes “010”.

reverse:

The string is reversed. For example, "001” becomes “100”.

```

To generate `S1000` string, please follow the rule as below:

```S0 = “”
S1 = “0”
S2 = “001”
S3 = “0010011”
…
SN = SN-1 + “0” + switch(reverse(SN-1))
```

Not much to this one, just manipulate the string and make a function to return Sn.

Perl 5 solution

``````#!/usr/bin/perl
# Test: ./ch-2.pl
use Modern::Perl;
use Test::More;

is (s_thousand(''),            '0',      'Test: Empty string');
is (s_thousand('0'),         '001',      'Test: 0');
is (s_thousand('001'),   '0010011',      'Test: 001');
done_testing();

# s1000
sub s_thousand {
my \$string = shift;
return \$string . "0" . s_switch(scalar reverse(\$string));
}

# Switch
sub s_switch {
my \$string = shift;
\$string =~ tr/01/10/;
return \$string;
}
``````

Output ./ch-2.pl

``````ok 1 - Test: Empty string
ok 2 - Test: 0
ok 3 - Test: 001
1..3``````

Raku solution

``````# Test: perl6 ch-2.p6
use Test;

sub MAIN() {
is s-thousand(''),            '0',      'Test: Empty string';
is s-thousand('0'),         '001',      'Test: 0';
is s-thousand('001'),   '0010011',      'Test: 001';
done-testing();
}

# s1000
sub s-thousand(Str \$s) {
return \$s ~ "0" ~ s-switch(\$s.flip);
}

# Switch
sub s-switch(Str \$s is copy) {
\$s ~~ tr/01/10/;
return \$s;
}
``````

Output perl6 ch-2.p6

``````ok 1 - Test: Empty string
ok 2 - Test: 0
ok 3 - Test: 001
1..3``````