Peter’s blog ✴ Week 226 ✴ 17 July 2023

THE WEEKLY CHALLENGE
Gnirsts and nothing left

The Perl Camel

Task 1

Shuffle strings

You are given a string and an array of indices of the same length as string. Write a script to return the string after re-arranging the characters in the correct order.

Examples


Example 1
Input: $string = 'lacelengh', @indices = (3,2,0,5,4,8,6,7,1)
Output: 'challenge'

Example 2
Input: $string = 'rulepark', @indices = (4,7,3,1,0,5,2,6)
Output: 'perlraku'

Analysis

Analysis of the examples reveals that the essence of this challenge is:

jumbled_text[j] == plain_text[indices[j]]

... which pretty well reduces to a one-liner. The only quirk is that the plain_text string needs to be initialised to a string of '_' characters the same length as the jumbled text, because it will not be populated left to right.

Note also the use of substr() as an lvalue, allowing a single character in the middle of the string to be substituted.

Perl Weekly’s review

from Perl Weekly issue 626

Nicely laid out solutions in Perl with detailed analysis. Thanks for your contributions.

Try it 

String - eg: rulepark

Indices - eg: 4, 7, 3, 1, 0, 5, 2, 6

Script


#!/usr/bin/perl

use v5.16;    # The Weekly Challenge - 2023-07-17
use utf8;     # Week 226 task 1 - Shuffle string
use strict;   # Peter Campbell Smith
use warnings; # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

shuffle_string('lacelengh', [3, 2, 0, 5, 4, 8, 6, 7, 1]);
shuffle_string('rulepark', [4, 7, 3, 1, 0, 5, 2, 6]);
shuffle_string('aaacccdeefgiiiiiiillloopprrssstuux',
    [6, 11, 24, 5, 19, 29, 27, 3, 20, 9, 12, 8, 13, 15, 18, 23, 26, 30, 
    7, 14, 25, 28, 31, 2, 22, 4, 10, 0, 16, 33, 17, 1, 32, 21]);
    
sub shuffle_string {
    
    my ($string, @indices, $result);
    
    # initialise
    $string = $_[0];
    @indices = @{$_[1]};
    
    # prepopulate $result with '_'
    $result = '_' x length($string);
    
    # copy chars: string[j] -> result[indices[j]]
    substr($result, $indices[$_], 1) = substr($string, $_, 1) for 0 .. @indices - 1;

    say qq[\nInput:  \$string = '$string',\n        \@indices = (] . join(qq[, ], @indices) . qq[)];
    say qq[Output: '$result'];
}

8 lines of code

Output from script


Input:  $string = 'lacelengh',
        @indices = (3, 2, 0, 5, 4, 8, 6, 7, 1)
Output: 'challenge'

Input:  $string = 'rulepark',
        @indices = (4, 7, 3, 1, 0, 5, 2, 6)
Output: 'perlraku'

Input:  $string = 'aaacccdeefgiiiiiiillloopprrssstuux',
        @indices = (6, 11, 24, 5, 19, 29, 27, 3, 20, 9, 12, 8, 13, 15, 18, 23, 26, 30, 7, 14, 25, 28, 31, 2, 22, 4, 10, 0, 16, 33, 17, 1, 32, 21)
Output: 'supercalifragilisticexpialidocious'

 

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