Robbie Hatley's Perl Solutions To The Weekly Challenge #207

For those not familiar with "The Weekly Challenge", it is a weekly programming puzzle, usually with two parts, cycling every Sunday. You can find it here:

The Weekly Challenge

This week (2023-03-05 through 2023-03-11) is weekly challenge #207.

Task 1 is to write a script which prints all of the words in a given array that can be typed using only letters on one row of a standard QWERTY keyboard. My solution was to create two simple subroutines, one to give the keyboard row number (1, 2, or 3) of any letter, and one to determine if all the letters of a word on on the same row:

use List::AllUtils 'all';

sub row($letter){
      if ($letter =~ m/[qwertyuiop]/i ) {return 1}
   elsif ($letter =~ m/[asdfghjkl]/i  ) {return 2}
   elsif ($letter =~ m/[zxcvbnm]/i    ) {return 3}
   else                                 {return 0}}

sub one_row($word){
   my @letters = split //,$word;
   my $rofl = row($letters[0]);
   if (all {row($_) eq $rofl} @letters) {return 1}
   else                                 {return 0}}

Task 2 is to write a script to compute the "H-Index" of an array of integers enumerating the citations which a researcher has received for each of his/her papers, where the "H-Index" is the largest number h such that h articles have at least h citations each. Now this I found rather tricky.

And though I'm pretty sure there are simpler ways, the way I came up with that works is a bit complicated. I make a "citations" array filled with zeros, with indices from 0 through the maximum number of citations which any of the author's papers have received. Then for each of the papers I increment each of the elements with indices from 0 through the number of citations which that paper received. Then I iterate through the citations array in-reverse, until I find the first element for which value >= index and return that index:

use List::AllUtils 'max';

sub max0 (@array){
   my $max = max(@array);
   return defined($max) ? $max : 0;}

sub h (@array){
   my @pap_w_n_citations = (0)x(max0(@array)+1);
   for (@array){for (0..$_) {++$pap_w_n_citations[$_]}}
   for (reverse(0..$#pap_w_n_citations)){
      if ($pap_w_n_citations[$_]>=$_){return $_}}}

That's it for 207; see you on 208!

Comments

Popular posts from this blog

Robbie Hatley's Solutions To The Weekly Challenge #262

Robbie Hatley's Solutions To The Weekly Challenge #266

Robbie Hatley's Solutions To The Weekly Challenge #273