Posts

PWC 188

PWC 188 Challenge 1 (Divisible pairs) We are given a list of integers, @list say, as well as a scalar integer $k. We are asked to count the number of pairs of elements of @list whose sum is divisible by $k. Thus, if $a and $b are elements of @list, we count ($a,$b) as an eligible pair if ($a+$b) is divisible by $k. This is a potential one-liner in Raku. But I settled for a one-line subroutine. Here is the key snippet: ( 0 .. @test-1) . combinations( 2 ) . grep ({@test[ $_ ] . sum %% $k}) . elems The task specification asks us to find pairs of indices of @list rather than pairs of elements of @list directly. I have followed this specification literally with Raku.  Of course it makes no difference if we get the pairs from the list directly. I did this with my Perl 5 and Julia versions, both of which are derived from the Raku one. Julia key snippet:   for i in collect ( combinations (list, 2 ))        if ( sum (i) % k == 0 ) ...

PWC 187

PWC 187 Challenge 1 (Days Together) Two friends Foo and Bar vacation in the same city, with the start-dates and end-dates for each one's vacation given in the form 'dd-mm'. The year is assumed to be the same non-leap year for all dates. The task is to work out the number of days when Foo and Bar are both in the city at the same time.  This resolves to finding the number of days between the later start-date and the earlier end-date, including both days in the count (e.g., if they are both the same day, then the count is 1, not zero). This is easy to do with the numerous Date modules in Perl 5, or the built-in Date support in Raku and Julia.  In Perl 5, I used the lightweight fast Date::Calc module exporting the Delta_Days subroutine. Delta_Days counts days between two (year, month, day) triplets, input as a flat list. Since it excludes the second (ending) date from the count, I add 1 to include it for the present task. My Perl 5 script uses simple helper subroutines to parse...

PWC 186

PWC 186 Challenge 1 (Zip List) Challenge 1 requires "zipping" two lists  a and b say, by creating a combined list in which the elements are: (a[0] b[0] a[1] b[1] a[2] b[2] ...). The lists are of equal length. There are ready-made functions to do this in all three languages I submit. In Perl 5, List::MoreUtils has a zip function that does exactly this. Raku has the Z operator, so it is as simple as @a Z @b . Julia has a zip function named zip, though the output is not quite what is requested. It returns an array of tuples: [(a[0] b[0]), (a[1] b[1]), ...].  I wrote my own function for the task, using straightforward logic. I just push the elements of the two arrays into a new array in the prescribed order. The key snippet: Perl 5: push @c , ( $$ra_a [ $_ ], $$ra_b [ $_ ]) for (0 .. @$ra_a -1);   Raku: @c . append (@a[ $_ ], @b[ $_ ]) for ( 0 .. @a-1); Julia: for i in 1:length(b)     append!(c, a[i], b[i]) end   Here is my Perl 5 script. Here is m...

PWC 185

PWC 185 Challenge 2 (Mask Code) Given a list of arbitrary strings consisting of alphanumeric and other characters, we are asked to run a script that replaces the first four alphanumeric characters in each string with x. Thus (from the test example), 'ab-cde-123' gets converted to 'xx-xxe-123'. This is a one-liner in Perl 5 and Raku. In Perl 5 : perl -E ' for my $test (@ARGV) {$test =~ s/[a-wyz0-9]/x/ for (1 .. 4); say $test} ' ' ab-cde-123 ' ' 123.abc.420 ' ' 3abc-0010.xy ' I loop through the strings in ARGV and for each string loop four times through a substitution regex that finds the next alphanumeric that is not x and replaces it with x.  The same logic in Raku : raku -e ' @*ARGS.map({my $temp=$_; ($temp ~~ s/<[a .. w y z 0 .. 9]>/x/) for (0 .. 3); say $temp;}) ' ' ab-cde-123 ' ' 123.abc.420 ' ' 3abc-0010.xy ' In Julia I do not use a ...

PWC 184

PWC 184 Both the tasks for this week have narrowly defined input requirements. I don't write a function to handle them. I want to avoid input validation and error handling chores, and any self-respecting function needs both. I present throwaway scripts or one-liners with the inputs explicitly written into the script or ARGV.  Challenge 1 (Sequence number) We are given a list of strings, each one formatted as two lower-case alphabets (/[a-z]/) followed by 4  numeric characters (/[0-9/), e.g.,  ('ab1234', 'cd5678', 'ef1342'). We are asked to replace the starting alphabets with a two-digit string of numbers indicating their position in the list starting with zero, e.g., ('001234', '015678', '021342'). I do this with one-liners in Perl 5, Raku and Julia. Perl 5: perl -e ' my $ctr=0; for my $x ("00" .. "99") {print $x . substr($ARGV[$ctr++],2,4) . " "; last if $ctr >= @ARGV;} print "\n"; '...

PWC 183

PWC 183 Challenge 1 (Unique array) Given an array of arrays, we are asked to remove any duplicate elements (arrays) and return the sub-array with only unique elements. Thus, given ([1,2],[3,4],[5,6],[1,2]), the script should return ([1,2],[3,4],[5,6]). Perl 5 In Perl 5, PDL offers an immediate solution via the uniqvec method. One just reads the list into a piddle: $list = pdl ([1,2],[3,4],[5,6],[1,2]); and then calls uniqvec on it: $list->uniqvec  The uniqvec method still works if the piddle has rows of unequal lengths, as in ([1,2],[3,4],[5,6,7],[1,2]). In this case, it pads the shorter rows with zeroes in the output: [     [1,2,0]     [3,4,0]     [5,6,7] ] I have presented my Perl 5 solution as a perldl executable command history. Here is my perldl script. Julia Julia has something similar to uniqvec in the unique function. println(unique(arry)) Just like PDL, it handles rows of unequal lengths. It does not pad the shorter row...

PWC 182

PWC 182 Challenge 1 (max index) Given a list of numbers, we are asked to give the index of the first occurrence of the biggest number in the list. This is easy to do via one-liners in all three languages. Here is my Raku one-liner raku -e ' say (0 .. @*ARGS.elems-1).grep({@*ARGS[$_] == @*ARGS.max}) ' 5 2 9 1 7 6 Here is my Perl 5 one-liner perl -MList::Util= ' max ' -E ' for (0 .. $#ARGV) {if ($ARGV[$_]==max(@ARGV)) {say;}} ' 5 2 9 1 7 6         It would be more compact with a trailing if as in say if (.. . ) , but I think that's just a cosmetic improvement.  I'll let the uglier syntax above stand. Julia has the convenient argmax function which returns the index of the maximum item. Here is my Julia one-liner julia -e 'println(argmax(ARGS)-1)' 5 2 9 1 7 6 My solutions differ slightly from the specification in that they return the indices of every occurrence of the biggest item, not just the first...

PWC 181

PWC 181 Challenge 1 (Sentence Order) This challenge asks us to take a given paragraph, and then: first, break it into sentences, and then sort the words and punctuation marks in each sentence into alphanumeric order print the sentences with the sorted word order Since this task does not need anything from CPAN, I did it using only Perl 4 syntax. I've done this in some earlier challenges. To add a bit of further challenge, I stuck a  use strict on top. Also, I used one single hydra-headed variable to do everything. To be precise, I used just one symbol-table entry,  main::teststring , or in Perl 4 syntax, main'teststring . Dynamic scope allows some strange things. For example, I locally redefine my &main'teststring subroutine inside the subroutine and then call the redefined subroutine from inside the original (a non-recursive call). A nested subroutine is not really needed here, but hey why not? I can't be sure that my script would actually work on a Perl 4 inter...

PWC 180

PWC 180 This week saw two light challenges, which I was able to do in both Perl 5 and Raku despite being busy at work. I also did Challenge 2 in Julia, but not Challenge 1. Challenge 1 is a string-handling task for which Julia is not a typical choice. Challenge 1 (First unique character) The challenge here is to find the first unique character in a given string.  The string is likely to be short (a long string would be unlikely to have unique characters, if naturally generated from a much smaller number of characters). So a two-loop solution should be efficient enough:  one loop to count the occurrences of each character using a hash, and  the second to loop through the characters again, checking the number of occurrences from the hash, and stopping at the first character for which the number of occurrences equals 1.  A twist is that we are asked to return the index position of the character, not the character itself.  I give my Perl 5 subroutine a somewhat retr...

PWC 179

PWC 179 These are somewhat quick and dirty attempts as I have less spare time this week. Challenge 1 (ordinal numbers) Challenge 1 asks for a numeric input to be represented in words (in English) as an ordinal number, e.g., 62 -> sixty-second. The easiest way to do this in Perl 5 is via the Lingua::EN::Numbers package or one of its relatives. The ready-made num2en_ordinal subroutine does what we need. In Raku, it is easiest to use Lingua::EN::Numbers again via Inline::Perl 5. In Julia too, I just run Perl 5 one-liners using Julia's backtick notation ( documented here ). So effectively I have three Perl 5 scripts wrapped slightly differently. Here is my Perl 5 script. Here is my Raku script. Here is my Julia script.   I found out later that Raku has its own Lingua::EN::Numbers , so one doesn't have to call the Perl 5 module. Challenge 2 (Unicode sparkline) Sparklines are inline graphics. We are asked to represent an array of numbers as a sparkline using unicode characters....

PWC 178

PWC 178 I didn't have time to do the full challenge in both Perls + Julia this week, so I have just submitted Challenge 1 in Raku, and Challenge 2 in Perl 5. The choice of language for each challenge is because of the availability of modules that make the respective task easy. I also did a partial solution to Challenge 1 in Julia. Challenge 1 (Quater-imaginary base) This is an offbeat number base proposed by Donald Knuth: base 2i. Read all about it in Wkipedia. We are asked to convert a given base-10 number to base-2i. It is trivial to do this in Raku because of the Base::Any module which converts a number from (almost) any number base to (almost) any number base. (The almost is because it does not handle complex bases with both a real and imaginary part. The wholly imaginary 2i is no problem). This allows easy conversion of any real or complex base-10 number, as I illustrate with a couple of examples from the wikipedia page (accessed 2022-8-17). Here is my Raku solution. Julia h...

PWC 177

PWC 177 Challenge 1 (Damm Algorithm) This challenge requires implementing the Damm algorithm which uses an extra check digit to catch errors in entering digits in a numeric code, especially the common transposition errors. In terms of programming, this is a simple matter of setting up a lookup table and then looking it up. I implement two subroutines, closely following the howto in the wikipedia page. "get_check_digit" calculates a check digit for a given number, and "validate" checks if a number is correct based on the extended number including a check digit. In Perl 5 and Raku, I give in to dark primitivist urges and set up the lookup table as a flat list of strings. In Julia, it is easy to implement it as a Matlab-like matrix. This algorithm is useful enough to have its own CPAN module: Algorithm::Damm Here is my Perl 5 script. Here is my Raku script. Here is my Julia script. Challenge 2 (Palindromic Prime Cyclops) This challenge requires looking for the first 2...