Posts

Showing posts from 2022

PWC 197

PWC 197 I did not attempt the challenges in Julia this time. I have solutions in Perl 5 and Raku. Challenge 1 (Move Zero) We are given a list of integers, say (3,0,1,0,5). We are asked to sort the list so that all zeros move to the end, and the remaining items are in their original relative order. In my example, the sorted list would be (3,1,5,0,0). This is a one-liner in Perl 5 and Raku. Perl 5: perl -wl -e ' my @o = sort { ($a == 0) ? 1 : ( ($b == 0) ? -1 : 0 ) } @ARGV; print "@o" ' $@ Raku: raku -e ' say @*ARGS.sort( { ($^a == 0) ?? 1 !! ( ($^b == 0) ?? -1 !! 0 ) } ) ' $@ The logic is via the block argument to sort. This takes two parameters $a and $b representing two elements in the list being compared. If the comparison returns -1, then $a precedes $b in the sorted list. If the comparison returns 1, then $b precedes $a in the sorted list. If the comparison returns 0, then the order doesn't matter. The sort pattern here follows this logic: If both

PWC 196

PWC 196 Aside on Advent of Code I have done the Advent of Code challenges in Perl 5 up to #14 so far. Here are my solutions. I probably should stop there at least for now, since I have a lot of work despite the holidays. But let's see, #15 looks intriguing, and I'm sure the later ones are too. Back to discussing our Weekly Challenges for this week. This week, I submitted only Perl 5 and Raku solutions, not Julia. Challenge 1 (Pattern 132) We are given a list of at least three integers. We are required to extract one sub-list of three integers that satisfies the following restrictions: If i,j,k respectively are the indices in the original list of the extracted items, then i < j < k. If a[i], a[j], a[k] respectively are the items in the sub-list in order, then we have: a[k] > a[i], and a[j] > a[k] (similar to the ordering in the list 1,3,2 whence the name). This is a one-liner in Raku, using the combinations operator. I did not directly implement restriction 1 above

PWC 195

PWC 195 Challenge 1 (Special integer) We are given a positive integer n. We are asked to find the number of positive integers between 1 to n inclusive of both ends, i.e., 1 .. $n in Perl- or Raku-speak, such that no digit is repeated in the integer. For example, 11 or 1313 are not okay, but 12 or 1302 are. After my over-engineered challenge 2 solution last week, brute force seems very appealing, and that is how I go with both challenges this week. I should point out though that in this case, brute force is strictly dominated by a standard analytical formula. We can calculate the number of permutations of the digits 0 .. 9 taken 1 at a time, 2 at a time, 3 at a time, etc. with adjustments to handle the upper bound n. Fellow-contributor Luis Mochan has spelled out the formula in his blog . In Raku, the brute force solution is a short and sweet one-liner: raku -e ' (1 .. @*ARGS[0]).grep({$_ == $_.comb.unique.join}).elems.say ' $@ I tried to translate this to an equivalent Perl 5

PWC 194

PWC 194 Aside on Advent of Code I also discovered Advent of Code and got started on it. Not sure if I will continue, because the daily cycle may be too much for me. I thought initially of doing it using Raku, but looking at the challenges, immediately decided to go with Perl 5. The tasks so far all involve reading an input file with some data in an arbitrary text-based format, then doing some computations with that data, and finally spitting out some output which one submits to Advent of Code for validation. This is exactly what Perl was designed to do. Raku of course is a development from the same source, but it's a bit less focused on the "practical extraction and reporting" stuff. Here is the repo with my solutions. And now, back to our regular scheduled weekly challenge. Challenge 1 (Digital Clock) We are given an input string which is a 24-hour clock time, in the format 'hh:mm'. For example, 23:59. From the examples, 24:00 is not allowed. One number is missi

PWC 193

PWC 193 Caveat that my scripts are all first pass solutions (I think it shows :-). Not optimized.  Challenge 1 (Binary string) We are given an integer n say, and asked to print out all the binary numbers of length n or less. This is a one-liner in all three languages. In my scripts, n is read from the command line. Here it is for n=3. In Perl 5: perl -e 'for (eval ("0b".(0 x $ARGV[0]). ".." . "0b". (1 x $ARGV[0]))){printf("%b\n",$_)}' 3 In Raku: raku -e 'use MONKEY-SEE-NO-EVAL; for (EVAL("0b" ~ (0 x @*ARGS[0]) ~ ".." ~ "0b" ~ (1 x @*ARGS[0]))) {printf("%b\n",Int($_))}' 3 In Julia: julia -e 'for i in (parse( Int64, "0b" * repeat( "0", parse( Int64,ARGS[1] ))) : parse( Int64, "0b" * repeat( "1", parse(Int64, ARGS[1] )))); println( SubString( bitstring(i), 65-parse(Int64, ARGS[1]))); end;' 3 In all three languages, I iterate through the range 0b0

PWC 192

PWC 192 Challenge 1 (Binary flip) We are given an integer. We are asked to convert it to its binary representation, and then flip the bits, that is, 1 becomes 0, and 0 becomes 1. From the examples, it is clear that we do not flip leading zeros in the binary representation: i.e., 010 flips to 001, not 101. It is easier to do this in Perl (5 or 6) with string-handling operators rather than bit operators. One first uses sprintf("%b",...) to represent the integer as a string version of its binary form. Then one applies the tr (transliterate) operator on this string to replace [01] with [10]. Then stick a '0b' in front of the resulting string, and call eval on the result to magically make it an integer. Here is my Perl 5 subroutine: sub binary_flip  {     my $b=sprintf("%b",shift);     $b =~ tr/[10]/[01]/;     eval('0b' . $b); } Here is the direct port to Raku: sub binary-flip (Int $n) {     my $b=sprintf("%b",$n);     $b ~~ tr/<[1 0]>/&l

PWC 191

PWC 191 This was a busy week at work again. I managed to do both challenges in Perl 5 and Raku (I skipped Julia this time). But like last week, these are minimal contributions that just satisfy the test examples. Particularly in Challenge 2, my solution is not efficient with a bigger input. I discuss briefly here how my solutions could be improved, but haven't had time to actually attempt the better solutions. Challenge 1 (Twice largest) We are given a list of integers, and asked to find if the biggest integer in the list is weakly more than twice the second-biggest integer.  This is easily done. Sort the list using a numeric sort, and then, if sorted in descending order as I did it, compare the first element in the sorted list with the second. Here is my Perl 5 subroutine to do this: sub twice_largest { my (@list)=@_; my @sorted_list = sort {$b <=> $a} @list; (($sorted_list[0]) >= (2*$sorted_list[1])) ? 1 : (-1); } And here is the Raku version: sub twice-larg

PWC 190

PWC 190 This week was busy at work. I thought I would only be able to do Challenge 1, but I managed to eke out a minimal solution in Perl 5 and Raku to Challenge 2 too (I passed on Julia for Challenge 2 this time). Challenge 1 (Capital Detection) We are given a string consisting of alphabets only (/^[A-Za-Z]+$/), and asked to test if one of the following conditions is met: The initial letter is uppercase, and all the rest are lowercase (as in "Perl"). All the letters are uppercase (as in "COBOL"). All the letters are lowercase (as in "bash"). This is one of those Perl programming exercises where the python philosophy almost applies: there's one very good way to do it, and that's the way to go. That is via a regex. This would be an easy one-liner, but I have used a subroutine instead. Here is the key snippet in Perl 5. ($s =~ /^[A-Z]?[a-z]+$|^[A-Z]+$|^[a-z]+$/) ? 1 : 0; Here is the same thing in Raku (a direct translatio

PWC 189

PWC 189 Challenge 1 (Greater Character) "You are given an array of characters (a..z) and a target character. Write a script to find out the smallest character in the given array lexicographically greater than the target character." I sort the list. Then, in Perl 5 and Julia, I loop through the sorted elements until I hit one just bigger than the target. In Raku, I just use grep. Here is the key snippet from my Raku script: @arry . sort ({$ ^ a cmp $ ^ b}) . grep ({ $_ gt $target}) . min ; Here is my Perl 5 script Here is my Raku script Here is my Julia script Challenge 2 (Array Degree) "You are given an array of 2 or more non-negative integers. Write a script to find out the smallest slice, i.e. contiguous subarray of the original array, having the degree of the given array." The degree of the array is the maximum frequency with which any element occurs. Thus for the example given (1,3,3,2), the degree is 2 (the frequency of the most common or modal element 3).

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 my Raku script. Here is m