The Weekly Challenge - 265


TASK #1: 33% Appearance
You are given an array of integers, @ints.

Write a script to find an integer in the given array that appeared 33% or more. If more than one found, return the smallest. If none found then return undef.


Here my solution with CPAN module Statistics::Frequency:

#!/usr/bin/perl
use strict;
use warnings;
use Statistics::Frequency;

sub gt33 {

  my @result; 	

  # create a new Statistics::Frequency object.
  my $f = Statistics::Frequency->new(@_);
  # return the frequencies as a hash, the elements as the keys and the frequencies as the values.
  my %freq_int = $f->frequencies;  

  foreach my $k (sort(keys(%freq_int))) {

    if(($freq_int{$k}/scalar(@_)) > 0.33) {
      push(@result, $k);
    }

  }	
  # print smallest, i.e. the first array item
  print("Result: $result[0]\n");
}

# TESTS

# Example 1
my @ints_1 = (1, 2, 3, 3, 3, 3, 4, 2);
gt33(@ints_1); # 3

# Example 2
my @ints_2 = (1, 2, 3);
gt33(@ints_2); # 1

# Example 3
my @ints_3 = (1, 1);
gt33(@ints_3); # 1

TASK #2: Completing Word
You are given a string, $str containing alphnumeric characters and array of strings (alphabetic characters only), @str.

Write a script to find the shortest completing word. If none found return empty string.

A completing word is a word that contains all the letters in the given string, ignoring space and number. If a letter appeared more than once in the given string then it must appear the same number or more in the word.


Here my solution again with CPAN module Statistics::Frequency:
#!/usr/bin/perl
use strict;
use warnings;
use Statistics::Frequency;

=begin
In this task, you need to answer two questions:
1. Does each letter of the given string ($given_str) occur in an element ($element) of the word array (@str)?
2. Is the frequency of a letter in the given string ($given_str) Less Than or Equal To the frequency in an element ($element) of the word array (@str)?

To put it another way:

if( (index($element, $char_given_str) == -1) || $f1->frequency($char_given_str) > $f2->frequency($char_given_str)) -> no success

where $f1 refers to $given_str and $f2 to an element of @str
=cut

sub completing_word {

  my($given_str, @str) = @_;

  my @result = ();
  
  # get characters [a-z] from the given string
  my @given_str_chars = grep( /[a-z]/, (split //, lc($given_str)) );
  # create a new Statistics::Frequency object to invoke later the 'frequency' method
  my $f1 = Statistics::Frequency->new(@given_str_chars);

  # extract all unique characters from $given_str to avoid duplicate results
  my $unique_chars_given_str = join ("", @given_str_chars);
  $unique_chars_given_str =~ tr/a-z//s;

  # evaluate each element in word array @str by an INNER loop
  OUTER: foreach my $element (@str) {  
	
       # create a new Statistics::Frequency object to invoke later the 'frequency' method
       my $f2 = Statistics::Frequency->new( (split //, $element) );

       my $success = 0;
       INNER: foreach my $char ((split //, $unique_chars_given_str)) {

           if( (index($element, $char) == -1) || $f1->frequency($char) > $f2->frequency($char)) {
             $success = 0;
             # terminate loop INNER and investigate next element (if exists)                        
             last INNER;  		 
           }	 
           $success++;
       }
       push(@result, $element) if($success);   
  }

  # if there is more than one string that satisfies the condition
  if(scalar @result > 1) {
      my @result_sorted = sort( { length($a) <=> length($b) } @result );
      # print the smallest array element	 
      print("Result: $result_sorted[0]\n");
  }
  else {
      print("Result: @result\n");	
  }

}

# TESTS

my($given_str, @str);

# Example 1
$given_str = 'aBc 11c';
@str = ('accbbb', 'abc', 'abbc');
completing_word($given_str, @str); # accbbb

# Example 2
$given_str = 'Da2 abc';
@str = ('abcm', 'baacd', 'abaadc');
completing_word($given_str, @str); # baacd

# Example 3
$given_str = 'JB 007';
@str = ('jj', 'bb', 'bjb');
completing_word($given_str, @str); # bjb 

# Example 4
$given_str = 'JB 007';
@str = ('jz', 'bb', 'bjb');
completing_word($given_str, @str); # bjb