The Bear's Den

Enter at your own risk

Reverse Frequencies

Task 1: Sum of Frequencies

Submitted by: Mohammad Sajid Anwar


You are given a string consisting of English letters.

Write a script to find the vowel and consonant with maximum frequency. Return the sum of two frequencies.

Example 1

Input: $str = "banana"
Output: 5

Vowel: "a" appears 3 times.
Consonant: "n" appears 2 times, "b" appears 1 time.

Max frequency of vowel: 3
Max frequency of consonant: 2

Example 2

Input: $str = "teestett"
Output: 7

Vowel: "e" appears 3 times.
Consonant: "t" appears 4 times, "s" appears 1 time.

Max frequency of vowel: 3
Max frequency of consonant: 4

Example 3

Input: $str = "aeiouuaa"
Output: 3

Vowel: "a" appears 3 times, "u" 2 times, "e", "i", "o" 1 time each.
Consonant: None.

Max frequency of vowel: 3
Max frequency of consonant: 0

Example 4

Input: $str = "rhythm"
Output: 2

Vowel: None
Consonant: "h" appears 2 times, "r", "y", "t", "m" 1 time each.

Max frequency of vowel: 0
Max frequency of consonant: 2

Example 5

Input: $str = "x"
Output: 1

Vowel: None
Consonant: "x" appears 1 time.

Max frequency of vowel: 0
Max frequency of consonant: 1

Solution

There is a small problem distinguishing between vowels and consonants: I dislike the approach of regarding a consonant as a character that is not a vowel (or vice versa). Therefore the given string is reduced to lower case letters only. After such preparation, the complement of lower case vowels are lower case consonants.

J

Implemented the J solution first and presenting it first.

freq_sum =: _(adverb define)
   NB. lower case letters as a character array
   ll =. a. {~ 97 + i.26

   NB. select the lower case letters from a character array
   sel_ll =. #~ e.&ll

   NB. vowels as a character array
   vowels =. 'aeiou'

   NB. apply the left operand to the group of vowels
   NB. and the group of other characters
   by_vo =. (/.~)`(e.&vowels)`:6

   NB. find the frequency of unique items
   freq =. #/.~

   NB. maximum over items
   max =. >./

   NB. sum over items
   sum =. +/

   NB. select lower case letters, find the maximum frequency
   NB. of unique characters over vowels / others
   NB. and take the sum over these
   (sum @: (max @: freq by_vo) @ sel_ll) f. : [:
)

The final verb and example 2:

   freq_sum
+/@:(>./@:(#/.~)/.~ e.&'aeiou')@(#~ e.&'abcdefghijklmnopqrstuvwxyz') :[:
   freq_sum 'teestett'
7

See the full solution.

Perl

An implementation that is a little less functional: restrict to lower case letters, count unique characters by vowel / other and add these.

use strict;
use warnings;
use List::Util qw(max sum);

sub freq_sum {
    my %cnt;
    $cnt{/[aeiou]/}{$_}++ for shift =~ /[a-z]/g;
    sum map {
        max values %$_
    } values %cnt;
}

See the full solution to task 1.

Task 2: Reverse Degree

Submitted by: Mohammad Sajid Anwar


You are given a string.

Write a script to find the reverse degree of the given string.

For each character, multiply its position in the reversed alphabet (‘a’ = 26, ‘b’ = 25, …, ‘z’ = 1) with its position in the string. Sum these products for all characters in the string to get the reverse degree.

Example 1

Input: $str = "z"
Output: 1

Reverse alphabet value of "z" is 1.
Position 1: 1 x 1
Sum of product: 1

Example 2

Input: $str = "a"
Output: 26

Reverse alphabet value of "a" is 26.
Position 1: 1 x 26
Sum of product: 26

Example 3

Input: $str = "bbc"
Output: 147

Reverse alphabet value of "b" is 25 and "c" is 24.
Position 1: 1 x 25
Position 2: 2 x 25
Position 3: 3 x 24
Sum of product: 25 + 50 + 72 => 147

Example 4

Input: $str = "racecar"
Output: 560

Reverse alphabet value of "r" is 9, "a" is 26, "c" is 24 and "e" is 24.
Position 1: 1 x 9
Position 2: 2 x 26
Position 3: 3 x 24
Position 4: 4 x 22
Position 5: 5 x 24
Position 6: 6 x 26
Position 7: 7 x 9
Sum of product: 9 + 52 + 72 + 88 + 120 + 156 + 63

Example 5

Input: $str = "zyx"
Output: 14

Reverse alphabet value of "z" is 1, "y" is 2 and "x" is 3.
Position 1: 1 x 1
Position 2: 2 x 2
Position 3: 3 x 3
Sum of product: 1 + 4 + 9

Solution

The input is a string without further restrictions, but the degree is defined for lower case letters only. I’ll assume any other character does not contribute to the degree itself, but it occupies a position.

J

Again, the J implementation came first.

For items in y that are not contained in x, the index dyad x i. y returns the number of items in x. That means: 26 - i will be zero for any character that is not a lower case letter.

reverse_degree =: _(adverb define)
   NB. lower case letters as a character array
   ll =: a. {~ 97 + i.26

   NB. the reverse index or zero
   ridx =. 26 - ll&i.

   NB. counting from one upwards
   pos =. >: @ i. @ #

   NB. sum over items
   sum =. +/

   NB. sum over position times reverse index
   ([: sum pos * ridx) f.  : [:
)

The final verb and example 3:

   reverse_degree
([: +/ >:@i.@# * 26 - 'abcdefghijklmnopqrstuvwxyz'&i.) :[:
   reverse_degree 'bbc'
147

See the full solution.

Perl

Perl’s index function takes the opposite approach: A substring that is not found produces -1. Therefore operating on the reversed list of lower case letters and adding one to the index.

use strict;
use warnings;
use List::Util 'sum';

sub reverse_degree {
    state $rev = join '', reverse 'a' .. 'z';
    my $pos;

    sum map {++$pos * (1 + index $rev, $_)} split //, shift;
}

See the full solution to task 2.