From 2cbcaebea8b7040874a054e50d578d312ab369a5 Mon Sep 17 00:00:00 2001 From: irifkin Date: Sun, 26 Nov 2023 10:05:36 -0500 Subject: Perl solutions and a short blog post --- challenge-244/ianrifkin/README.md | 135 +++++++++++++++-------------------- challenge-244/ianrifkin/blog.txt | 1 + challenge-244/ianrifkin/perl/ch-1.pl | 111 ++++++++++++++++++++++++++++ challenge-244/ianrifkin/perl/ch-2.pl | 100 ++++++++++++++++++++++++++ 4 files changed, 268 insertions(+), 79 deletions(-) create mode 100644 challenge-244/ianrifkin/blog.txt create mode 100644 challenge-244/ianrifkin/perl/ch-1.pl create mode 100644 challenge-244/ianrifkin/perl/ch-2.pl 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 + + + + -- cgit From 4c7c82fd82af45e00923f93b2cc41558f0c7c10e Mon Sep 17 00:00:00 2001 From: irifkin Date: Wed, 29 Nov 2023 14:37:11 -0500 Subject: Perl solution for ch. 245 and initial draft of short blog post --- challenge-245/ianrifkin/README.md | 82 +++++++++++++++++++++++++++ challenge-245/ianrifkin/blog.txt | 1 + challenge-245/ianrifkin/perl/ch-1.pl | 77 +++++++++++++++++++++++++ challenge-245/ianrifkin/perl/ch-2.pl | 107 +++++++++++++++++++++++++++++++++++ 4 files changed, 267 insertions(+) create mode 100644 challenge-245/ianrifkin/README.md create mode 100644 challenge-245/ianrifkin/blog.txt create mode 100644 challenge-245/ianrifkin/perl/ch-1.pl create mode 100644 challenge-245/ianrifkin/perl/ch-2.pl diff --git a/challenge-245/ianrifkin/README.md b/challenge-245/ianrifkin/README.md new file mode 100644 index 0000000000..6d044c531d --- /dev/null +++ b/challenge-245/ianrifkin/README.md @@ -0,0 +1,82 @@ +# Language popularity and largest of 3 + +Challenge 245: https://theweeklychallenge.org/blog/perl-weekly-challenge-245/ + +## Task 1: Sort Language + +``` +You are given two array of languages and its popularity. + +Write a script to sort the language based on popularity. + +Example 1 +Input: @lang = ('perl', 'c', 'python') + @popularity = (2, 1, 3) +Output: ('c', 'perl', 'python') +Example 2 +Input: @lang = ('c++', 'haskell', 'java') + @popularity = (1, 3, 2) +Output: ('c++', 'java', 'haskell') +``` + +My first instinct to solve this was to align the two arrays (lang and popularity) into a hash. While this made sense I quickly realized I would still have the step of sorting based on the keys. This should still have worked but since the arrays have the same indices I didn't really need to combine them into a hash. + +I sorted the popularity array and outputted the indices in sort order (not the values): +`my @pop_sort_idx = sort { $popularity[$a] <=> $popularity[$b] } 0 .. $#popularity;` + +With that I return an array of the languages in sort order using the inputted langage array in the order of the sorted popularity: `@lang[@pop_sort_idx];` + +## Task 2: Largest of Three + +``` +You are given an array of integers >= 0. + +Write a script to return the largest number formed by concatenating some of the given integers in any order which is also multiple of 3. Return -1 if none found. + + +Example 1 +Input: @ints = (8, 1, 9) +Output: 981 + +981 % 3 == 0 +Example 2 +Input: @ints = (8, 6, 7, 1, 0) +Output: 8760 +Example 3 +Input: @ints = (1) +Output: -1 +``` + +This was fun to think through. The first part of the problem is to create an array of all potential numbers sorted from biggest to smallest. The second part of the problem is simpler -- ouput the biggest number (if available) that is divisible by 3. + +In Challenge 244 I used Algorithm::Combinatoric::partitions so I decided to start with that again here. I take the input number and use `partitions` to generate the various "partitions" e.g. for 9,8,1 it is: 981, 98, 91, 9, 81, 8, 1. +``` +my @parts = partitions(\@ints); +``` + +This only gets me part of the way there. I then need each of those numbers in every order (e.g. I need 89 in addition to 98). I decided to use Algorithm::Permute to take the partitions and create all these permutations. +``` +for (my $i=0; $i<@parts-1; $i++) { + foreach ( @{$parts[$i]} ) { + my @parts = $_; + my $p_iterator = Algorithm::Permute->new ( \@{$parts[0]} ); +``` + +Finally I will take the output from Algorithm::Permute and push it into an array of all the numbers to try: +``` +while (my @perm = $p_iterator->next) { + push(@numbers_to_try, join('', @perm)); +} +``` + +At this point I have a randomly sorted array of every number to try. I next need to find out which number (if any) is the largest number divisible by 3. +``` +foreach my $num_2_try (sort { $b <=> $a } @numbers_to_try) { + return $num_2_try unless $num_2_try % 3; +} +``` + +The above loop will return the first number (the largest number) divisible by 3. If it doesn't find one then after this loop there is a `return -1` so that the default behavoir matches the requirements. + +--- +The full code with comments is available at https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-245/ianrifkin diff --git a/challenge-245/ianrifkin/blog.txt b/challenge-245/ianrifkin/blog.txt new file mode 100644 index 0000000000..74387c5aab --- /dev/null +++ b/challenge-245/ianrifkin/blog.txt @@ -0,0 +1 @@ +https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-245/ianrifkin#readme diff --git a/challenge-245/ianrifkin/perl/ch-1.pl b/challenge-245/ianrifkin/perl/ch-1.pl new file mode 100644 index 0000000000..cdcfe89983 --- /dev/null +++ b/challenge-245/ianrifkin/perl/ch-1.pl @@ -0,0 +1,77 @@ +use v5.30.3; +use warnings; +use strict; +use Getopt::Long; +use Pod::Usage; + +# Task 1: Sort Language + +my $man = 0; +my $help = 0; +GetOptions ('help|?' => \$help, man => \$man + ) + or pod2usage(2); + +pod2usage(1) if $help; +pod2usage(-exitstatus => 0, -verbose => 2) if $man; + +# Example 1 +my @lang = ('perl', 'c', 'python'); +my @popularity = (2, 1, 3); +say sort_lang(\@lang, \@popularity); +#Output: ('c', 'perl', 'python') + +#Example 2 +@lang = ('c++', 'haskell', 'java'); +@popularity = (1, 3, 2); +say sort_lang(\@lang, \@popularity); +#Output: ('c++', 'java', 'haskell') + +sub sort_lang { + my ($lang, $popularity) = @_; + # Get indices of popularity array in sort order + my @pop_sort_idx = sort { $popularity[$a] <=> $popularity[$b] } 0 .. $#popularity; + # Return sorted language array using indices of sorted popularity numbers + return "@lang[@pop_sort_idx]"; +} + +__END__ + +=head1 Challenge 245, Task 1: Sort Language, by IanRifkin + +You are given two array of languages and its popularity. + +Write a script to sort the language based on popularity. + +Example 1 +Input: @lang = ('perl', 'c', 'python') + @popularity = (2, 1, 3) +Output: ('c', 'perl', 'python') +Example 2 +Input: @lang = ('c++', 'haskell', 'java') + @popularity = (1, 3, 2) +Output: ('c++', 'java', 'haskell') + +See https://theweeklychallenge.org/blog/perl-weekly-challenge-245/#TASK1 for more information on this challenge + +=head1 SYNOPSIS + +perl ./ch-1.pl [options] + +=head1 OPTIONS + +=over 8 + +=item B<-help> + +Print a brief help message and exits. + +=item B<-man> + +Prints the manual page and exits. + +=back + + + + diff --git a/challenge-245/ianrifkin/perl/ch-2.pl b/challenge-245/ianrifkin/perl/ch-2.pl new file mode 100644 index 0000000000..0ed48deed8 --- /dev/null +++ b/challenge-245/ianrifkin/perl/ch-2.pl @@ -0,0 +1,107 @@ +use v5.30.3; +use warnings; +use strict; +use Getopt::Long; +use Pod::Usage; +use Algorithm::Permute; +use Algorithm::Combinatorics qw(partitions); + + +# Task 2: Largest of Three + +my $man = 0; +my $help = 0; +GetOptions ('help|?' => \$help, man => \$man + ) + or pod2usage(2); + +pod2usage(1) if $help; +pod2usage(-exitstatus => 0, -verbose => 2) if $man; + +# Example 1 +my @ints = (8, 1, 9); +say largest(@ints); +# Output: 981 + +# Example 2 +@ints = (8, 6, 7, 1, 0); +say largest(@ints); +# Output: 8760 + +# Example 3 +@ints = (1); +say largest(@ints); +# Output: -1 + +sub largest { + my @ints = @_; #input array of indidviual ints + + # form an an array of all the possible numbers to try + my @numbers_to_try; + # use Algorithm::Combinatoric::partitions to generate all the combinations of numbers + # e.g. for 9,8,1 it is: 981, 98, 91, 9, 81, 8, 1 + my @parts = partitions(\@ints); + for (my $i=0; $i<@parts-1; $i++) { + foreach ( @{$parts[$i]} ) { + my @parts = $_; + # use Algorithm::Permute to take the partitions and create every order of the numbers + # e.g. for an input of 91 it would output 91 and 19 + my $p_iterator = Algorithm::Permute->new ( \@{$parts[0]} ); + while (my @perm = $p_iterator->next) { + push(@numbers_to_try, join('', @perm)); + } + } + } + + # Use array of potential numbers in numerical descending sort order + # to determine if any are divisible by 3 + foreach my $num_2_try (sort { $b <=> $a } @numbers_to_try) { + # return the first (biggest) number found + return $num_2_try unless $num_2_try % 3; + } + return -1 #default return value of -1 if no number found +} + +__END__ + +=head1 Challenge 245, Task 2: Largest of Three, by IanRifkin + +You are given an array of integers >= 0. + +Write a script to return the largest number formed by concatenating some of the given integers in any order which is also multiple of 3. Return -1 if none found. + +Example 1 +Input: @ints = (8, 1, 9) +Output: 981 + +981 % 3 == 0 +Example 2 +Input: @ints = (8, 6, 7, 1, 0) +Output: 8760 +Example 3 +Input: @ints = (1) +Output: -1 + +See https://theweeklychallenge.org/blog/perl-weekly-challenge-245/#TASK2 for more information on this challenge + +=head1 SYNOPSIS + +perl ./ch-1.pl [options] + +=head1 OPTIONS + +=over 8 + +=item B<-help> + +Print a brief help message and exits. + +=item B<-man> + +Prints the manual page and exits. + +=back + + + + -- cgit From e678c347452eaab29ee620d6699bd09f979d5a3e Mon Sep 17 00:00:00 2001 From: irifkin Date: Wed, 29 Nov 2023 14:39:37 -0500 Subject: README formatting --- challenge-245/ianrifkin/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/challenge-245/ianrifkin/README.md b/challenge-245/ianrifkin/README.md index 6d044c531d..d9c9e325ba 100644 --- a/challenge-245/ianrifkin/README.md +++ b/challenge-245/ianrifkin/README.md @@ -22,9 +22,10 @@ Output: ('c++', 'java', 'haskell') My first instinct to solve this was to align the two arrays (lang and popularity) into a hash. While this made sense I quickly realized I would still have the step of sorting based on the keys. This should still have worked but since the arrays have the same indices I didn't really need to combine them into a hash. I sorted the popularity array and outputted the indices in sort order (not the values): -`my @pop_sort_idx = sort { $popularity[$a] <=> $popularity[$b] } 0 .. $#popularity;` +```my @pop_sort_idx = sort { $popularity[$a] <=> $popularity[$b] } 0 .. $#popularity;``` -With that I return an array of the languages in sort order using the inputted langage array in the order of the sorted popularity: `@lang[@pop_sort_idx];` +With that I return an array of the languages in sort order using the inputted langage array in the order of the sorted popularity: +```@lang[@pop_sort_idx];``` ## Task 2: Largest of Three -- cgit From 25917d1892085b04f55d9da828f6be65421b27df Mon Sep 17 00:00:00 2001 From: irifkin Date: Wed, 29 Nov 2023 15:56:36 -0500 Subject: readme title and formatting --- challenge-245/ianrifkin/README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/challenge-245/ianrifkin/README.md b/challenge-245/ianrifkin/README.md index d9c9e325ba..86cce400cb 100644 --- a/challenge-245/ianrifkin/README.md +++ b/challenge-245/ianrifkin/README.md @@ -1,7 +1,9 @@ -# Language popularity and largest of 3 +# I'm never last picked Challenge 245: https://theweeklychallenge.org/blog/perl-weekly-challenge-245/ +This week we have a task to sort an array based on another array and a task to calculate the largest number combination from a given input that is divisible by 3. + ## Task 1: Sort Language ``` @@ -22,10 +24,14 @@ Output: ('c++', 'java', 'haskell') My first instinct to solve this was to align the two arrays (lang and popularity) into a hash. While this made sense I quickly realized I would still have the step of sorting based on the keys. This should still have worked but since the arrays have the same indices I didn't really need to combine them into a hash. I sorted the popularity array and outputted the indices in sort order (not the values): -```my @pop_sort_idx = sort { $popularity[$a] <=> $popularity[$b] } 0 .. $#popularity;``` +``` +my @pop_sort_idx = sort { $popularity[$a] <=> $popularity[$b] } 0 .. $#popularity; +``` With that I return an array of the languages in sort order using the inputted langage array in the order of the sorted popularity: -```@lang[@pop_sort_idx];``` +``` +@lang[@pop_sort_idx]; +``` ## Task 2: Largest of Three -- cgit From f313cf8c5750187d2d5307f82f1f62980c990265 Mon Sep 17 00:00:00 2001 From: irifkin Date: Thu, 30 Nov 2023 13:57:43 -0500 Subject: adding a python solution and updating readme blog post --- challenge-245/ianrifkin/README.md | 43 +++++++++++++++++++++ challenge-245/ianrifkin/python/ch-1.py | 32 ++++++++++++++++ challenge-245/ianrifkin/python/ch-2.py | 69 ++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 challenge-245/ianrifkin/python/ch-1.py create mode 100644 challenge-245/ianrifkin/python/ch-2.py diff --git a/challenge-245/ianrifkin/README.md b/challenge-245/ianrifkin/README.md index 86cce400cb..9c60e93a61 100644 --- a/challenge-245/ianrifkin/README.md +++ b/challenge-245/ianrifkin/README.md @@ -33,6 +33,18 @@ With that I return an array of the languages in sort order using the inputted la @lang[@pop_sort_idx]; ``` +I also solved this task only slightly differently with Python. I first created a list combining the `popularity` and `lang` lists using `zip`: +``` +sorted_langs_with_pop = sorted(zip(popularity,lang)) +``` + +I then use that to create the desired output of just the languages in the sort order: +``` +[lang for _,lang in sorted_langs_with_pop] +``` + +That could have been in one line but I thought it was clearer in the two distinct steps. + ## Task 2: Largest of Three ``` @@ -85,5 +97,36 @@ foreach my $num_2_try (sort { $b <=> $a } @numbers_to_try) { The above loop will return the first number (the largest number) divisible by 3. If it doesn't find one then after this loop there is a `return -1` so that the default behavoir matches the requirements. + +Again with this task I wanted to see how to solve it using Python. It is a fairly similar approach but I of course don't have the Perl modules available; instead I used `itertools:permutations` which is native to Python. + +`itertools:permutations` can have a length to its output but I don't see a way for it to provide a dynamic length like we need. Instead I loop through the list length so that I can run the permutations for each length: +``` +for i in range(len(nums)): + num_of_digits = i+1 + perms = list(permutations(nums, num_of_digits)) +``` + +That creates a list of tuples, but I need the tuples to be combined into actual numbers to try: +``` + for group_of_digits in perms: + combined_digits = int("".join(map(str, group_of_digits))) + numbers_to_try.append(combined_digits) +``` + +Now I have an unsorted list of numbers to try, so next comes the sorting: +``` +numbers_to_try.sort(reverse=True) +``` + +The final step, like in the Perl solution, is to return the first (largest) number divisible by 3, otherwise return -1: +``` +for num2try in numbers_to_try: + if num2try % 3 == 0: + return num2try +return -1 +``` + + --- The full code with comments is available at https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-245/ianrifkin diff --git a/challenge-245/ianrifkin/python/ch-1.py b/challenge-245/ianrifkin/python/ch-1.py new file mode 100644 index 0000000000..54d125e553 --- /dev/null +++ b/challenge-245/ianrifkin/python/ch-1.py @@ -0,0 +1,32 @@ +#!/usr/local/bin/python3 +import sys + +# Task 1: Sort Language + +# See https://theweeklychallenge.org/blog/perl-weekly-challenge-245/#TASK1 for more information on this challenge + +# You are given two array of languages and its popularity. +# Write a script to sort the language based on popularity. + +def main(argv): + # Example 1 + lang = ('perl', 'c', 'python') + popularity = (2, 1, 3) + print( sort_languages(lang, popularity) ) + #Output: ('c', 'perl', 'python') + + # Example 2 + lang = ('c++', 'haskell', 'java') + popularity = (1, 3, 2) + print( sort_languages(lang, popularity) ) + #Output: ('c++', 'java', 'haskell') + +def sort_languages(lang,popularity): + # Create a single list based on the two inputted lists + sorted_langs_with_pop = sorted(zip(popularity,lang)) + # Created a sorted list using the above list but only with the languages + sorted_langs = [lang for _,lang in sorted_langs_with_pop] + return sorted_langs + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/challenge-245/ianrifkin/python/ch-2.py b/challenge-245/ianrifkin/python/ch-2.py new file mode 100644 index 0000000000..8af7ea3f1e --- /dev/null +++ b/challenge-245/ianrifkin/python/ch-2.py @@ -0,0 +1,69 @@ +#!/usr/local/bin/python3 +import sys, argparse +import math +from itertools import permutations + +# Task 2: Largest of Three + +# You are given an array of integers >= 0. + +# Write a script to return the largest number formed by concatenating some of the given integers in any order which is also multiple of 3. Return -1 if none found. + +# See https://theweeklychallenge.org/blog/perl-weekly-challenge-245/#TASK2 for more information on this challenge + +def main(argv): + argParser = argparse.ArgumentParser() + argParser.add_argument("-n", "--nums", nargs='+', type=int, help="space seperated list of positive integers e.g. -n 10 30 4 5") + args = argParser.parse_args() + + if args.nums: + nums = args.nums + print( largest(nums) ) + else: + # Example 1 + nums = [8, 1, 9] + print( largest(nums) ) + #Output: 981 + + # Example 2 + nums = [8, 6, 7, 1, 0] + print( largest(nums) ) + #Output: 8760 + + # Example 3 + nums = [1] + print( largest(nums) ) + #Output: -1 + + +def largest(nums): + numbers_to_try = [] + for i in range(len(nums)): + num_of_digits = i+1 + perms = list(permutations(nums, num_of_digits)) + + for group_of_digits in perms: + combined_digits = int("".join(map(str, group_of_digits))) + numbers_to_try.append(combined_digits) + + numbers_to_try.sort(reverse=True) + + for num2try in numbers_to_try: + if num2try % 3 == 0: + return num2try + return -1 + + + # # Use array of potential numbers in numerical descending sort order + # # to determine if any are divisible by 3 + # foreach my $num_2_try (sort { $b <=> $a } @numbers_to_try) { + # # return the first (biggest) number found + # return $num_2_try unless $num_2_try % 3; + # } + # return -1 #default return value of -1 if no number found + + + + +if __name__ == "__main__": + main(sys.argv[1:]) -- cgit