Posts

Showing posts from December, 2023

PWC #250

PWC 250 Disclaimer on earlier "Perl 4" attempts In my previous challenges, I often mentioned sticking to Perl 4 syntax. I did not actually have Perl 4, so could not test on that platform.  Recently, I did manage to find an old MS-DOS executable of Perl 4.019 that I can run in DOSBOX. I quickly found that my "Perl 4" answers to earlier challenges will not run in Perl 4. Particularly, my habit of using "local * xxx = sub { ...};" to create a localized sub will not work on Perl 4. Firstly, the "local" keyword must be used with a bracketed list of arguments, as local (*x, ...). The statement form "local *x," gives a syntax error. Secondly, the sub keyword cannot appear on the right-hand-side of an assignment. Syntax error again even with "local (*x)=sub {..};" . Looks like this facility to assign a sub to a local glob only became available in Perl 5. In Perl 4, looks like subroutines always had to be global or package-level in sco...

PWC 249

PWC 249 Challenge 1 (Equal pairs) We are given a list of integers with an even number of elements. We are asked to check if the list can be completely divided into sub-lists of size 2 with each sub-list containing the same integer repeated, like say (2,2). If so, we are asked to return the list of such sub-lists. This is straightforward in Perl 5. I use modern conveniences this time, though it could be done using only primitive Perl 4 syntax. Here is my subroutine. It returns a list of array references. local *equal_pairs = sub {     #-- return () if input is of odd length     ((scalar(@_) % 2) > 0) && (return ());          #-- count number of occurrences of each element using a hash     local %_ = ();     map {$_{$_}++} @_;          #-- if any element occurs an odd number of times, return ()     (grep {($_{$_} % 2) > 0} keys %_) &&...

PWC 248

PWC 248 I use PDL with Inline:Pdlpp for both challenges this week. I found these docs helpful: the perldocs on PDL::PP and PDL::API , the chapter on PP in the PDL book, and the Practical Magic guide to using PP. Challenge 2 (submatrix sum) We are given a matrix, say A, with M columns and N rows. We are asked to find a matrix, say B, with M-1 columns and N-1 rows, such that the entry for column i and row j of B, or B(i,j) using column-first notation is given by: B(i,j) = A(i,j)+A(i,j+1)+A(i+1,j+1)+A(i+1,j) With PP, we write XS code which uses a traditional pair of nested loops to create B. Here is the PP definition: pp_def('submatrix_sum',     Pars => 'a(m,n); [o]b(p,q);',     RedoDimsCode => '$SIZE(p)=$SIZE(m)-1; $SIZE(q)=$SIZE(n)-1;',     Code => q{         PDL_Indx i, j, m_size, n_size;         m_size=$SIZE(m)-1;         n_...

PWC 247

PWC 247 Two easy challenges this week. I attempt to do both using only the core Perl 5 syntax inherited from Perl 4. ( Update and disclaimer : These programs will not work on Perl 4 as I discovered later when I found and installed a Perl 4.019 executable. For one thing, the ability to assign a subroutine to a locally scoped typeglob was not available in Perl 4.) Challenge 1 (Secret Santa) We are given a list of surnames, some of them repeated (representing different members of the same family). We are asked to create a scheme indicating who in the list gives gifts to who else, avoiding family members giving gifts within the family if possible. I go through the input list using a hash to count the number of occurrences of each surname, and then append the hash count to the surname and store this in another list say @secret_santa, so that for example the second occurrence of 'Anwar' is recorded as 'Anwar_2'. I then sort the @secret_santa list twice in opposite directions ...

PWC 246

PWC 246 For both challenges, I adopt conservative syntax and a procedural programming style mostly skewing towards the Perl 4.036 specification in Programming Perl 1e (pink camel). This is not Perl 4 though, as I take advantage of the map statement and the Perl 5 enhanced grep syntax and also some useful CPAN libraries. Challenge 1 (6 out of 49) We are asked to generate 6 random integers between 1 and 49 with no repetitions. This is inspired by a German lottery. In Perl 5, this can be done by creating a 49-element array of random numbers, say @rnd, and sorting their indices (plus one) based on the order of the random number at that index. We can then just peel off the first 6 indices from the sorted list of indices. (sort {$rnd[$a-1] <=> $rnd[$b-1]} 1..49)  [0..5] Here is the full subroutine: local *six_out_of_49 = sub {     local @six_out_of_49 = map {rand} 0 .. 48;     return (sort {$six_out_of_49[$a-1] <=> $six_out_of_49[$b-1]} 1 .. 49) ...