Peter’s blog ✴ Week 195 ✴ 12 December 2022

THE WEEKLY CHALLENGE
Special and frequent numbers

The Perl Camel

Task 2

Most frequent even

You are given a list of numbers, @list. Write a script to find most frequent even number in the list. In case you get more than one, then return the smallest. For all other cases, return -1.

Examples


Input: @list = (1,1,2,6,2)
Output: 2 as there are only 2 even numbers 2 and 6 and 
  of those 2 appears the most.

Example 2
Input: @list = (1,3,5,7)
Output: -1 since no even numbers found in the list

Example 3
Input: @list = (6,4,4,6,1)
Output: 4 since there are only two even numbers 4 and 6. 
  They both appears the equal number of times, so pick 
  the smallest.

Analysis

Let's sort the list and then pass down it, ignoring odd numbers and incrementing $freq[$j] when we see an even $j.

As we do that, we keep a $max_freq to keep track of the maximum frequency seen, and $max_freq_no being the first (ie least) number that occurs with that frequency.

Perl Weekly’s review

from PW issue 595

Plenty to learn how to speed up your solutions. Thanks for sharing the knowledge.

Try it 

Try running the script with any input:



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

Script


#!/usr/bin/perl

# Peter Campbell Smith - 2022-12-12
# PWC 195 task 2

use v5.28;
use utf8;
use warnings;

my (@tests, $test, @freq, $max_freq, $max_freq_no, $j, @list);

@tests = ([1,1,2,6,2], [1,3,5,7], [6,4,4,6,1], 
    [8, 8, 6, 6, 4, 4, 2, 2], [1, 2, 2, 4, 4, 4], [8, 6, 8, 6, 8, 6, 8]);

# loop over tests
for $test (@tests) {
    
    # initialise
    $max_freq = 0;
    $max_freq_no = -1;
    @freq = ();
    
    # look at each member of input list, sorted numerically so that we see the smallest first
    for $j (sort {$a <=> $b} @$test) {
        
        # ignore it if it is odd
        next if $j & 1;
        
        # increment its frequency
        $freq[$j] ++;
        
        # if more that the highest seen so far, remember it
        if ($freq[$j] > $max_freq) {
            $max_freq = $freq[$j];
            $max_freq_no = $j;
        }
    }
    
    # and show the result
    say qq[\nInput:  \@list = (] . join(', ', @$test) . qq[)];
    say qq[Output: $max_freq_no ] . ($max_freq > 0 ? qq[($max_freq times)] : '');

}

18 lines of code

Output from script


Input:  @list = (1, 1, 2, 6, 2)
Output: 2 (2 times)

Input:  @list = (1, 3, 5, 7)
Output: -1

Input:  @list = (6, 4, 4, 6, 1)
Output: 4 (2 times)

Input:  @list = (8, 8, 6, 6, 4, 4, 2, 2)
Output: 2 (2 times)

Input:  @list = (1, 2, 2, 4, 4, 4)
Output: 4 (3 times)

Input:  @list = (8, 6, 8, 6, 8, 6, 8)
Output: 8 (4 times)

 

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