Peter’s blog ✴ Week 265 ✴ 15 April 2024

THE WEEKLY CHALLENGE
Frequent number and shortest word

The Perl Camel

Task 1

33% appearance

You are given an array of integers, @ints. Write a script to find an integer in the given array that appears 33% or more. If more than one is found, return the smallest. If none is found then return undef.

Examples


Example 1
Input: @ints = (1,2,3,3,3,3,4,2)
Output: 3

1 appeared 1 times.
2 appeared 2 times.
3 appeared 4 times.

3 appeared 50% (>33%) in the given array.

Example 2
Input: @ints = (1,1)
Output: 1

1 appeared 2 times.

1 appeared 100% (>33%) in the given array.

Example 3
Input: @ints = (1,2,3)
Output: 1

1 appeared 1 times.
2 appeared 1 times.
3 appeared 1 times.

Since all three appeared 33.3% (>33%) in the given array.
We pick the smallest of all.

Analysis

This is a task where I think the obvious method is the best.

First we count the frequencies of all the numbers in @times.

Then we look for the first $times[$i] which is greater than 33% of the size of @ints.

If none meets that criterion we return undef.

I am sorry that the 'Try it' feature is currently working very slowly or not at all owing to some issue with my web hosting provider.

Try it 

Try running the script with any input:



example: 1, 2, 3, 4, 5, 5, 5

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.26;    # The Weekly Challenge - 2024-04-15
use utf8;     # Week 265 - task 1 - 33% appearance
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';

my ($j, @ints);

over_33perct_appearance(1, 2, 3, 3, 3, 3, 4, 2);
over_33perct_appearance(1, 1);
over_33perct_appearance(1, 2, 3);
over_33perct_appearance(1, 2, 3, 4);
over_33perct_appearance(8, 8, 8, 9, 9, 9, 7, 7, 7);

for $j (1 .. 100) {
    push @ints, int(rand(3)) + 1;
}
over_33perct_appearance(@ints);

sub over_33perct_appearance {
    
    my (@ints, @times, $one_third, $i);
    
    # intialise
    @ints = @_;
    say qq[\nInput:  \@ints = (] . join(', ', @ints) . ')';
    $one_third = (scalar @ints) * 0.33;
    
    # count frequenceies
    $times[$_] ++ for @ints;
    
    # find smallest with >33%
    for ($i = 0; $i < @times; $i ++) {
        next unless defined $times[$i];
        if ($times[$i] > $one_third) {
            say qq[Output: $i (] . int($times[$i] / @ints * 100) . '%)';
            return;
        }
    }
    
    # none found
    say qq[Output: undef];
}

12 lines of code

Output from script


Input:  @ints = (1, 2, 3, 3, 3, 3, 4, 2)
Output: 3 (50%)

Input:  @ints = (1, 1)
Output: 1 (100%)

Input:  @ints = (1, 2, 3)
Output: 1 (33%)

Input:  @ints = (1, 2, 3, 4)
Output: undef

Input:  @ints = (8, 8, 8, 9, 9, 9, 7, 7, 7)
Output: 7 (33%)

Input:  @ints = (3, 3, 2, 2, 3, 3, 3, 1, 3, 3, 2, 1, 3, 3,
1, 3, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, 3, 1,
3, 2, 2, 3, 3, 2, 3, 2, 3, 1, 1, 3, 3, 3, 3, 3, 1, 3, 3,
2, 1, 1, 1, 2, 3, 2, 3, 1, 3, 2, 1, 2, 3, 1, 1, 1, 2, 3,
2, 2, 1, 2, 3, 1, 2, 3, 3, 2, 3, 3, 2, 1, 3, 3, 1, 1, 2,
3, 2, 1, 2, 3, 1, 1, 2, 2, 3)
Output: 2 (34%)
	

 

Any content of this website which has been created by Peter Campbell Smith is in the public domain