Golf aléatoire du jour n ° 1: Mélangez un tableau


35

A propos de la série

Je vais lancer une petite série de défis de code-golf autour du thème du hasard. Ce sera essentiellement un parcours de golf de 9 trous , mais divisé en plusieurs questions. Vous pouvez participer à n'importe quel défi individuellement, comme s'il s'agissait d'une question normale.

Cependant, je maintiendrai un classement dans tous les défis. La série se déroulera sur 9 défis (pour le moment), un posté tous les deux ou trois jours. Chaque utilisateur qui participe aux 9 défis est éligible pour gagner la série complète. Leur score global est la somme des soumissions les plus courtes sur chaque défi (donc si vous répondez deux fois à un défi, seule la meilleure réponse compte pour le score). Si quelqu'un occupe la première place de ce classement général pendant 28 jours, je lui attribuerai une prime de 500 reps .

Bien que de nombreuses idées soient en préparation pour la série, les défis à venir ne sont pas encore figés. Si vous avez des suggestions, veuillez me le faire savoir sur le message du bac à sable correspondant .

Trou 1: Mélangez un tableau

La première tâche est assez simple: mélangez-le aléatoirement avec un tableau d'entiers non vide. Il y a quelques règles cependant:

  • Toutes les permutations possibles doivent être retournées avec la même probabilité (le brassage devrait donc avoir une distribution uniforme). Vous pouvez vérifier si votre algorithme est uniforme / non biaisé en l'implémentant en JavaScript dans Will it Shuffle , ce qui produira une matrice des biais - le résultat devrait être aussi uniforme que celui intégré dans Fisher-Yates ou être trié (ordre aléatoire) .
  • Vous ne devez utiliser aucune méthode intégrée ou tierce partie pour mélanger le tableau ou générer une permutation aléatoire (ou énumérer toutes les permutations). En particulier, la seule fonction aléatoire intégrée que vous pouvez utiliser consiste à obtenir un seul nombre aléatoire à la fois . Vous pouvez supposer que toute méthode de nombre aléatoire intégrée s'exécute en O (1) et est parfaitement uniforme sur l'intervalle demandé (au sens mathématique - vous pouvez ignorer les détails de la représentation en virgule flottante ici). Si votre langue vous permet d’obtenir simultanément une liste de m nombres aléatoires, vous pouvez utiliser cette fonction, à condition que les m nombres soient indépendants les uns des autres et que vous les comptiez comme O (m).
  • Votre implémentation ne doit pas dépasser une complexité temporelle de O (N) , où N est la taille de la matrice à mélanger. Par exemple, vous ne pouvez pas "trier par nombres aléatoires".
  • Vous pouvez soit mélanger le tableau à la place, soit créer un nouveau tableau (auquel cas l'ancien tableau peut être modifié à votre guise).

Vous pouvez écrire un programme complet ou une fonction et effectuer une entrée via STDIN, un argument de ligne de commande, un argument de fonction ou une invite et produire une sortie via une valeur de retour ou en imprimant sur STDOUT (ou son alternative la plus proche). Si vous écrivez une fonction qui mélange le tableau en place, vous n'avez évidemment pas besoin de la renvoyer (à condition que votre langue vous permette d'accéder au tableau modifié après le retour de la fonction).

Les entrées et les sorties peuvent se présenter sous n'importe quelle liste ou format de chaîne, mais doivent prendre en charge des entiers quelconques compris dans la plage -2 31 ≤ x <2 31 . En principe, votre code devrait fonctionner pour les tableaux d'une longueur maximale de 2 à 31 , bien que cela ne doive pas nécessairement être enregistré dans votre mémoire ou terminé dans un délai raisonnable. (Je ne veux tout simplement pas voir des limites de taille arbitraires pour les boucles en code fixe ou quelque chose du genre.)

C'est le code de golf, donc la soumission la plus courte (en octets) gagne.

Classement

L'extrait suivant générera un classement pour tous les défis de la série.

Pour vous assurer que vos réponses apparaissent, commencez chaque réponse par un titre, en utilisant le modèle Markdown suivant:

# Language Name, N bytes

Nest la taille de votre soumission. Si vous améliorez votre score, vous pouvez conserver les anciens scores en les effaçant. Par exemple:

# Ruby, <s>104</s> <s>101</s> 96 bytes

(La langue n'est pas affichée pour le moment, mais l'extrait de code nécessite une analyse syntaxique. Il se peut que j'ajoute un classement par langue ultérieurement.)


7
Je suis déçu que nous ne soyons pas autorisés à être "intelligents" et à utiliser des fonctions de bibliothèque autres que "obtenir un nombre aléatoire" . Voulons-nous nous pencher sur 69 autres mises en œuvre du shuffling Fisher-Yates? Veuillez envisager de supprimer cette règle dans les tâches futures. Aussi, pourquoi une limite de temps complexe? S'il vous plaît, envisagez de le relâcher à au moins O (n ^ 2); Je pense aussi que quelqu'un pourrait trouver une implémentation spécialement jouée au golf si vous autorisez O (n!).
Anatolyg

7
@anatolyg Supprimer les restrictions revient à dire que chaque réponse est soit sortby(random)(la raison de la restriction temporelle), soit simplement .shuffle()(la raison de la restriction intégrée), ce qui est beaucoup moins intelligent, à mon avis, que de devoir mettre en œuvre Fisher-Yates ou un autre. approche.
Martin Ender

1
Si le brassage est en place, une fonction doit-elle renvoyer le tableau ou suffit-il qu'il soit modifié? Puis-je écrire une fonction pour shuffle(array)au lieu de newArray=shuffle(array)?
Geobits

1
@Bakuriu Affirmer que vous pouvez trier en temps linéaire si les nombres sont fixes, c'est un peu comme prétendre que vous pouvez faire n'importe quoi dans O (1) si les tailles d'entrée sont fixes. La restriction pertinente concerne également les tableaux de taille fixe, et non les entiers de taille fixe, car la taille du tableau détermine la taille de vos nombres aléatoires. Quoi qu'il en soit, la limite de complexité temporelle concerne bien sûr l'algorithme général que vous implémentez, tandis que les limites de taille des entrées sont en place, vous évitant ainsi d'utiliser des entiers à précision arbitraire si votre langue ne les utilise pas immédiatement. .
Martin Ender

2
Pourquoi la solution d'Adám arrive-t-elle à 43319 octets alors qu'elle est en réalité de 14?
Boboquack

Réponses:


20

Dyalog APL, 25 24 bytes

First for the 25-character solution: i{⊃a[⍺⍵]←a[⍵⍺]}¨?i←⌽⍳⍴a←⎕

                      a←⎕ ⍝ evaluated input, assign to "a"
                     ⍴a   ⍝ length
                    ⍳⍴a   ⍝ 1 2 .. length
                   ⌽⍳⍴a   ⍝ length .. 2 1
                 i←       ⍝ assign to "i"
                ?i        ⍝ random choices: (1..length)(1..length-1)..(1 2)(1)
i{            }¨?i        ⍝ for each index ⍺ and corresponding random choice ⍵
   a[⍺⍵]←a[⍵⍺]            ⍝ swap a[⍺] and a[⍵]
        ←                 ⍝ in Dyalog, assignment returns its right-hand side
  ⊃                       ⍝ first element, i.e. a[⍵]
                          ⍝ the result from {} is an array of all those a[⍵]

After some equivalence transformations on the above:

i {}¨ ?i  ←→  i {}¨∘? i   ⍝ because A f∘g B ←→ A f g B
          ←→  {}¨∘?⍨ i    ⍝ because f⍨ B ←→ B f B

we can get rid of the assignment i← and save a character:

{⊃a[⍺⍵]←a[⍵⍺]}¨∘?⍨⌽⍳⍴a←⎕


3
... mind. blown.
danwyand

1
a language I have to read right to left?? wow!
Luminous

5
@Luminous as is often the case with mathematical notation: sin cos ln sqrt x
ngn

4
@ngn when you put it that way that makes my previous comment look laughable. ha.
Luminous

5
@ronalchn There are 8-bit encodings for APL, like this one or this other one; I heard Dyalog uses one of these, as an alternative to Unicode.
anatolyg

12

80386 machine code, 44 24 bytes

Hexdump of the code:

60 8b fa 0f c7 f0 33 d2 f7 f1 49 8b 04 8f 87 04
97 89 04 8f 75 ed 61 c3

Thanks to FUZxxl, who suggested using the rdrand instruction.

Here is the source code (can be compiled by Visual Studio):

__declspec(naked) void __fastcall shuffle(unsigned size, int array[])
{
    // fastcall convention:
    // ecx = size
    // edx = array
    _asm
    {
        pushad;             // save registers
        mov edi, edx;       // edi now points to the array

    myloop:
        rdrand eax;         // get a random number
        xor edx, edx;
        div ecx;            // edx = random index in the array

        dec ecx;            // count down
        mov eax, [edi + 4 * ecx];   // swap elements
        xchg eax, [edi + 4 * edx];  // swap elements
        mov [edi + 4 * ecx], eax;   // swap elements
        jnz myloop;

        popad;              // restore registers
        ret;
    }
}

Yet another Fisher-Yates implementation. Most of the golfing was achieved by passing parameters in registers.


1
You could have also used rdrand for shits and giggles.
FUZxxl

@FUZxxl I totally forgot about it! Too bad it removes the most interesting part about my answer...
anatolyg

9

Java, 88 101

A basic Fisher-Yates shuffle does the trick. I get the feeling it'll be used pretty commonly here, since it's quick and easy to implement. There's some loop/assignment cramming here, but there's honestly not too much to golf; it's just short by nature.

void t(int[]s){for(int i=s.length,t,x;i>0;t=s[x*=Math.random()],s[x]=s[i],s[i]=t)x=i--;}

With some line breaks:

void t(int[]s){
    for(int i=s.length,t,x;
        i>0;
        t=s[x*=Math.random()],
        s[x]=s[i],
        s[i]=t
    )
        x=i--;
}

This shuffles in place, modifying the original array s[]. Test program:

public class Shuffle {
    public static void main(String[] args) {
        int[] a = {1,2,3,4,5,6,7,8,9};
        new Shuffle().t(a);
        for(int b:a)
            System.out.print(b+" ");
    }
    void t(int[]s){for(int i=s.length,t,x;i>0;t=s[x*=Math.random()],s[x]=s[i],s[i]=t)x=i--;}
}

1
No, the challenge states that you can assume that it "is perfectly uniform over the requested range". The requested range of Math.random() has a size which is a power of two, so this doesn't meet spec.
Peter Taylor

1
@PeterTaylor Jan's and Geobits' interpretations are indeed how I intended the rule - that you don't have to worry about the actual cycle-length of your PRNG.
Martin Ender

1
@MartinBüttner the cycle length is not the issue here - that is covered by your rule. The coarseness of floats is.
John Dvorak

3
@TheBestOne It's one byte shorter than the only currently-posted python solution ;)
Geobits

1
Not any more! :D
Sp3000

8

Python 2, 86 bytes

from random import*
def S(L):i=len(L);exec"i-=1;j=randint(0,i);L[i],L[j]=L[j],L[i];"*i

This is a function which shuffles the array in place without returning it, using a straightforward implementation of the Fisher-Yates shuffle. Getting random numbers from Python is expensive...

Thanks to @xnor and @colevk for tips.


That range expression looks pretty cumbersome. Surely it's shorter to count down manually as while i:i-=1;...?
xnor

@xnor Yeah it is - thanks for that. I keep forgetting that while tends to be shorter than for for this sort of thing...
Sp3000

1
Awww... now my Java answer isn't beating this. I was quite happy for a very short while :(
Geobits

You can save another 2 bytes by making i=len(L) and putting the decrement at the beginning of the while loop.
colevk

8

J, 45 44 characters

This was a tricky one.

<@({.,?@#@}.({,<^:3@[{])}.)&>/@(<"0@i.@#,<)

Here is an explanation:

  1. # y: The tally of y, that is, the number of elements in y.
  2. ?@# y: A random number uniformly distributed over the range from 1 to (#y)-1.
  3. x { y: The item from y at index x.
  4. (<<<x) { y: All items except the item at index x in y.
  5. x , y: y appended to x.
  6. x ({ , <^:3@[ { ]) y: The item at index x in y, then all the other items.
  7. (?@# ({ , <^:3@[ { ]) ]) y A random it from y, then all the other items.
  8. x {. y: The first x items taken from y.
  9. x }. y: The first x items dropped from y.
  10. x ({. , }.) y: The first x items taken from y, then the first x items dropped from y
  11. x ({. , (?@# ({ , <^:3@[ { ]) ])@}.) y: The first x items taken from y, then the first x items from y processed as in number 7.
  12. x ({. , ?@#@}. ({ , <^:3@[ { ]) }.) y: The same thing with the drop pulled in to save one character.
  13. u/ y: u inserted between the items of y.
  14. < y: y boxed.
  15. <"0 y: Each item of y boxed.
  16. i. y: integers from 0 to y - 1.
  17. i.@# y: integers from 0 to (#y) - 1.
  18. (<"0@i.@# , <) y: Integers from 0 to (#y) - 1 each boxed and then y in a single box. This is needed because arrays in J are uniform. A box hides the shape of its content.
  19. x u&v y: like (v x) u (v y).
  20. > y: y opened, that is, without its box.
  21. x ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&> y the phrase from number 12 applied to its unboxed arguments.
  22. ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&>/ y the phrase from number 21 inserted between items of y.
  23. ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&>/@(<"0@i.@# , <) y the phrase from number 22 applied to the the result of the phrase from number 18, or, a uniform permutation of the items of y.

1
I just can't distinguish all the parentheses. And that triple boxing <@<@<@[ is also a mystery... Waiting for explanation. :)
randomra

2
Once this gets explained, I might be much more likely to upvote this answer ;-)
John Dvorak

@randomra Here you go.
FUZxxl

@JanDvorak Is the explanation satisfying?
FUZxxl

Great explanation! I didn't know about all the boxed use of from ({). And I really like the &>/ trick to manipulate a list. I'm sure I could have used it a couple times before.
randomra

5

Pyth, 25 bytes

Test it here.

Yet another Fisher-Yates implementation. Is essentially the same as @Sp3000 python solution, just in pyth.

FNrlQ1KONJ@QN XXQN@QKKJ)Q

Thanks to @Jakube for the swapping trick

<implicit>    Q=input()
FNrlQ1        For N in len(Q) to 1, only goes len Q-1 because how range implemented in pyth
 KON          K = random int 0-N
 J@QN         J=Q[N]
 <space>      Suppress print
 XXQN@QKKJ    Swap K and J
)             End for
Q             Print Q

You can save two bytes by combining those two list assignments: ` XXQN@QKKJ` instead of ` XQN@QK XQKJ`.
Jakube

@Jakube thanks for the tip. I knew there must have been a way to swap values in a list, and this is really smart. You should add it to the tips list.
Maltysen

4

Perl, 68 56 44

Like many other solutions, this uses the Fisher-Yates algorithm.

Using nutki's comment, 12 characters are saved by using $_ instead of $i and performing the operations in the array indices.

44:

sub f{@_[$_,$j]=@_[$j=rand$_,--$_]for 1..@_}

56:

sub f{$i=@_;$j=int(rand$i),@_[$i,$j]=@_[$j,$i]while$i--}

This is my first codegolf.


Not a bad start, I did not know that you can use @_[...] as rvalue like that. Can be golfed further into sub f{@_[$_,$j]=@_[$j=rand$_,--$_]for 1..@_}.
nutki

3

C, 63 61 60 bytes

i,t;s(a,m)int*a;{for(;m;a[m]=t)t=a[i=rand()%m--],a[i]=a[m];}

Just a straight implementation of Fischer-Yates that sorts the given array in place. Compiles and links perfectly fine with the visual studio compiler (vs2013, haven't tested the other versions) and the Intel Compiler. Nice looking function signature is s(int array[], int length). I'm legitimately impressed I beat Python and Ruby.

This does assume srand() is called and rand() is implemented properly, but I believe this rule allows for that:

You may assume that any built-in random number method runs in O(1) and is perfectly uniform over the requested interval

Nicely formatted version:

index, temp;
shuffle(array, length) int* array;  {
    for(;length; array[index] = temp)
        index = rand() % length--,
        temp = array[length],
        array[length] = array[index];
}

I think it suffices to make the function header s(a,m)*a{, but I'm not sure and don't want to test either. You might want to do a xor-swap, like in a[i]^=a[m]^=a[i]^=a[m]. This also avoids the need to declare t.
FUZxxl

@FUZxxl I believe an xor swap causes problems if i==m.
Geobits

@Geobits indeed. I missed that possibility.
FUZxxl

I was just trying to figure out why that wasn't working... should have remembered that. Also I do need s(a,m)int*a for visual studio and the intel compiler. Don't have gcc or clang installed to test, but I assume they will also complain.
pseudonym117

This is pretty impressively golfed. After trying a lot of modifications that didn't save anything, I did manage to see a way to save 2 characters. If you change the swap order so that the first swap statement becomes t=a[i], you can then move the i=rand()%m-- statement inside as the array index.
Runer112

3

Octave, 88 77 bytes

function s=r(s)for(i=length(s):-1:1)t=s(x=randi(i));s(x)=s(i);s(i)=t;end;end

Yet another Fisher-Yates implementation... Should be fairly straightforward if I add the usual line returns and spacing:

function s=r(s)
  for(i=length(s):-1:1) # Counting down from i to 1
    t=s(x=randi(i));    # randi is builtin number generator for an int from 0 to i
    s(x)=s(i);
    s(i)=t;
  end
end

The "end" keywords really kill the golf score here, unfortunately. Hey, I can use "end" instead of "endfor" and "endfunction"!


1
Just FYI, the "bytes" isn't really required by the code, it just makes sure there is a headline, which contains a comma (to separate the language) and at least one number after the comma, and then just chooses the last number that isn't crossed out. Having "bytes" in there is still nice though. ;)
Martin Ender

1
You could save 1 byte by using numel instead of lenght. As a bonus your program would also work with 2-D arrays aka matrices ;)
paul.oderso

2

Java 8, 77

(x)->{for(int i=x.length,j,t;;t=x[j*=Math.random()],x[j]=x[i],x[i]=t)j=i--;};

It's a lambda taking int[] and returning void. My first attempt seemed not very interesting, so I decided to have it exit by throwing an exception.

Test program:

interface shuff {
    void shuff(int[] x);
}
class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        shuff s = (x)->{for(int i=x.length,j,t;;t=x[j*=Math.random()],x[j]=x[i],x[i]=t)j=i--;};
        int[] x = {3, 9, 2, 93, 32, 39, 4, 5, 5, 5, 6, 0};
        try {
            s.shuff(x);
        } catch(ArrayIndexOutOfBoundsException _) {}
        for(int a:x) System.out.println(a);
    }
}

1
Isn't it cheating to use a lambda to get around having to write a function signature, when you have to supply a delegate in order to use the lambda anywhere? Also... can't you drop the parentheses around Math.random()?
Rawling

1
@Rawling You could vote in this meta question. Currently, there are 9 votes in favor of lambdas, and 0 against. Yes, the parentheses can be removed.
feersum

Huh, if there's a meta post and a so-far-consensus then fire away. (And enjoy the two-lower golf score on me :p)
Rawling

3
I think, it's unfair for function to stop by exception in a normal case, is it?
Qwertiy

1
@Qwertiy To each his own... You think it's unfair, I think it's great.
feersum

2

Golflua, 37

How to run Golflua?

~@i=1,#X`r=M.r(i)X[i],X[r]=X[r],X[i]$

The input is provided as a table in the variable X. The table is shuffled in place.

Example usage:

> X={0,-45,8,11,2}
> ~@i=1,#X`r=M.r(i)X[i],X[r]=X[r],X[i]$
> w(T.u(X))
-45 0 8 11 2

2

R, 79 bytes

f=function(x){n=length(x);for(i in 1:n){j=sample(i:n,1);x[c(i,j)]=x[c(j,i)]};x}

This is a straightforward implementation of the Fisher-Yates shuffle. The R function sample draws a simple random sample of a given size from a given vector with equal probability. Here we're drawing a random sample of size 1 at each iteration from the integers i, ..., n. As stated in the question, this can be assumed to be O(1), so in all this implementation should be O(N).


2

Matlab, 67

Also implementing Fisher-Yates.

a=input('');n=numel(a);for i=1:n;k=randi(i);a([i,k])=a([k,i]);end;a

I thought it was too bad I could not use Matlab's randperm function. But after some fiddling around, I thought I may look at the source of randperm to see how it is done, and I was astonished to see that there was just one line: [~,p] = sort(rand(1,n)) =)


2

Perl, 44

sub f{($_[$x],$_)=($_,$_[$x=rand++$i])for@_}

Another perl in 44 characters. Example use:

@x=(1..9);f(@x);print@x

2

Mathematica, 82 90 83 93 bytes

Note: This variation the Fisher-Yates shuffle is actually Martin Büttner's solution, with some code paring by alephalpha. s is the input array. Nothing fancy-smancy, but sometimes the simple things are the most elusive.

f@s_:=(a=s;m=Length@a;Do[t=a[[r=RandomInteger@{1,m-1}]];a[[r]]=a[[m]]; a[[m]]=t,{n,1,m-1}];a)

You can use Do here. It's shorter than While.
alephalpha

2

Ruby, 57 bytes

->a{a.size.times{|i|j=rand(i+1);a[i],a[j]=a[j],a[i]};p a}

Input (as lambda function):

f.([1,2,3,4,5])

Output:

[2, 1, 4, 3, 5]


2

K, 31 chars

f:{{l[i:x,1?x]:l@|i}'|!#l::x;l}

Not quite as short as the one I put up before (which got disqualified)...oh well.

It's a basic Fisher-Yates shuffle. This was built with lots of help from the Kona mailing list.


2

JavaScript (ES6), 66

This function shuffles the array in place. It also returns a byproduct array that is NOT the shuffled output and must not be considered.

F=a=>a.map((v,i)=>a[a[i]=a[j=0|i+Math.random()*(a.length-i)],j]=v)

2

MATL, 16 bytes

XH`HnYr&)XHxvHHn

Try it online!

Fisher-Yates in MATL. Almost a third of this program is devoted to the letter H, which corresponds to the clipboard function in MATL.

Basically, H stores the unused items from the input, while the stack keeps track of the shuffled list.


2

Japt, 12

rÈiMqZÄ Y}[]

Try it!

-10 (about half ;) thanks to @Shaggy!

I have been wanting to try out a golfing language, and the Japt interpreter had good documentation and a way to try things out in the browser.

Below is the strategy I took:

  • Reduce input seeding with an empty array
  • At each step, find a random slot to insert the current element

1
Welcome to Japt, good to have you with us. I think this works for 9 bytes, using the same method. If the RNG isn't satisfactory, though, then try this instead.
Shaggy

@Shaggy - Thanks for the tips! :) I ended up using a slightly modified version of your 2nd solution. Since the 3rd parameter of the reduce function is an index, we already know the length.
dana

1

Javascript ES6, 69

a=>{m=a.length;while(m)[a[m],a[i]]=[a[i=~~(Math.random()*m--)],a[m]]}

It's Fisher–Yates.

PS: Can be tested in Firefox


@MartinBüttner, removed it :)
Qwertiy

1

Pyth, 27 bytes

Test it here

FkQJOhlYaY?@YtJJkIJ XYtJk;Y

This is an implementation of the incremental Fisher-Yates shuffle, mentioned second here.


1

Haskell, 170

import System.Random
import Data.Array.IO
s a=do(_,n)<-getBounds a;sequence$map(\i->do j<-randomRIO(i,n);p<-a%i;q<-a%j;writeArray a j p;return q)[1..n]where(%)=readArray

Another Fisher-Yates solution inspired by the algorithm at https://wiki.haskell.org/Random_shuffle.

s is a function which has signature: IOArray Int a -> IO [a]


1

CJam - 30

q~_,,W%{_I=I)mr:J2$=@I@tJ@t}fI

Try it at http://cjam.aditsu.net/

Example input: [10 20 30 40 50]
Example output: 3020401050 (add a p at the end of the code for pretty printing)

If the code is allowed to take the input from the stack (like a function), then the first 2 characters can be removed, reducing the size to 28.

Explanation:

The code is longer than I hoped, due to the lack of a "swap" operator for arrays
(to be implemented later :p)

q~            read and evaluate the input (let's call the array "A")
_,,           make an array [0 1 2 ... N-1] where N is the size of A
W%            reverse the array, obtaining [N-1 ... 2 1 0]
{…}fI         for I in this array
    _I=       push A[I]
    I)mr:J    push a random number from 0 to I (inclusive) and store it in J
              stack: A, A[I], J
    2$=       get A[J]
    @I@t      set A[I] = A[J]
              stack: former A[I], A
    J@t       set A[J] = former A[I]

As mentioned in the comments, I'm afraid this is invalid. At the very least _ is O(N) (inside an O(N) loop). Unfortunately, I don't see a way to work around that in CJam.
Martin Ender

Lists are handled like immutable objects, so duplication is just implemented as duplicating the reference. It's actually the t that kills it, as it can't mutate the list and now must create a copy.
Runer112

@MartinBüttner I was about to post the same thing as Runer112; yes there might be a problem with t, I'd like to improve it in future versions..
aditsu

So this code follows the spirit of the question, but not the "letter", due to internal language implementation issues.
aditsu

1

JavaScript (ES 6), 61

S=a=>(a.map((c,i)=>(a[i]=a[j=Math.random()*++i|0],a[j]=c)),a)

You can test it here by just adding a line that says shuffle = S (Firefox only).


1

STATA, 161

di _r(s)
set ob wordcount($s)
token $s
g a=0
foreach x in $s{
gl j=floor(runiform()*_n)+1
replace a=`$j' if word($s,_n)=`x'
replace a=`x' if word($s,_n)=`$j'
}
l

Expects input as space separated numbers. I can remove the headers and observation numbers from the output if you would like, but otherwise this is shorter.


What's _n in this?
Martin Ender

_n is the number of the current observation.
bmarks


1

SQF, 91 bytes

params["i"];{n=floor random count i;i set[_forEachIndex,i select n];i set[n,_x]}forEach i;i

1
This is biased (see "swap (i <-> random)" on Will It Shuffle), but you can turn it into Fisher-Yates (which is unbiased) by replacing %x with %i.
Martin Ender

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.