Peter’s blog ✴ Week 306 ✴ 27 January 2025

THE WEEKLY CHALLENGE
Odd game

The Perl Camel

Task 2

Last element

You are given a array of integers, @ints. Write a script to play a game where you pick two biggest integers in the given array, say x and y. Then do the following:
a) if x == y then remove both from the given array
b) if x != y then remove x and replace y with (y - x)

At the end of the game, there is at most one element left. Return the last element if found otherwise return 0.

Examples


Example 1
Input: @ints = (3, 8, 5, 2, 9, 2)
Output: 1
Step 1: pick 8 and 9 => (3, 5, 2, 1, 2)
Step 2: pick 3 and 5 => (2, 2, 1, 2)
Step 3: pick 2 and 1 => (1, 2, 2)
Step 4: pick 2 and 1 => (1, 2)
Step 5: pick 1 and 2 => (1)

Example 2
Input: @ints = (3, 2, 5)
Output: 0
Step 1: pick 3 and 5 => (2, 2)
Step 2: pick 2 and 2 => ()

Analysis

In order to get the results in the examples it is necessary to require that x > y, which is not quite clear from the task description.

The order of @ints is not significant, so my solution starts by reverse-sorting it, so that x is $ints[0] and y is $ints[1]. I then apply the rules repetitively, using shift to pull x and y off @ints.

It is interesting to note that if @ints is populated with more than around 100 random positive integers, even with numbers up to a million or more, it almost always converges to 1 or to 0 (ie 1, 1).

Perl Weekly’s review

from PW issue 706

Don't you love when you are presented with multiple solutions to the same problem. Plent to learn each week. Keep it up great work.

Try it 

Try running the script with any input:



example: 12, 23, 34, 45, 56

Script


#!/usr/bin/perl

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

use v5.26;    # The Weekly Challenge - 2025-01-27
use utf8;     # Week 306 - task 2 - Last element
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';

last_element(3, 8, 5, 2, 9, 2);
last_element(3, 2, 5);
last_element(43, 21, 56, 86, 2, 69, 10, 43, 77, 30);

sub last_element {
    
    my (@ints, $x);
    
    # initialise
    @ints = @_;
    say qq[\nInput:  \@ints = (] . join(', ', @_) . ')';
    
    # loop until 0 or 1 element left
    while ($#ints > 0) {
        @ints = sort {$b <=> $a} @ints;
        
        # if x == y
        if ($ints[0] == $ints[1]) {
            shift @ints; 
            shift @ints;
        
        # if x != y
        } else {
            $x = shift @ints;
            $ints[0] = $x - $ints[0];
        }
    }
    say qq[Output: ] . ($ints[0] or 0);
}
 

13 lines of code

Output from script


Input:  @ints = (3, 8, 5, 2, 9, 2)
Output: 1

Input:  @ints = (3, 2, 5)
Output: 0

Input:  @ints = (43, 21, 56, 86, 2, 69, 10, 43, 77, 30)
Output: 1

 

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