diff options
| author | irifkin <ianrifkin@ianrifkin.com> | 2023-11-02 15:05:40 -0400 |
|---|---|---|
| committer | irifkin <ianrifkin@ianrifkin.com> | 2023-11-02 15:05:40 -0400 |
| commit | 25b7cd78a7df9fff61c3975713fae77b3ca8eadd (patch) | |
| tree | 2ced6ebb0f06258f0bb584c54988c08bd588ca7b /challenge-241 | |
| parent | ae3e42824c7cb46ce76f5c9a795693a6b27afaac (diff) | |
| download | perlweeklychallenge-club-25b7cd78a7df9fff61c3975713fae77b3ca8eadd.tar.gz perlweeklychallenge-club-25b7cd78a7df9fff61c3975713fae77b3ca8eadd.tar.bz2 perlweeklychallenge-club-25b7cd78a7df9fff61c3975713fae77b3ca8eadd.zip | |
Challenge 241 README Blog
Diffstat (limited to 'challenge-241')
| -rw-r--r-- | challenge-241/ianrifkin/README.md | 157 | ||||
| -rw-r--r-- | challenge-241/ianrifkin/blog.txt | 1 |
2 files changed, 107 insertions, 51 deletions
diff --git a/challenge-241/ianrifkin/README.md b/challenge-241/ianrifkin/README.md index a3d7bf545f..3c47888b88 100644 --- a/challenge-241/ianrifkin/README.md +++ b/challenge-241/ianrifkin/README.md @@ -1,83 +1,138 @@ # A.A.B.A. (Acronym And Build Array) -Challenge 240: https://theweeklychallenge.org/blog/perl-weekly-challenge-240/ +Challenge 241: https://theweeklychallenge.org/blog/perl-weekly-challenge-241/ -## Task 1: Acronym +## Task 1: Arithmetic Triplets -> You are given an array of strings and a check string. +``` +You are given an array (3 or more members) of integers in increasing order and a positive integer. -> Write a script to find out if the check string is the acronym of the words in the given array. +Write a script to find out the number of unique Arithmetic Triplets satisfying the following rules: +a) i < j < k +b) nums[j] - nums[i] == diff +c) nums[k] - nums[j] == diff Example 1 -``` -Input: @str = ("Perl", "Python", "Pascal") - $chk = "ppp" -Output: true -``` +Input: @nums = (0, 1, 4, 6, 7, 10) + $diff = 3 +Output: 2 +Index (1, 2, 4) is an arithmetic triplet because both 7 - 4 == 3 and 4 - 1 == 3. +Index (2, 4, 5) is an arithmetic triplet because both 10 - 7 == 3 and 7 - 4 == 3. Example 2 -``` -Input: @str = ("Perl", "Raku") - $chk = "rp" -Output: false -``` +Input: @nums = (4, 5, 6, 7, 8, 9) + $diff = 2 +Output: 2 -Example 3 -``` -Input: @str = ("Oracle", "Awk", "C") - $chk = "oac" -Output: true +(0, 2, 4) is an arithmetic triplet because both 8 - 6 == 2 and 6 - 4 == 2. +(1, 3, 5) is an arithmetic triplet because both 9 - 7 == 2 and 7 - 5 == 2. ``` -I am sure there are plenty of more interesting ways to solve this but the way my mind works is to create a real acronym by looping through each word in the in the input array to get the first letter. +A quick read of this task was overwhelming to me because it sounded like it was going to be more math than I could handle, but upon closer inspection the answer is in the description. -``` -sub check_acronym { - my ($acronym, $words) = @_; - my $real_acronym; - foreach (@{$words}) { - $real_acronym .= substr($_, 0, 1); - } -``` +I kept it simple and just explicitely created the three loops with the three specified iterators. It's very helpful to match the incrementor names in my code with the task's description. -With that in place just compare the strings, forcing them both into uppercase so that it's a case insensitive comparison. You could also do this with a simple RegEx compare but this feels simpler to write/read to my brain. +I started by looping through the input array with an incrementer `$i`. We know that $i is needed for the first value so the max $i is going to be 2 less than the total array length: `for (my $i = 0; $i < $nums_length - 2; $i++)` -``` -uc($acronym) eq uc($real_acronym) ? print "true\n" : print "false\n"; -``` +Within this loop I just make the next loop with `$j` which is 1 more than `$i` to 1 less than the array length: `for (my $j = $i + 1; $j < $nums_length - 1; $j++)` -I did a similar approach with Raku and Python. With Perl the final print statement is a conditional so that it will print the words "true" or "false" instead of 0 or 1 but that's not needed with Python and Raku. +Finally within that loop I create the loop with `$k` which is going to be 1 more than `$j` to the end of the array: `for (my $k = $j + 1; $k < $nums_length; $k++)` -## Task 2: Build Array +Now that I have my loops I go back to the instructions which stated: +nums[j] - nums[i] == diff +and +nums[k] - nums[j] == diff -> You are given an array of integers. +which in my Perl code is simple: `(@{$nums}[$j] - @{$nums}[$i] eq $diff && @{$nums}[$k] - @{$nums}[$j] eq $diff)` -> Write a script to create an array such that new[i] = old[old[i]] where 0 <= i < new.length. +Anytime the above is true it increments a counter `$total_finds`. After the loops are complete it prints the `$total_finds` counter. + +The complete `sub find_triplets` is as follows: -Example 1 ``` -Input: @int = (0, 2, 1, 5, 3, 4) -Output: (0, 1, 2, 4, 5, 3) +sub find_triplets { + my ($diff, $nums) = @_; + my $nums_length = scalar @{$nums}; + my $total_finds = 0; + for (my $i = 0; $i < $nums_length - 2; $i++) { + for (my $j = $i + 1; $j < $nums_length - 1; $j++) { + for (my $k = $j + 1; $k < $nums_length; $k++) { + if (@{$nums}[$j] - @{$nums}[$i] eq $diff && @{$nums}[$k] - @{$nums}[$j] eq $diff) { + $total_finds++; + } + } + } + } + print "$total_finds\n"; +} ``` -Example 2 + +Full script with comments available at https://github.com/ianrifkin/perlweeklychallenge-club/blob/ianrifkin-challenge-241/challenge-241/ianrifkin/perl/ch-1.pl + + +## Task 2: Prime Order ``` -Input: @int = (5, 0, 1, 2, 3, 4) -Output: (4, 5, 0, 1, 2, 3) +You are given an array of unique positive integers greater than 2. + +Write a script to sort them in ascending order of the count of their prime factors, tie-breaking by ascending value. + +Example 1 +Input: @int = (11, 8, 27, 4) +Output: (11, 4, 8, 27)) + +Prime factors of 11 => 11 +Prime factors of 4 => 2, 2 +Prime factors of 8 => 2, 2, 2 +Prime factors of 27 => 3, 3, 3 ``` -Doing `new[i] = old[old[i]]` seemed simple enough but I do have trouble mentally processing `where 0 <= i < new.length`. If `i` is a postion of the input array it is always going to be equal to or greater than 0 because of how arrays are numbered. Since each new[i] is mapped to a value calculated from the old array they should naturally end up the same length, so `i` should never be longer than new.length because `i` shouldn't be less than old.length either. +This one sounded simple enough but I needed to write WAY more code to accomplish. Though to be fair, part of the length is a lot more code commends and documentation. + +I split up the work into 2 subroutines. The second one is simpler so let's talk about that first. I created a `prime_finder` to accept a number and output its prime. + +In the sub I have a for loop where the iterator goes from 2 to the square root of the number, which I calculated with the sqrt() function. I have it find the prime by taking the number and dividing by the iterator and seeing if it equals 0. -With that out of the way, I did a simple for loop using the iterator variable `$i` -- within the loop I am literally just doing the exact mapping from the question: `new[i] = old[old[i]]` +When it finds the prime instead of returning that value I'm returning the number / that prime iterator value so that I can use it later to calcuate the remaining values. + +For example, given the input 8 it will find the value 2 then return 4 (because 8/2=4). This will allow the other subroutine to calculate the complete list: 2,2,2 for input 8. + +The only other things that `prime_finder` does is if $num % $i does not equal to 0 in any of the loops then that means that the input number was actually prime so it will return the input number. ``` -for (my $i = 0; $i < @ints; $i++) { - $new_ints[$i] = $ints[$ints[$i]]; +sub prime_finder { + my ($num) = @_; + my $num_was_prime; + for (my $i = 2; $i <= sqrt($num); $i++) { + if ($num % $i == 0) { + return $num / $i; + $num_was_prime = 0; + last; + } + else { + $num_was_prime = 1; + } + + } + return $num if $num_was_prime; } ``` -That's it! After the loop I print the new array in the desired format: -``` -print "(" . join(', ', @new_ints) . ")\n"; -``` +The subroutine that calls the above and does the sorting and output printing took a notable amount of time to think through and test and troubleshoot, especially since I wanted it to work for any input (and any amount of input). + +The sub accepts the input array of numbers and loops through each one. It creates a hash `%results` to store the count of prime factors for each number. + +The loop starts by setting `$results{$num} = 1;` because every number will have at least the prime factor of itself. + +Next I use the `prime_finder()` sub on the input number to get the value. + +If the `prime_finder()` value is undefined or equal to the input number, we're done and can proceed to the next number in the loop. + +If `prime_finder()` returned a new number I increment `$results{$num}` to account for the smallest factor than loop to find the remaining factors, if applicable. + +The loop goes from the initial value returned by `prime_finder()` to the value of the input number devided by that `prime_finder()` value, which should be the smallest factor (hence why I already incremented for the smallest factor above). + +In the loop I calculate the next prime with `prime_finder()` then either increment the counter or exit the loop if no new prime is found. If a prime was found, in addition to incrementing the counter I then loop back through using the new `prime_finder()` value. + +With all the looping complete I sort the `%results` hash first by its values (the counter) then do a secondary sort on the key (the input number), which I save in an array. I am assuming that `tie-breaking by ascending value` mean the value of the input number. At the end I just print the `@sorted_output` array. -This task sounded more complicated so I will be curious to see if others took a more interesting approach.
\ No newline at end of file +The full code with comments is available at https://github.com/ianrifkin/perlweeklychallenge-club/blob/ianrifkin-challenge-241/challenge-241/ianrifkin/perl/ch-2.pl
\ No newline at end of file diff --git a/challenge-241/ianrifkin/blog.txt b/challenge-241/ianrifkin/blog.txt new file mode 100644 index 0000000000..409085ddee --- /dev/null +++ b/challenge-241/ianrifkin/blog.txt @@ -0,0 +1 @@ +https://github.com/ianrifkin/perlweeklychallenge-club/blob/ianrifkin-challenge-240/challenge-241/ianrifkin/README.md |
