diff options
| author | Jared Martin <jaredor+github@gmail.com> | 2020-05-16 23:42:00 -0500 |
|---|---|---|
| committer | Jared Martin <jaredor+github@gmail.com> | 2020-05-16 23:42:00 -0500 |
| commit | 533cfc058ad950549c5e1881eefa69aead5132b5 (patch) | |
| tree | ee796f127a113a90f27e1bb39aa9a02c9751d63b /challenge-060/jaredor | |
| parent | 16b5c61e73278b37d483e0153ee9455d7c9b3be9 (diff) | |
| download | perlweeklychallenge-club-533cfc058ad950549c5e1881eefa69aead5132b5.tar.gz perlweeklychallenge-club-533cfc058ad950549c5e1881eefa69aead5132b5.tar.bz2 perlweeklychallenge-club-533cfc058ad950549c5e1881eefa69aead5132b5.zip | |
Final submissions for PWC 060
Diffstat (limited to 'challenge-060/jaredor')
| -rwxr-xr-x | challenge-060/jaredor/perl/ch-1.pl | 33 | ||||
| -rwxr-xr-x | challenge-060/jaredor/perl/ch-2.pl | 159 |
2 files changed, 192 insertions, 0 deletions
diff --git a/challenge-060/jaredor/perl/ch-1.pl b/challenge-060/jaredor/perl/ch-1.pl new file mode 100755 index 0000000000..dc56e885f6 --- /dev/null +++ b/challenge-060/jaredor/perl/ch-1.pl @@ -0,0 +1,33 @@ +#!/usr/bin/env perl + +use v5.012; +use warnings; +use integer; +use List::Util qw(reduce all); + +# PWC 060, TASK #1 : Excel Column + +my ( @alpha, %trans ) = ( 'A' .. 'Z', ); +@trans{ @alpha, keys @alpha } = ( keys(@alpha), @alpha, ); + +sub num_to_col { + my ( $num, @col ) = ( $_[0], ); + push @col, ( $num - 1 ) % 26 and $num = ( $num - 1 ) / 26 while $num; + return join( '', reverse @trans{@col} ); +} + +sub col_to_num { + return 1 + reduce { 26 * ( $a + 1 ) + $b } @trans{ split( '', $_[0] ) }; +} + +my @inargs = map { s/\b 0+ \B//xms; uc($_) } @ARGV; + +die "Input is not a list consisting of " + . "either alphabetic strings or positive integers." + unless all { /\A [0-9A-Z]+ \Z/xms and $_ ne '0' } @inargs; + +for my $inarg (@inargs) { + my $type = $inarg =~ /\d/ ? 'Number' : 'Column Name'; + my $output = $type eq 'Number' ? num_to_col $inarg : col_to_num $inarg; + say "\nInput $type: $inarg\nOutput: $output"; +} diff --git a/challenge-060/jaredor/perl/ch-2.pl b/challenge-060/jaredor/perl/ch-2.pl new file mode 100755 index 0000000000..8f149eef48 --- /dev/null +++ b/challenge-060/jaredor/perl/ch-2.pl @@ -0,0 +1,159 @@ +#!/usr/bin/env perl + +use v5.012; +use warnings; +use integer; +use Getopt::Long; +use Pod::Usage; +use List::Util qw(uniq any min); + +Getopt::Long::Configure( 'bundling_values', 'ignorecase_always', + 'pass_through' ); + +GetOptions( + 'X=i' => \( my $X ), + 'Y=i' => \( my $Y ), + 'help|h!' => \( my $help ), + 'task|t!' => \( my $task ) +); + +pod2usage(1) if $help; +pod2usage( -exitval => 0, -verbose => 2 ) if $task; + +my @errors; +push @errors, "Required --X option must be a positive integer." + unless defined $X and $X > 0; +push @errors, "Required --Y option must be a positive integer." + unless defined $Y and $Y > 0; +push @errors, "One or more non-negative numbers must be given." + unless @ARGV; +pod2usage( join "\n", map { "ERROR: " . $_ } @errors ) if @errors; + +my $nmax = $Y - 1; + +die "The maximum valid value, $nmax, is too small to be of length $X." + unless length($nmax) >= $X; + +my $nums; +push @{ $nums->{ length $_ } }, $_ for uniq sort { $a <=> $b } @ARGV; + +my ( $minv, $maxv ) = ( 10**( $X - 1 ), 10**$X ); +$minv = 0 if $X == 1 and any { $_ == 0 } @{ $nums->{1} }; + +sub get_all_substrs { + my ( $lim, $len, $nums, $not_first_recursion ) = @_; + return ( '', ) unless $len; + my %nums = %{$nums}; + $_ > $len and delete $nums{$_} for keys %nums; + my $keylen_min = min keys %nums; + return ( '', ) unless defined $keylen_min; + my @results; + for my $numlen ( keys %nums ) { + my $newlen = $len - $numlen; + if ($newlen) { + for my $num ( @{ $nums{$numlen} } ) { + next unless $not_first_recursion or $num; + my $beglim = substr( $lim, 0, $numlen ); + my $newlim = + $num < $beglim ? '9' x $newlen + : $num == $beglim ? substr( $lim, $numlen ) + : undef; + push @results, + map { $num . $_ } + get_all_substrs( $newlim, $newlen, \%nums, 1 ) + if defined $newlim and $newlen >= $keylen_min; + } + } + else { + push @results, grep { $_ <= $lim } @{ $nums{$numlen} }; + } + } + return @results; +} + +my @output = sort { $a <=> $b } get_all_substrs( $nmax, $X, $nums ); + +if (@output) { + say join ", ", @output; +} +else { + die "No strings of length $X less than value $Y can be formed."; +} + +__END__ + +=head1 NAME + +PWC 059, TASK #2 : Find Numbers + +=head1 SYNOPSIS + + ch-2.pl [options] [nonnegint ... ] + + Options: + --X length of answer string + --Y Upper bound, exclusive, answer string value + --help Brief help + --task Full description + + Arguments: + One or more non-negative integers to be used in constructing an answer + +=head1 OPTIONS + +=over 8 + +=item B<--X> + +The required length of any numerical string produced as result. + +=item B<--Y> + +The upper numerical bound any result must be less than. + +=item B<--help> + +Brief help message. + +=item B<--task> + +Complete description of task and the script's attempt to satisfy it. + +=back + +=head1 DESCRIPTION + +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. + +=head2 Example + +=head3 Input: + + @L = (0, 1, 2, 5); + $X = 2; + $Y = 21; + +=head3 Output: + + 10, 11, 12, 15, 20 + +=head1 INTERPRETATION + +Though the task statement says "list of positive numbers" for input arguments, +the example includes 0 in the list and it is used in constructing an answer. +Accordingly, allow 0 as an argument, changing the requirement to "list of +non-negative numbers." Actually, the script effectively changes the requirement +to "list of non-negative integers" because concatenation with floating point +numbers is probably not desired. + +Since the output in the example has "11" as an answer with the only input with a +"1" digit being the number "1" itself, the script is written to allow reuse of +elements. + +Because octal numbers are a pain and because the task example doesn't have the +digit 0 as a leading digit, e.g., using 05 as an output result, if 0 is in the +"list of non-negative integers" it is not allowed to be a leading digit, except +for the case where it is the only digit, i.e., 0. +=cut |
