Peter’s blog ✴ Week 307 ✴ 3 February 2025

THE WEEKLY CHALLENGE
Orders and anagrams

The Perl Camel

Task 1

Check order

You are given an array of integers, @ints. Write a script to re-arrange the given array in an increasing order and return the indices where it differs from the original array.

Examples


Example 1
Input: @ints = (5, 2, 4, 3, 1)
Output: (0, 2, 3, 4)
Before: (5, 2, 4, 3, 1)
After : (1, 2, 3, 4, 5)
Difference at indices: (0, 2, 3, 4)

Example 2
Input: @ints = (1, 2, 1, 1, 3)
Output: (1, 3)
Before: (1, 2, 1, 1, 3)
After : (1, 1, 1, 2, 3)
Difference at indices: (1, 3)

Example 3
Input: @ints = (3, 1, 3, 2, 3)
Output: (0, 1, 3)
Before: (3, 1, 3, 2, 3)
After : (1, 2, 3, 3, 3)
Difference at indices: (0, 1, 3)

Analysis

I tried doing this using grep or map and while I'm sure it's possible, I find code hard to maintain when $_ and $_[0] are mixed in a single expression - and especially when $_[$_] makes an appearance.

So I've gone for a slightly more wordy approach, which still works in negligible time for an @ints with thousands of elements.

Perl Weekly’s review

Working through to get the efficient solution can be fun. You would definitely love the journey behind it. Thanks for sharing.

Try it 

Try running the script with any input:



example: 3, 1, 4, 1, 5, 9

Script


#!/usr/bin/perl

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

use v5.26;    # The Weekly Challenge - 2025-02-03
use utf8;     # Week 307 - task 1 - Check order
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';

check_order(5, 2, 4, 3, 1);
check_order(1, 2, 1, 1, 3);

my @ints;
push @ints, int(rand(10)) for 0 .. 49;
check_order(@ints);

sub check_order {
    
    my (@ints, @sorted, @different, $j);
    
    # sort the list
    @ints = @_;
    @sorted = sort {$a <=> $b} @ints;
    
    # find indices where original and sorted differ
    for $j (0 .. $#ints) {
        push @different, $j if $ints[$j] != $sorted[$j];
    }       
    
    say qq[\nInput:  \@ints =      (] . join(', ', @ints) . ')';
    say qq[        \@sorted =    (] . join(', ', @sorted) . ')';
    say qq[Output: \@different = (] . join(', ', @different) . ')';
}

9 lines of code

Output from script


Input:  @ints =      (5, 2, 4, 3, 1)
        @sorted =    (1, 2, 3, 4, 5)
Output: @different = (0, 2, 3, 4)

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

Input:  @ints =      (5, 6, 8, 2, 6, 7, 6, 4, 9, 9, 1, 8,
2, 7, 8, 6, 6, 5, 9, 7, 9, 5, 3, 4, 4, 6, 0, 5, 3, 1, 8,
8, 2, 8, 1, 1, 9, 0, 9, 7, 2, 4, 1, 3, 0, 6, 1, 2, 6, 3)
        @sorted =    (0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2,
2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6,
6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8,
9, 9, 9, 9, 9, 9)
Output: @different = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49)

 

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