Peter
Peter Campbell Smith

Counting words and
subtracting numbers

Weekly challenge 225 — 10 July 2023

Week 225 - 10 Jul 2023

Task 2

Task — Left right sum diff

You are given an array of integers, @ints. Write a script to return left right sum diff array as shown below:


@ints = (a, b, c, d)

@left  = (0, a, (a+b), (a+b+c))
@right = ((b+c+d), (c+d), d, 0)
@left_right_sum_diff = ( | 0 - (b+c+d) |,
                         | a - (c+d)   |,
                         | (a+b) - d   |,
                         | (a+b+c) - 0 | )

Note: I have altered the above to match the examples. The original has 5 elements in @ints and only 4 in @left_right_sum_diff.

Examples


Example 1:
Input: @ints = (10, 4, 8, 3)
Output: (15, 1, 11, 22)

@left  = (0, 10, 14, 22)
@right = (15, 11, 3, 0)

@left_right_sum_diff = ( |0-15|, |10-11|, |14-3|, |22-0|)
                     = (15, 1, 11, 22)
Example 2:
Input: @ints = (1)
Output: (0)

@left  = (0)
@right = (0)

@left_right_sum_diff = ( |0-0| ) = (0)

Example 3:
Input: @ints = (1, 2, 3, 4, 5)
Output: (14, 11, 6, 1, 10)

@left  = (0, 1, 3, 6, 10)
@right = (14, 12, 9, 5, 0)

@left_right_sum_diff = ( |0-14|, |1-12|, |3-9|, |6-5|, |10-0|)
                     = (14, 11, 6, 1, 10)

Analysis

The task description is more-or-less a prose version of the required code:

  • Make a reversed copy of the input, @stni
  • For both @ints and @stni:
    • add (unshift) a zero at the beginning and remove (pop) the last element.
    • Add element $j to element $j + 1, from $j == 1 to the end
  • Reverse @stni again.

@ints and @stni are now respectively the @left and @right arrays, and @lrsd (as I have abbreviated it) is the element-by-element absolute difference between these.

Try it 

Example: 1, 2, 3, 4, 5

Script


#!/usr/bin/perl

use v5.16;    # The Weekly Challenge - 2023-07-10
use utf8;     # Week 225 task 2 - Left right sum diff
use strict;   # Peter Campbell Smith
use warnings; # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

left_right_sum_diff(10, 4, 8, 3);
left_right_sum_diff(1);
left_right_sum_diff(1, 2, 3, 4, 5);
left_right_sum_diff(3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5);

sub left_right_sum_diff {
    
    my (@ints, @stni, @lrsd, $count, $x);
    
    # initialise
    @ints = @_;
    $count = @ints - 1;
    
    # do the sums on @ints and the reverse of @ints
    @stni = reverse @ints;
    for $x (\@ints, \@stni) {
        unshift @$x, 0;
        pop @$x;
        $x->[$_] += $x->[$_ - 1] for 1 .. $count;
    }
    @stni = reverse @stni;
    
    # do the differences
    $lrsd[$_] = abs($ints[$_] - $stni[$_]) for 0 .. $count;
    
    # and spout
    say qq[\nInput:  \@ints  = (] . join(', ', @_) . q[)] .
        qq[\nOutput: \@left  = (] . join(', ', @ints) . q[)] .
        qq[\n        \@right = (] . join(', ', @stni) . q[)] .
        qq[\n        \@lrsd  = (] . join(', ', @lrsd) . q[)];
    
}

Output


Input:  @ints  = (10, 4, 8, 3)
Output: @left  = (0, 10, 14, 22)
        @right = (15, 11, 3, 0)
        @lrsd  = (15, 1, 11, 22)

Input:  @ints  = (1)
Output: @left  = (0)
        @right = (0)
        @lrsd  = (0)

Input:  @ints  = (1, 2, 3, 4, 5)
Output: @left  = (0, 1, 3, 6, 10)
        @right = (14, 12, 9, 5, 0)
        @lrsd  = (14, 11, 6, 1, 10)

Input:  @ints  = (3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5)
Output: @left  = (0, 3, 4, 8, 9, 14, 23, 25, 31, 36, 39)
        @right = (41, 40, 36, 35, 30, 21, 19, 13, 8, 5, 0)
        @lrsd  = (41, 37, 32, 27, 21, 7, 4, 12, 23, 31, 39)