Skip to content

Commit 9623763

Browse files
robbie-hatleyrobbie-hatley
robbie-hatley
authored and
robbie-hatley
committed
Robbie Hatley's Perl solutions to The Weekly Challenge manwar#245.
1 parent 313f3f8 commit 9623763

File tree

3 files changed

+278
-0
lines changed

3 files changed

+278
-0
lines changed

challenge-245/robbie-hatley/blog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
https://hatley-software.blogspot.com/2023/11/robbie-hatleys-solutions-to-weekly_29.html
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#!/usr/bin/env -S perl -CSDA
2+
3+
=pod
4+
5+
--------------------------------------------------------------------------------------------------------------
6+
COLOPHON:
7+
This is a 110-character-wide Unicode UTF-8 Perl-source-code text file with hard Unix line breaks ("\x0A").
8+
¡Hablo Español! Говорю Русский. Björt skjöldur. ॐ नमो भगवते वासुदेवाय. 看的星星,知道你是爱。麦藁雪、富士川町、山梨県。
9+
10+
--------------------------------------------------------------------------------------------------------------
11+
TITLE BLOCK:
12+
Solutions in Perl for The Weekly Challenge 245-1.
13+
Written by Robbie Hatley on Tue Nov 28, 2023.
14+
15+
--------------------------------------------------------------------------------------------------------------
16+
PROBLEM DESCRIPTION:
17+
Task 245-1: Sort Language
18+
Submitted by: Mohammad S Anwar
19+
You are given two arrays: one of languages and the other of their
20+
popularities. Write a script to sort the languages based on their
21+
popularities.
22+
23+
Example 1:
24+
Input: @lang = ('perl', 'c', 'python'); @popularity = (2, 1, 3);
25+
Output: ('c', 'perl', 'python')
26+
27+
Example 2:
28+
Input: @lang = ('c++', 'haskell', 'java'); @popularity = (1, 3, 2);
29+
Output: ('c++', 'java', 'haskell')
30+
31+
--------------------------------------------------------------------------------------------------------------
32+
PROBLEM NOTES:
33+
I tried solving this problem by "zipping" the two arrays together to make an array of [language, popularity]
34+
pairs, then sorting that array numerically by the second elements of the pairs; however, the resulting code
35+
was excessively verbose. But then I hit upon a much easier way: use an array slice! Take the indexes of the
36+
first array (0..$#$aref1), re-order them according to a sort of the second array, then "slice" the first
37+
array using the re-ordered indexes. The result was that I could now solve this entire problem with half a line
38+
of code.
39+
40+
--------------------------------------------------------------------------------------------------------------
41+
IO NOTES:
42+
Input is via either built-in variables or via @ARGV. If using @ARGV, provide one argument which must be a
43+
double-quoted array of arrays of two arrays, with the inner array pairs consisting of an array of
44+
single-quoted strings followed by an array of small positive integers (1-9), in proper Perl syntax, like so:
45+
./ch-1.pl "([['Go','Lisp','AutoIt3','Logo'],[2, 1, 4, 3]],[['Awk','Cobol','Perl','Sed'],[3,4,1,2]])"
46+
47+
Output is to STDOUT and will be each input array followed by the corresponding output.
48+
49+
=cut
50+
51+
# ------------------------------------------------------------------------------------------------------------
52+
# PRAGMAS AND MODULES USED:
53+
54+
use v5.38;
55+
use strict;
56+
use warnings;
57+
use utf8;
58+
use warnings FATAL => 'utf8';
59+
use Sys::Binmode;
60+
use Time::HiRes 'time';
61+
62+
# ------------------------------------------------------------------------------------------------------------
63+
# START TIMER:
64+
our $t0;
65+
BEGIN {$t0 = time}
66+
67+
# ------------------------------------------------------------------------------------------------------------
68+
# SUBROUTINES:
69+
70+
sub is_array_of_pos_ints($aref) {
71+
return 0 if 'ARRAY' ne ref $aref;
72+
for (@$aref) {
73+
return 0 if !/^[1-9]\d*$/;
74+
}
75+
return 1;
76+
}
77+
78+
sub sort_array1_by_array2($aref1, $aref2) {
79+
return @$aref1[sort{$$aref2[$a]<=>$$aref2[$b]}0..$#$aref1];
80+
}
81+
82+
# ------------------------------------------------------------------------------------------------------------
83+
# MAIN BODY OF PROGRAM:
84+
85+
# Inputs:
86+
my @arrays = @ARGV ? eval($ARGV[0]) :
87+
(
88+
# Example 1 Inputs:
89+
[
90+
['perl', 'c', 'python'],
91+
[2, 1, 3],
92+
],
93+
# Expected Output: ('c', 'perl', 'python')
94+
95+
# Example 2 Inputs:
96+
[
97+
['c++', 'haskell', 'java'],
98+
[1, 3, 2],
99+
],
100+
# Expected Output: ('c++', 'java', 'haskell')
101+
);
102+
103+
# Main loop:
104+
for my $aref (@arrays) {
105+
say '';
106+
my $aref1 = $aref->[0];
107+
my $aref2 = $aref->[1];
108+
say 'Languages = (' . join(', ', map {"'$_'"} @$aref1) . ')';
109+
say 'Popularities = (' . join(', ', @$aref2) . ')';
110+
if ( scalar(@$aref1) != scalar(@$aref2) ) {
111+
say 'Error: subarrays are of unequal lengths.';
112+
say 'Moving on to next array.';
113+
next;
114+
}
115+
if ( !is_array_of_pos_ints($aref2) ) {
116+
say 'Error: second subarray is not array of positive integers.';
117+
say 'Moving on to next array.';
118+
next;
119+
}
120+
my @sorted = sort_array1_by_array2($aref1, $aref2);
121+
say 'Sorted = (' . join(', ', map {"'$_'"} @sorted) . ')';
122+
}
123+
exit;
124+
125+
# ------------------------------------------------------------------------------------------------------------
126+
# DETERMINE AND PRINT EXECUTION TIME:
127+
END {mys = 1000000 * (time - $t0);printf("\nExecution time was %.0fµs.\n", $µs)}
128+
__END__
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#!/usr/bin/env -S perl -CSDA
2+
3+
=pod
4+
5+
--------------------------------------------------------------------------------------------------------------
6+
COLOPHON:
7+
This is a 110-character-wide Unicode UTF-8 Perl-source-code text file with hard Unix line breaks ("\x0A").
8+
¡Hablo Español! Говорю Русский. Björt skjöldur. ॐ नमो भगवते वासुदेवाय. 看的星星,知道你是爱。麦藁雪、富士川町、山梨県。
9+
10+
--------------------------------------------------------------------------------------------------------------
11+
TITLE BLOCK:
12+
Solutions in Perl for The Weekly Challenge 245-2.
13+
Written by Robbie Hatley on Tue Nov 28, 2023.
14+
15+
--------------------------------------------------------------------------------------------------------------
16+
PROBLEM DESCRIPTION:
17+
Task 245-2: Largest of Three
18+
Submitted by: Mohammad S Anwar
19+
You are given an array of integers >= 0. Write a script to return
20+
the largest number formed by concatenating some of the given
21+
integers in any order which is also multiple of 3. Return -1 if
22+
none found.
23+
24+
Example 1:
25+
Input: @ints = (8, 1, 9)
26+
Output: 981
27+
981 % 3 == 0
28+
29+
Example 2:
30+
Input: @ints = (8, 6, 7, 1, 0)
31+
Output: 8760
32+
33+
Example 3:
34+
Input: @ints = (1)
35+
Output: -1
36+
37+
--------------------------------------------------------------------------------------------------------------
38+
PROBLEM NOTES:
39+
This WOULD BE just a matter of combinatorics if not for the fact that no upper bound is given for our
40+
non-negative integers. That means that we'll be "concatenating" integers with possibly more-than-one digit,
41+
so we can't just assume that each integer is one digit then concatenate all permutations of all combinations.
42+
Instead, we need to make a "sub concatenate($aref)" which first splits each input into its digits, then
43+
pushes those clusters of digits onto an array, then joins that array. Also we'll need a "sub are_nni($aref)"
44+
to check that all inputs are non-negative integers, and a "sub largest_of_three($aref)" to find the largest
45+
multiple of 3 we can make or return -1 if we can't make any. THEN the rest is just permutations of
46+
combinations. More work for CPAN module "Math::Combinatorics". This time I'll use it's non-OOP functions,
47+
as OOP just isn't necessary for a problem like this, and indeed just gets in the way.
48+
49+
--------------------------------------------------------------------------------------------------------------
50+
IO NOTES:
51+
Input is via either built-in variables or via @ARGV. If using @ARGV, provide one argument which must be a
52+
single-quoted array of arrays of non-negative integers, in proper Perl syntax, like so:
53+
./ch-2.pl '([3,14,0,5,72],[1,0,97,23])'
54+
55+
Output is to STDOUT and will be each input array followed by the corresponding output.
56+
57+
=cut
58+
59+
# ------------------------------------------------------------------------------------------------------------
60+
# PRAGMAS AND MODULES USED:
61+
62+
use v5.38;
63+
use strict;
64+
use warnings;
65+
use utf8;
66+
use warnings FATAL => 'utf8';
67+
use Sys::Binmode;
68+
use Time::HiRes 'time';
69+
use Math::Combinatorics;
70+
71+
# ------------------------------------------------------------------------------------------------------------
72+
# START TIMER:
73+
our $t0;
74+
BEGIN {$t0 = time}
75+
76+
# ------------------------------------------------------------------------------------------------------------
77+
# SUBROUTINES:
78+
79+
# Are all of the elements of a referred-to array decimal representations of non-negative integers?
80+
sub are_nni ($aref) {
81+
return 0 if 'ARRAY' ne ref $aref;
82+
return 0 if scalar(@$aref) < 1;
83+
for (@$aref) {return 0 if !/^0$|^[1-9]\d*$/}
84+
return 1;
85+
}
86+
87+
sub concatenate($aref) {
88+
my @digits;
89+
for (@$aref) {push @digits, split(//,$_)}
90+
return join('',@digits);
91+
}
92+
93+
sub largest_of_three($aref) {
94+
# For each possible non-empty subset size of @$aref, get all combinations
95+
# of that size, then get all permutations of each of those combinations,
96+
# then concatentate each of those permutations to an integer, and keep track
97+
# of the maximum divisible-by-3 integer seen, then return the maximum
98+
# which will be -1 if we couldn't make any divisible-by-3 integers:
99+
my $max = -1;
100+
for ( my $size = scalar(@$aref) ; $size >= 1 ; --$size ) {
101+
my @combs = combine($size,@$aref);
102+
for my $cref ( @combs ) {
103+
my @perms = permute(@$cref);
104+
for my $pref ( @perms ) {
105+
my $integer = concatenate($pref);
106+
0 == $integer % 3 && $integer > $max and $max = $integer;
107+
}
108+
}
109+
}
110+
return $max;
111+
}
112+
113+
# ------------------------------------------------------------------------------------------------------------
114+
# MAIN BODY OF PROGRAM:
115+
116+
# Inputs:
117+
my @arrays = @ARGV ? eval($ARGV[0]) :
118+
(
119+
# Example 1 Input:
120+
[8, 1, 9],
121+
# Expected Output: 981
122+
123+
# Example 2 Input:
124+
[8, 6, 7, 1, 0],
125+
# Expected Output: 8760
126+
127+
# Example 3 Input:
128+
[1],
129+
# Expected Output: -1
130+
);
131+
132+
# Main loop:
133+
for my $aref (@arrays) {
134+
say '';
135+
say 'Array = (' . join(', ', @$aref) . ')';
136+
if ( !are_nni($aref) ) {
137+
say 'Error: not an array of non-negative integers.';
138+
say 'Moving on to next array.';
139+
next;
140+
}
141+
say 'Greatest multiple of 3 creatable from array = ',
142+
largest_of_three($aref);
143+
}
144+
exit;
145+
146+
# ------------------------------------------------------------------------------------------------------------
147+
# DETERMINE AND PRINT EXECUTION TIME:
148+
END {mys = 1000000 * (time - $t0);printf("\nExecution time was %.0fµs.\n", $µs)}
149+
__END__

0 commit comments

Comments
 (0)