PWC 258

PWC 258

Last week (#257)

I finished challenge 2 and my blog post for challenge 257 late last week, so had only submitted challenge 1. Here is my blog post for PWC 257, including the full code for my challenge 2 solution.

This week, I have done both challenges in perl 4.019 on DOSBOX. Both scripts also work fine on the latest Perl 5.38. I also did the challenges in Raku, where they are one-liners. 

Challenge 1 (Count Even Digits Number)

We are given a list of integers, and asked to count the number of elements whose base-10 representation has an even number of digits.

In Raku, this is a one-liner. Here it is:

raku -e 'say +@*ARGS.grep({$_.chars %% 2})' $@

It could be a one-liner in Perl 4 too, but since I run it on DOSBOX, my script would not be a bash shell script. Here is the short subroutine that does the job. 

sub count_even_digits {
 scalar( grep( ((length($_) % 2) == 0), @_) );
}

The full code is here.

Challenge 2 (Sum of values)

We are given an integer k and a list ints of integers. We are asked to first find the indices of ints whose base-2 representation contains exactly k instances of the digit 1. We then return the sum of the elements of ints at those indices.

In Raku, this is a one-liner. Here it is:

raku -e 'my ($k, @ints)=@*ARGS; say sum @ints[ (0 .. @ints.elems-1).grep({$_.base(2).comb.sum == $k}) ];' $@

We find the base-2 representation of each index, split it, and then sum the elements, which gives the number of 1's. 

In perl 4, I have a limited solution, which only works for lists of 10 or less elements. For the numbers 0 to 9, we can use the vec(.) function to get a length-4 vector of the digits in its binary representation (backwards, but that doesn't matter for our purpose). 

Here is a helper subroutine to calculate the sum of binary digits of a given string (should be a number from 0 to 9 to work correctly, but I don't bother with input validation)

sub binsum {
 #sum of digits of binary form of a number
 local($num)=$_[0];
 local($binsum)=0;
 foreach (0 .. 3) {
  $binsum += vec($num,$_,1);
 }
 $binsum;
}

Here is the primary subroutine. It calls &binsum within a loop, which my "Programming perl 1e" warns against, but the inefficiency shouldn't matter here.

sub sum_of_values {
 local($k,@ints)=@_;
 ($#ints > 9) && (return "Error. Max 10 elements allowed.");
 grep($_ =~ /[^0-9]/, ($k,@ints)) && (return "Error. Only integers allowed.");
 local($sum_of_values)=0;
 foreach (0 .. $#ints) {
  (&binsum($_)==$k) && ($sum_of_values += $ints[$_]);
 }
 $sum_of_values;
}

The full code is here.

Comments

Popular posts from this blog

PWC 215

PWC 227

PWC 234