PERL WEEKLY CHALLENGE – 060

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


TASK #1 › Excel Column

Reviewed by: Ryan Thompson

Write a script that accepts a number and returns the Excel Column Name it represents and vice-versa.

Excel columns start at A and increase lexicographically using the 26 letters of the English alphabet, A..Z. After Z, the columns pick up an extra “digit”, going from AAAB, etc., which could (in theory) continue to an arbitrary number of digits. In practice, Excel sheets are limited to 16,384 columns.

Example

Input Number: 28 Output: AB

Input Column Name: AD Output: 30


For this challenge it was just a matter of converting the number to BASE 26 and mapping the appropropriate characters to the digits.

Perl 5 solution

#!/usr/bin/perl
# Test: ./ch-1.pl 30
use strict;
use warnings;
use feature qw /say/;

say to_excel($ARGV[0]);

sub to_excel {
	my $n = shift;

	# Array to store digits
	my @digits;

	# Break down the digits to base 26
	while ($n > 0) {
		push @digits, ($n-1) % 26;
		$n = int(($n-1)/26);
	}

	# Join the digits
	return join '',
	       map { chr(ord('A') + $_) }
	       reverse @digits;
}

Output: perl ./ch-1.pl 30

AD

Raku solution

# Test: perl6 ch-1.p6 30
sub MAIN(Int $n) {
	say to-excel($n);
}


sub to-excel(Int $n is copy) {
	# Array to store digits
	my @digits;

	# Break down the digits to base 26
	while ($n > 0) {
		@digits.push(($n-1) % 26);
		$n = Int( ($n-1)/26 );
	}

	# Join the digits
	return @digits.reverse.map({ chr(ord('A') + .Int) }).join('');
}

Output perl6 ch-1.p6 30

AD

TASK #2 › Find Numbers

Reviewed by: Ryan Thompson

Write a script that accepts list of positive numbers (@L) and two positive numbers $X and $Y.

The script should print all possible numbers made by concatenating the numbers from @L, whose length is exactly $X but value is less than $Y.

Example

Input:

@L = (0, 1, 2, 5);
$X = 2;
$Y = 21;

Output:

10, 11, 12, 15, 20


For this challenge I just brute forced it by calculating all the variations of the concatenated numbers and checking that the length of the number matches $X and the value is less than $Y

Perl 5 solution

#!/usr/bin/perl
# Test: ./ch-2.pl

use strict;
use warnings;
use feature qw /say/;
use Algorithm::Combinatorics qw /variations/;

my @L = (0, 1, 2, 5);
my $X = 2;
my $Y = 21;
my @answers;

# Brute force the variations
my $variations = variations(\@L, $X);
while (my $v = $variations->next) {
	my $n = join '', @$v;
	$n = int($n);  #Remove leading 0
	push @answers, $n
		if ($n < $Y && length($n) == $X);
}

say join ', ', sort @answers;

Output

10, 12, 15, 20

Raku solution

# Test: perl6 ch-2.p6
sub MAIN() {
	my @L = (0, 1, 2, 5);
	my $X = 2;
	my $Y = 21;
	my @answers;

	# Brute force the variations
	my @combos = @L.combinations: $X;
	for @combos -> $combo {
		for $combo.permutations -> $perms {
			my $n = $perms.join('').Int;
			@answers.push($n)
				if ($n < $Y && $n.chars == $X);
		}
	}

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

Output

10, 12, 15, 20

One thought on “PERL WEEKLY CHALLENGE – 060

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