aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoririfkin <ianrifkin@ianrifkin.com>2023-11-26 10:05:36 -0500
committeririfkin <ianrifkin@ianrifkin.com>2023-11-26 10:05:36 -0500
commit2cbcaebea8b7040874a054e50d578d312ab369a5 (patch)
treee952a28e933b0721509937e916424ad9602a5728
parenta21c8ec426c8151d3b00e2e7e17d220992bea80f (diff)
downloadperlweeklychallenge-club-2cbcaebea8b7040874a054e50d578d312ab369a5.tar.gz
perlweeklychallenge-club-2cbcaebea8b7040874a054e50d578d312ab369a5.tar.bz2
perlweeklychallenge-club-2cbcaebea8b7040874a054e50d578d312ab369a5.zip
Perl solutions and a short blog post
-rw-r--r--challenge-244/ianrifkin/README.md135
-rw-r--r--challenge-244/ianrifkin/blog.txt1
-rw-r--r--challenge-244/ianrifkin/perl/ch-1.pl111
-rw-r--r--challenge-244/ianrifkin/perl/ch-2.pl100
4 files changed, 268 insertions, 79 deletions
diff --git a/challenge-244/ianrifkin/README.md b/challenge-244/ianrifkin/README.md
index 10bfcf4aa0..9e84586460 100644
--- a/challenge-244/ianrifkin/README.md
+++ b/challenge-244/ianrifkin/README.md
@@ -1,113 +1,90 @@
-# loop-de-loop
+# And then a hero comes along
-Challenge 243: https://theweeklychallenge.org/blog/perl-weekly-challenge-243/
+Challenge 244: https://theweeklychallenge.org/blog/perl-weekly-challenge-244/
-I decided to take what I think is a simple approcah to solving this week's problems (and I basically did the same approach in both tasks).
+This task was during the week of American Thanksgiving so I may not be fully present with my responses. The first task seemed straightforward enough so let's start with that one.
+
+## Task 1: Count Smaller
-## Task 1: Reverse Pairs
```
You are given an array of integers.
-Write a script to return the number of reverse pairs in the given array.
-
-A reverse pair is a pair (i, j) where: a) 0 <= i < j < nums.length and b) nums[i] > 2 * nums[j].
+Write a script to calculate the number of integers smaller than the integer at each index.
Example 1
-Input: @nums = (1, 3, 2, 3, 1)
-Output: 2
-
-(1, 4) => nums[1] = 3, nums[4] = 1, 3 > 2 * 1
-(3, 4) => nums[3] = 3, nums[4] = 1, 3 > 2 * 1
+Input: @int = (8, 1, 2, 2, 3)
+Output: (4, 0, 1, 1, 3)
+
+For index = 0, count of elements less 8 is 4.
+For index = 1, count of elements less 1 is 0.
+For index = 2, count of elements less 2 is 1.
+For index = 3, count of elements less 2 is 1.
+For index = 4, count of elements less 3 is 3.
Example 2
-Input: @nums = (2, 4, 3, 5, 1)
-Output: 3
-
-(1, 4) => nums[1] = 4, nums[4] = 1, 4 > 2 * 1
-(2, 4) => nums[2] = 3, nums[4] = 1, 3 > 2 * 1
-(3, 4) => nums[3] = 5, nums[4] = 1, 5 > 2 * 1
+Input: @int = (6, 5, 4, 8)
+Output: (2, 1, 0, 3)
+Example 3
+Input: @int = (2, 2, 2)
+Output: (0, 0, 0)
```
-I added some extra code to my solutions in support of features like supporting command-line input, but let's focus on the code that actually solves the task.
-
-I pass the `@nums` array to a subroutine `reverse_pairs` which has a nested `for` loop in it. We want to count how many times `$nums[$i]` is `>` `$nums[$j] * 2` where `$j` is any item after `$i` in the array. Since there is no point to look at an `$i` with no `$j` the parent loop should contain every array element except the last one:
-
+I solve this by looping through the `@int` array and creating an array for the output for each numbers total of numbers that are smaller than it (defaulting it to 0):
```
-for (my $i = 0; $i < @nums-1; $i++)
+for (my $i=0; $i < @int; $i++) {
+ $int_out[$i] = 0; #default is no number is smaller than it
```
-Within the above loop I created a nested loop to compare `$nums[$i]` to every value after it in the array. We know that `$j` is after `$i` so the loop can start at the element after `$i` and continues to the end of the array:
+Then I loop through the `@int` array again, this time to check each number in the array (except for itself) and increment the output number when needed:
```
-for (my $j = $i+1; $j < @nums; $j++)
+for (my $j=0; $j < @int; $j++) {
+ $int_out[$i]++ if ($int[$i] > $int[$j] && $i != $j);
+}
```
-Within that loop I increment a counter whenever `$nums[$i] > $nums[$j] * 2`
-
-The full sub is as follows:
+That's it! Other than that it's just calling the sub and outputting it in the desired format.
-```
-sub reverse_pairs {
- my @nums = @_;
- my $pairs_found = 0;
- for (my $i = 0; $i < @nums-1; $i++) {
- for (my $j = $i+1; $j < @nums; $j++) {
- $pairs_found++ if ($nums[$i] > $nums[$j] * 2);
- }
- }
- return $pairs_found;
-}
-```
+## Task 2: Group Hero
-## Task 2: Floor Sum
```
-You are given an array of positive integers (>=1).
+You are given an array of integers representing the strength.
-Write a script to return the sum of floor(nums[i] / nums[j]) where 0 <= i,j < nums.length. The floor() function returns the integer part of the division.
+Write a script to return the sum of the powers of all possible combinations; power is defined as the square of the largest number in a sequence, multiplied by the smallest.
Example 1
-Input: @nums = (2, 5, 9)
-Output: 10
-
-floor(2 / 5) = 0
-floor(2 / 9) = 0
-floor(5 / 9) = 0
-floor(2 / 2) = 1
-floor(5 / 5) = 1
-floor(9 / 9) = 1
-floor(5 / 2) = 2
-floor(9 / 2) = 4
-floor(9 / 5) = 1
-Example 2
-Input: @nums = (7, 7, 7, 7, 7, 7, 7)
-Output: 49
-```
+Input: @nums = (2, 1, 4)
+Output: 141
-My solution to this task is very similar to my approach to solving task 1. Again I start with a loop of every array item, but this time the parent loop does include the last element in the array:
-```
-for (my $i = 0; $i < @nums; $i++)
-```
+Group 1: (2) => square(max(2)) * min(2) => 4 * 2 => 8
+Group 2: (1) => square(max(1)) * min(1) => 1 * 1 => 1
+Group 3: (4) => square(max(4)) * min(4) => 16 * 4 => 64
+Group 4: (2,1) => square(max(2,1)) * min(2,1) => 4 * 1 => 4
+Group 5: (2,4) => square(max(2,4)) * min(2,4) => 16 * 2 => 32
+Group 6: (1,4) => square(max(1,4)) * min(1,4) => 16 * 1 => 16
+Group 7: (2,1,4) => square(max(2,1,4)) * min(2,1,4) => 16 * 1 => 16
-Likewise, the nested loop within it needs to include every element (including where `$i == $j`) so it's basically the same loop as its parent:
-```
-for (my $j = 0; $j < @nums; $j++)
+Sum: 8 + 1 + 64 + 4 + 32 + 16 + 16 => 141
```
-Within that loop I take the floor of `$nums[$i] / $nums[$j]` and add it to the sum of the previous values. To calculate the floor I was going to use the actual `floor()` from `POSIX` but just used `int()` -- I think it's good enough for this task but note that `int()` can sometimes produce counterintuitive results (see https://perldoc.perl.org/functions/int).
+This task was a lot more challenging for me and I'm not entirely sure I am solving it in a sane manner, but I do appear to get the correct output.
-The full sub is as follows:
+I created a subroutine `group_hero` which accepts the input array. I then use `Algorithm::Combinatorics qw(partitions)` to create the different number combinations. Is this cheating? Maybe, but I'm okay with it. Don't worry, it's not the only "cheat" I used in this one. I also use `List::Util qw( min max )` to calculuate the min and max values in an array!
+So I start byt creating the number combinations: `my @parts = partitions(\@nums);`
+
+The final array element in `@parts` is duplicative for our purposes so I ignore that. I loop through the rest of the parts: `for (my $i=0; $i<@parts-1; $i++) {`
+
+Each `$parts[$i]` is an array of the desired combinations so I loop through that: `foreach ( @{$parts[$i]} ) {`
+
+Within this final loop I calculate the min, max and perform the math:
```
-sub sum_floors {
- my @nums = @_;
- my $sum_floors = 0;
- for (my $i = 0; $i < @nums; $i++) {
- for (my $j = 0; $j < @nums; $j++) {
- $sum_floors += int($nums[$i] / $nums[$j]);
- }
- }
- return $sum_floors;
-}
+my $min = min @{$parts[0]};
+my $max = max @{$parts[0]};
+$group_hero += $max**2 * $min;
```
-The full code with comments is available at https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-243/ianrifkin \ No newline at end of file
+Then at the conclusion I return `$group_hero` with the final number.
+
+---
+The full code with comments is available at https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-244/ianrifkin
diff --git a/challenge-244/ianrifkin/blog.txt b/challenge-244/ianrifkin/blog.txt
new file mode 100644
index 0000000000..39bffa2018
--- /dev/null
+++ b/challenge-244/ianrifkin/blog.txt
@@ -0,0 +1 @@
+https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-244/ianrifkin#readme
diff --git a/challenge-244/ianrifkin/perl/ch-1.pl b/challenge-244/ianrifkin/perl/ch-1.pl
new file mode 100644
index 0000000000..b41e0c1ae1
--- /dev/null
+++ b/challenge-244/ianrifkin/perl/ch-1.pl
@@ -0,0 +1,111 @@
+use v5.30.3;
+use warnings;
+use strict;
+use Getopt::Long;
+use Pod::Usage;
+use Data::Dumper;
+
+# Task 1: Count Smaller
+
+my $man = 0;
+my $help = 0;
+my $str_input;
+GetOptions ('help|?' => \$help, man => \$man,
+ "nums=s" => \$str_input
+ )
+ or pod2usage(2);
+
+pod2usage(1) if $help;
+pod2usage(-exitstatus => 0, -verbose => 2) if $man;
+
+# Prepare input array
+my @int;
+# if values provided at cmd line split on comma
+if ( $str_input ) {
+ say reverse_pairs(split(/,/, $str_input));
+}
+# else set default values from example if no cmd line input
+else {
+ # Example 1
+ @int = (8, 1, 2, 2, 3);
+ say count_smaller(@int);
+
+ # Example 2
+ @int = (6, 5, 4, 8);
+ say count_smaller(@int);
+
+ # Example 3
+ @int = (2, 2, 2);
+ say count_smaller(@int);
+}
+
+sub count_smaller {
+ my @int = @_;
+ my @int_out;
+
+ # Loop through each number in array to count how many numbers are smaller than it
+ for (my $i=0; $i < @int; $i++) {
+ $int_out[$i] = 0; #default is no number is smaller than it
+ # check each number in the array except for self
+ for (my $j=0; $j < @int; $j++) {
+ $int_out[$i]++ if ($int[$i] > $int[$j] && $i != $j);
+ }
+ }
+
+ # Return the @output array in the desired format
+ $Data::Dumper::Terse = 1; #don't print VAR names
+ $Data::Dumper::Indent = 0; #keep output on one line
+ return '(' . join(',', Dumper(@int_out)) . ')';
+}
+
+__END__
+
+=head1 Challenge 244, Task 1: Count Smaller, by IanRifkin
+
+You are given an array of integers.
+
+Write a script to calculate the number of integers smaller than the integer at each index.
+
+Example 1
+Input: @int = (8, 1, 2, 2, 3)
+Output: (4, 0, 1, 1, 3)
+
+For index = 0, count of elements less 8 is 4.
+For index = 1, count of elements less 1 is 0.
+For index = 2, count of elements less 2 is 1.
+For index = 3, count of elements less 2 is 1.
+For index = 4, count of elements less 3 is 3.
+Example 2
+Input: @int = (6, 5, 4, 8)
+Output: (2, 1, 0, 3)
+Example 3
+Input: @int = (2, 2, 2)
+Output: (0, 0, 0)
+
+See https://theweeklychallenge.org/blog/perl-weekly-challenge-244/#TASK1 for more information on this challenge
+
+=head1 SYNOPSIS
+
+perl ./ch-1.pl [options]
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<-nums>
+
+A list of numbers
+
+=item B<-help>
+
+Print a brief help message and exits.
+
+=item B<-man>
+
+Prints the manual page and exits.
+
+=back
+
+
+
+
diff --git a/challenge-244/ianrifkin/perl/ch-2.pl b/challenge-244/ianrifkin/perl/ch-2.pl
new file mode 100644
index 0000000000..e15f62303b
--- /dev/null
+++ b/challenge-244/ianrifkin/perl/ch-2.pl
@@ -0,0 +1,100 @@
+use v5.30.3;
+use warnings;
+use strict;
+use Getopt::Long;
+use Pod::Usage;
+use Algorithm::Combinatorics qw(partitions);
+use List::Util qw( min max );
+use Data::Dumper;
+
+# Task 2: Group Hero
+
+my $man = 0;
+my $help = 0;
+my $str_input;
+GetOptions ('help|?' => \$help, man => \$man,
+ "nums=s" => \$str_input
+ )
+ or pod2usage(2);
+
+pod2usage(1) if $help;
+pod2usage(-exitstatus => 0, -verbose => 2) if $man;
+
+# Prepare input array
+my @nums;
+# if values provided at cmd line split on comma
+if ( $str_input ) {
+ say reverse_pairs(split(/,/, $str_input));
+}
+# else set default values from example if no cmd line input
+else {
+ # Example 1
+ @nums = (2, 1, 4);
+ say group_hero(@nums);
+}
+
+sub group_hero {
+ my @nums = @_;
+ my $group_hero = 0;
+
+ my @parts = partitions(\@nums);
+ for (my $i=0; $i<@parts-1; $i++) {
+ foreach ( @{$parts[$i]} ) {
+ my @parts = $_;
+ my $min = min @{$parts[0]};
+ my $max = max @{$parts[0]};
+ $group_hero += $max**2 * $min;
+ }
+ }
+ return $group_hero;
+}
+
+__END__
+
+=head1 Challenge 244, Task 2: Count Smaller, by IanRifkin
+
+You are given an array of integers representing the strength.
+
+Write a script to return the sum of the powers of all possible combinations; power is defined as the square of the largest number in a sequence, multiplied by the smallest.
+
+Example 1
+Input: @nums = (2, 1, 4)
+Output: 141
+
+Group 1: (2) => square(max(2)) * min(2) => 4 * 2 => 8
+Group 2: (1) => square(max(1)) * min(1) => 1 * 1 => 1
+Group 3: (4) => square(max(4)) * min(4) => 16 * 4 => 64
+Group 4: (2,1) => square(max(2,1)) * min(2,1) => 4 * 1 => 4
+Group 5: (2,4) => square(max(2,4)) * min(2,4) => 16 * 2 => 32
+Group 6: (1,4) => square(max(1,4)) * min(1,4) => 16 * 1 => 16
+Group 7: (2,1,4) => square(max(2,1,4)) * min(2,1,4) => 16 * 1 => 16
+
+Sum: 8 + 1 + 64 + 4 + 32 + 16 + 16 => 141
+
+See https://theweeklychallenge.org/blog/perl-weekly-challenge-244/#TASK2 for more information on this challenge
+
+=head1 SYNOPSIS
+
+perl ./ch-1.pl [options]
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<-nums>
+
+A list of numbers
+
+=item B<-help>
+
+Print a brief help message and exits.
+
+=item B<-man>
+
+Prints the manual page and exits.
+
+=back
+
+
+
+