Perl Weekly Challenge 226: Shuffle String

These are some answers to the Week 226, Task 1, of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Spoiler Alert: This weekly challenge deadline is due in a few days from now (on July 23, 2023 at 23:59). This blog post offers some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.

Task 1: Shuffle String

You are given a string and an array of indices of same length as string.

Write a script to return the string after re-arranging the indices in the correct order.

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'

I first thought that the indice represented the order in which to pick the letters from the string, and quickly came up with the following simple Raku subroutine:

sub shuffle-string ($string, @indices) {
    # Caution: wrong solution
    return ($string.comb)[@indices].join("");

and ran it with the first example provided with task:

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

But that doesn't work, as, instead of "challenge", it returns the following string:


What the heck is this? After some checks, I quickly came to the conclusion that my program did not appear to be buggy, but that I had misunderstood the task. How the hell can we obtain the string "challenge" from the given input data? It took me a few minutes to understand. Looking at the letters of the input string and the input indice:

[l a c e l e n g h]
(3 2 0 5 4 8 6 7 1)

we can see that it works differently: we need to pick the letter whose position is that of 0 in the indice (i.e. 'c'), then the letter whose position is that of 1 in the indice, and so on:

0   c
1   h
2   a
3   l
4   l
5   e
6   n
7   g
8   e

So we need to transform the input @indice array, or reverse it if you prefer, if we want to use it as a "slice" on the array containing the letters of the input string. The idea is to construct a new array where the first integer will be the position corresponding to 0 in the original @indice array (i.e. letter 'c'), the second item will be the position corresponding to 1 in the original @indice array (letter 'h'), and so on so that we will end up with the following new array:

[2 8 1 0 4 3 6 7 5]

which can readily used as a slice over the arrays of letters of the original string.

Shuffle String in Raku

Please refer to the above explanations to understand the array transformation (@indices -> @index) performed by the program.

sub shuffle-string ($string, @indice) {
    my @index;
    @index[@indice[$_]]= $_ for 0..@indice.end;
    # say @index;
    return ($string.comb)[@index].join("");

for ('lacelengh', (3,2,0,5,4,8,6,7,1)),
    ('rulepark', (4,7,3,1,0,5,2,6)) -> @test {
    printf "%-10s - %-20s => ", @test[0], "@test[1]";
    say shuffle-string @test[0], @test[1];

This program displays the following output:

$ raku ./shuffle-string.raku
lacelengh  - 3 2 0 5 4 8 6 7 1    => challenge
rulepark   - 4 7 3 1 0 5 2 6      => perlraku

Shuffle String in Perl

This a port to Perl of the above Raku program. Please refer to the explanations after the task description if you need any further explanation.

use strict;
use warnings;
use feature 'say';

sub shuffle_string {
    my ($string, $idx_ref) = @_;
    my @indices = @$idx_ref;
    my @index;
    @index[$indices[$_]]= $_ for 0..$#indices;
    return join "", (split //, $string)[@index];

for my $test (['lacelengh', [3,2,0,5,4,8,6,7,1]],
    ['rulepark', [4,7,3,1,0,5,2,6]]) {
    printf "%-10s - %-18s => ", 
        $test->[0], "@{$test->[1]}";
    say shuffle_string $test->[0], $test->[1];


This program displays the following output:

$ perl ./
lacelengh  - 3 2 0 5 4 8 6 7 1  => challenge
rulepark   - 4 7 3 1 0 5 2 6    => perlraku

Wrapping up

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check and make sure you answer the challenge before 23:59 BST (British summer time) on July 30 , 2023. And, please, also spread the word about the Perl Weekly Challenge if you can.

Leave a comment

About laurent_r

user-pic I am the author of the "Think Perl 6" book (O'Reilly, 2017) and I blog about the Perl 5 and Raku programming languages.