Peter
Peter Campbell Smith

Initialisms and contorted arrays

Weekly challenge 240 — 23 October 2023

Week 240 - 23 Oct 2023

Task 2

Task — Build array

You are given an array of integers. Write a script to create an array such that new[i] = old[old[i]] where 0 <= i < new.length.

Examples


Example 1
Input: @int = (0, 2, 1, 5, 3, 4)
Output: (0, 1, 2, 4, 5, 3)

Example 2
Input: @int = (5, 0, 1, 2, 3, 4)
Output: (4, 5, 0, 1, 2, 3)

Analysis

The essence of this task is in the task statement: it is only necessary to evaluate:

$new[$_] = $old[$old[$_]] for (0 .. @old - 1)

This task can only be done for certain arrays, that is, arrays containing all the integers from 0 to (length - 1) in any order. So I check for that by sorting @old, checking that $old[0] is zero and every other $old[$i] equals old[$i - 1] + 1.

Try it 

Try running the script with any input:



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

Script


#!/usr/bin/perl

use v5.16;    # The Weekly Challenge - 2023-10-23
use utf8;     # Week 240 task 2 - Build array
use strict;   # Peter Campbell Smith
use warnings; # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

build_array(0, 2, 1, 5, 3, 4);
build_array(5, 0, 1, 2, 3, 4);
build_array(5, 6, 1, 2, 3, 4);
build_array(10, 6, 3, 8, 5, 4, 1, 9, 2, 0, 7);

sub build_array {
    
    my (@old, @new, $last, @check, $good);
    
    # need to make sure the task is possible
    @old = @_;
    $last = @old - 1;
    @check = sort {$a <=> $b} @old;
    $good = $check[0] == 0;
    $good &= $check[$_] == $check[$_ - 1] + 1 for (1 .. $last);
    
    # show results
    say qq[\nInput:  \@old = (] . join(q[, ], @old) . q[)];
    if ($good) {
        $new[$_] = $old[$old[$_]] for (0 .. $last);
        say qq[Output: \@new = (] . join(', ', @new) . ')';

    } else {
        say qq[Output: impossible];
    }
}
    

Output



Input:  @old = (0, 2, 1, 5, 3, 4)
Output: @new = (0, 1, 2, 4, 5, 3)

Input:  @old = (5, 0, 1, 2, 3, 4)
Output: @new = (4, 5, 0, 1, 2, 3)

Input:  @old = (5, 6, 1, 2, 3, 4)
Output: impossible

Input:  @old = (10, 6, 3, 8, 5, 4, 1, 9, 2, 0, 7)
Output: @new = (7, 1, 8, 2, 4, 5, 6, 0, 3, 10, 9)