Perl Weekly Challenge 207

Keyboard Words

Task

You are given an array of words.

Write a script to print all the words in the given array that can be types using alphabet on only one row of the keyboard.

Let us assume the keys are arranged as below:

  • Row 1: qwertyuiop
  • Row 2: asdfghjkl
  • Row 3: zxcvbnm

Solution

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/bin/env raku

use v6.d;

sub keyboard-word(Str $word --> Bool) {
    my $row1 = /:i <[qwertyuiop]> /;
    my $row2 = /:i <[asdfghjkl]> /;
    my $row3 = /:i <[zxcvbnm]> /;
    $word ~~ /^ [<$row1>+ | <$row2>+ | <$row3>+] $ / ?? True !! False;
}

sub keyboard-word-list(Str @words --> Array[Str]) {
    my Str @kwords = grep(&keyboard-word, @words);
    return @kwords
}

#| Run test cases
multi sub MAIN('test') {
    use Test;
    plan 2;

    is keyboard-word-list(Array[Str].new(["Hello","Alaska","Dad","Peace"])),
        ("Alaska", "Dad"),
        'works for ("Hello","Alaska","Dad","Peace")';
    is keyboard-word-list(Array[Str].new(["OMG","Bye"])),
        (),
        'works for ("OMG","Bye")';
}

#| Take user provided list like: Hello how are you asdf
multi sub MAIN(*@elements where @elements.elems  1 && all(@elements) ~~ /^<[a..zA..Z]>+$/) {
    my Str @str-elements = @elements;
    say keyboard-word-list(@str-elements);
}

Discussion

Matching strings against regular expressions is naturally a strong point in Raku. Creating a named regex for each row and comparing them using alternation is done in keyboard-word. The ternary operator then returns whether a match has been found. This function is then used to filter the word list.

H-Index

Task

You are given an array of integers containing citations a researcher has received for each paper.

Write a script to compute the researcher’s H-Index. For more information please checkout the Wikipedia page.

The H-Index is the largest number h such that h articles have at least h citations each. For example, if an author has five publications, with 9, 7, 6, 2, and 1 citations (ordered from greatest to least), then the author’s h-index is 3, because the author has three publications with 3 or more citations. However, the author does not have four publications with 4 or more citations.

Solution

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env raku

use v6.d;

sub h-index(Int @citations --> Int) {
    my Int @sorted-citations = sort(@citations);
    my Int $index = 2;
    $index++ while @sorted-citations[* - $index]  $index;
    return $index - 1;
}

#| Run test cases
multi sub MAIN('test') {
    use Test;
    plan 2;

    is h-index(Array[Int].new([10, 8, 5, 4, 3])), 4, 'works for (10, 8, 5, 4, 3)';
    is h-index(Array[Int].new([25, 8, 5, 3, 3])), 3, 'works for (25, 8, 5, 3, 3)';
}

#| Take user provided list like 1 2 2 3
multi sub MAIN(*@elements where @elements.elems  1 && all(@elements) ~~ /^0?<[1..9]><[0..9]>*$/) {
    my Int @int-elements = @elements;
    say "The h-index of ({@int-elements}) is: {h-index(@int-elements)}";
}

Discussion

After sorting the list just iterate the list from the back. The first value which is smaller than it’s inverted index aborts the while loop. As we went one iteration too far, subtract one from the index and return it.

Related
Raku · Perl