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;
my @answers;

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

	push @answers, $orig
		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) {
	my @answers;
	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;
			}

			push @answers, $orig_i
				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

One thought on “PERL WEEKLY CHALLENGE – 069

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s