Peter
Peter Campbell Smith

Climbing or falling
and reshaping the matrix

Weekly challenge 204 — 13 February 2023

Week 204 - 13 Feb 2023

Task 1

Task — Uphill or downhill?

We are given an array of integers and tasked to write a script to find out if it is monotonic (1) or not (0). Monotonic means that successive pairs are either all not increasing (eg 2, 1, 1) or all not decreasing (eg 3, 3, 4).

Analysis

It seems inevitable that we have to examine each pair of consecutive array members. Let's start by assuming that the array is monotonic ($result = 1), but we don't know whether it's increasing or decreasing ($direction = 0).

As we look at each pair, $i and $j:

  • if $direction == 0 we can set $direction to +1 or -1 if $array[$i] != $array[$j]
  • if $direction != 0 then we can set $result to 0 and stop looking if the direction of $array[$j] from $array[$i] is not in line with $direction

... and if we get to the end of the loop with $result == 1 then the array is monotonic.

And that's just how my solution does it.

Note that if all the elements of @array are identical, then it is, by the task's definition, both increasing and decreasing. The loop will end with $direction still zero and $result equal to 1. I have reported such an array as monotonic with direction 'level'.

Also, I've used the $a <=> $b operator which conveniently returns -1, 0 or +1 according to whether $a is less than, equal to or more than $b. I can't remember when I last used that (apart from in a call to sort).

Try it 

Example: 1, 2, 2, 3

Script


#!/usr/bin/perl

# Peter Campbell Smith - 2023-02-14

use v5.28;
use utf8;
use warnings;
use Time::HiRes qw(time);

# Task: You are given an array of integers. Write a script to find out if the given array is Monotonic. 
# Print 1 if it is otherwise 0. An array is Monotonic if it is either monotonically increasing or decreasing:
# Monotonically increasing if for i <= j , nums[i] <= nums[j]
# Monotonically decreasing if for i <= j , nums[i] >= nums[j]

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

my (@tests, $test, @array, $direction, $next, $result, $j);

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

for $test (@tests) {
    
    @array = @$test;
    
    $result = 1;
    $direction = 0;
    for $j (0 .. scalar(@array) - 2) {
        $next = $array[$j + 1] <=> $array[$j];
        unless ($direction) {
            $direction = $next;
        } else {
            unless ($next == $direction or $next == 0) {
                $result = 0;
                last;
            }
        }
    }
    say qq[\nInput:  (] . join (', ', @array) . qq[)];
    
    say qq[Output: $result] . ($result == 0 ? '' :
        ($direction > 0 ? ' increasing' : ($direction < 0 ? ' decreasing' : ' level')));
}   


Output


Input:  (1, 2, 2, 3)
Output: 1 increasing

Input:  (1, 3, 2)
Output: 0

Input:  (6, 5, 5, 4)
Output: 1 decreasing

Input:  (7, 7, 7, 6, 8)
Output: 0

Input:  (5, 5, 5, 5, 5)
Output: 1 level