in reply to Fisher-Yates shuffle?

While im not sure why you want this to be a one liner
($a=rand $_-1),@values[$_,$a] = @values[$a,$_] for (reverse 1..$#value +s);
I believe that this resolves Abigail-IIs concern.

Yves / DeMerphq
---
Software Engineering is Programming when you can't. -- E. W. Dijkstra (RIP)

Replies are listed 'Best First'.
Re: Re: Fisher-Yates shuffle?
by BrowserUk (Patriarch) on Aug 09, 2002 at 17:13 UTC

    I didn't set out to create a one-liner. I set out to shuffle some test data. I found the Fisher-Yates thing and set about working out how the Perl implementation using slices worked (I haven't done much with slices before now), and came up with the one-liner which on casual inspection appeared to work.

    Given Abigail's fix for it's failings, I'm happy to use it, with it's dependancy on subscript evaluation order on the basis that if this ever changes, it will break a lot of other code too, so the change should be well announced.

    As for "why ... a one-liner", I will turn that around and ask--Why not?--provided it works.

    Isn't it the Perlish way?

      will turn that around and ask--Why not?--provided it works

      Well, i suppose there are different answers. One could be speed. A "normal" swap of two variables (using a temp var and three assignments) is faster than list assignment. Another but better argument is maintainability. Consider that the cause of abigail-IIs concern about the LHS/RHS is that of trying to get the code to work without imposing a scoping block of some sort. Also, another effect of trying to get this to work on one line is that you used $a. Now most would tell you to avoid that and $b for various reasons. In your code it doesnt look like it would be a problem, but as the code morphs in the future, perhaps back to a multiline solution maybe that $a will not go away, and then maybe the code will morph so much that the trap im thinking off catches you (or your successor)

      But one liners are fun I agree. :-)

      Given Abigail's fix for it's failings, I'm happy to use it, with it's dependancy on subscript evaluation order on the basis that if this ever changes, it will break a lot of other code too, so the change should be well announced.

      Actually I doubt it would be. Im pretty sure the assumption would be that no one in their right mind would depend on such an undocumented feature. (er, sorry :-)

      Anyway, seya,

      Yves / DeMerphq
      ---
      Software Engineering is Programming when you can't. -- E. W. Dijkstra (RIP)

        Just to show I do listen:).

        As you don't object to $a and do object to slices and the reliance on subscript evaluation order, I offer this: (it passes Abigail-II's test!!)

        $_ ne ($a=int( rand( $#values-$_+1))+$_) and $values[$_] ^= $values[$a] ^= $values[$_] ^= $values[$a] for (0..$#values); # Fisher-Yates one-liner

        Its a shame you can't use an named iterator with the for (list) statement modifier otherwise I would have this as:

        $b ne ($a=int(rand($#values-$b+1))+$b) and $values[$b] ^= $values[$a] ^= $values[$b] ^= $values[$b] for $b (0..$#values);

        Then noone could complain about the use of $a and $b...they are used for swapping aren't they?

        UpdateI forgot to mention...I had to re-institute the don't swap if same test for this to work, but given some C-compilers used the 3-Xor's trick to optomise register swaps in register constrained situations, I wonder if this was the real reason for that test in the oeriginal Fisher-Yates C code?