# Re-arrange by recipe

#### Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

•  Subject
• Author
• Posted on
First arg is recipe, the rest is the list.
The goal is re-arranging the list by the recipe.
Not so efficient way is

my \$R = shift @ARGV;
my @A = @ARGV;
my @p = split//, \$R;
my @B = ();
map { \$B[\$_] = \$A[\$p[\$_]-1] } 0..\$#p;
print "@B\n";

\$ script.pl 3142 aa bb cc dd
cc aa dd bb

There must be a better way?

TIA
James

## Re: Re-arrange by recipe

On Tuesday, November 3, 2015 at 3:00:28 PM UTC-8, James wrote:

@B = map { \$ARGV[\$_] } split //,\$ARGV[0];

## Re: Re-arrange by recipe

I doubt it. Unless you have specific subject matter knowledge, e.g.
'most of the time most items will stay in their current location', you
will have to copy all items. And that requires to touch all of them.

I would probably write this as

foreach (split//, \$R){
push @B, \$a[\$_-1];
}

But that is still the same basic algorithm that you got already.

jue

## Re: Re-arrange by recipe

What's you definition of 'better'? The obvious idea would be using an
array slice,

perl -le 'print("@ARGV[split //, shift]")' 2031 aa bb cc dd

but I didn't benchmark that.

## Re: Re-arrange by recipe

I was thinking of perl golf. Less typing, the better.

James.

## Re: Re-arrange by recipe

Two suggestions for the original problem:

perl -E 'say"@ARGV[map--\$_,shift=~/./g]"' 3142 aa bb cc dd

or

perl -E '\$[=1,say"@ARGV[shift=~/./g]"' 3142 aa bb cc dd

But I'm not really good at this is that's the opposite of how my mind
usually operates.

I actually thought that -- and ++ should default to \$_ some days ago.

## Re: Re-arrange by recipe

On 4/11/2015 01:00, James wrote:

my    \$R = 3142;
my    @A = qw/aa bb cc dd/;
print @A[ map split //, \$R];

## Re: Re-arrange by recipe

[ Variation ]
input: 3142 aa bb cc dd ee ff gg hh
output: cc aa dd bb gg ee hh ff

TIA
James

## Re: Re-arrange by recipe

On 11/11/2015 01:40, James wrote:

sure bro.
p.s.  it can be written a lot shorter, but I am tired

my \$R = 3142;
my @A = qw/aa bb cc dd ee ff gg hh/;

my @r;
for my \$of (0 .. (@A/length \$R)-1) {
push @r, map {\$_+(\$of*length \$R)} split //, \$R
}

print @A[ map @r];

## Re: Re-arrange by recipe

Two more: The first is a slight variation of George's approach using an
expression to calculate the perturbed index set, the second uses a
recursive function to apply 'the perturbation' to subsequent tuples from
the input set.

-------
my \$R = 3142;
my @A = qw/aa bb cc dd ee ff gg hh xx yy zz 00/;

my @disp = \$R=~/./g;
print("@A[map { (0,\$_*@disp .. \$_*@disp+\$#disp)[@disp] } 0 .. @A/@disp - 1]", "\n");

use Scalar::Util qw(weaken);

sub make_tumbler
{
my @d = map { \$_ - 1 } \$_[0] =~ /./g;
my (\$tumbler, \$t);

\$t = \$tumbler = sub {
return unless @_;
return (@_[@d], \$tumbler->(@_[@d .. \$#_]));
};

weaken(\$tumbler);
return \$t;
};

my \$t = make_tumbler(\$R);
print(join(' ', \$t->(@A)), "\n");
-------

## Re: Re-arrange by recipe

Somewhat more interesting:

---------
my \$R = 3142;
my @A = qw/aa bb cc dd ee ff gg hh mm nn oo pp/;

use Scalar::Util qw(weaken);

sub tumbler
{
my @d = map \$_ - 1,  shift =~ /./g;
my \$n;

return map {(map \$_[\$n++], @d)[@d]} 1 .. @_/@d;
};

print(join(',', tumbler(\$R, @A)), "\n");

## Re: Re-arrange by recipe

On 11/11/2015 01:40, James wrote:

my \$R = 3142;
my @A = qw/aa bb cc dd ee ff gg hh/;
my \$o;

print @A[map {\$o=\$_, map {\$_+(\$o*length \$R)-1} split '',\$R }
(0..(@A/length \$R)-1)];

## Re: Re-arrange by recipe

That's not only a veritable tapeworm and very inefficient but
additionally, doesn't work as the \$o=\$_ injects a wrong index into the
list at every position which is evenly divisible length(\$R) + 1. This
can be fixed, but the tapeworm then swells to Shai-Hulud-like proportions:

----------
my \$R = 3142;
my @A = qw/aa bb cc dd ee ff gg hh kk ll mm nn/;

my \$o;
print "@A[map{\$o=\$_,map{\$_+(\$o*length \$R)-1}split'',\$R }(0..(@A/length\$R)-1)]", "\n";

my \$o;
print "@A[(map{\$o=\$_,map{\$_+(\$o*length \$R)-1}split'',\$R }(0..(@A/length\$R)-1))[grep0..(\$#A+@A/length\$R)]]", "\n";

my @r = split'',\$R;
my \$n;
print "@A[map1..@A/@r]", "\n";
----------

NB: I think the trick with prepending a 0 to each index tuple in order
to avoid subtracting 1 from the members of @r is a silly sleight of
hand.

## Re: Re-arrange by recipe

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

my \$R = 3142;
my @A = qw/aa bb cc dd ee ff gg hh/;

my @B=([],\$;,length \$R);
map {\$B[1]=\$_, push @ ,map split '',\$R}
(0..(@A/\$B[2])-1);
say @A[@];

# or

my @C=([],length \$R);
for my \$d (0..(@A/\$C[1])-1) {push @ ,map split
'',\$R }
say @A[@]