Random Golf of the Day # 1: Shuffle an Array


35

Informazioni sulla serie

Farò una piccola serie di sfide di code-golf che ruotano attorno al tema della casualità. Questo sarà fondamentalmente un campo da golf a 9 buche , ma si sviluppa su diverse domande. Puoi partecipare a qualsiasi sfida individualmente come se fosse una domanda normale.

Tuttavia, manterrò una classifica per tutte le sfide. La serie supererà 9 sfide (per ora), una pubblicata ogni pochi giorni. Ogni utente che partecipa a tutte e 9 le sfide è idoneo a vincere l'intera serie. Il loro punteggio complessivo è la somma dei loro contributi più brevi per ogni sfida (quindi se si risponde a una sfida due volte, viene conteggiata solo la risposta migliore per il punteggio). Se qualcuno deterrà il primo posto in questa classifica generale per 28 giorni , assegnerò loro un premio di 500 rappresentanti .

Anche se ho un sacco di idee in programma per la serie, le sfide future non sono ancora state messe sulla pietra. Se hai qualche suggerimento, per favore fatemelo sapere sul post sandbox pertinente .

Hole 1: Shuffle an Array

Il primo compito è piuttosto semplice: dato un array di numeri interi non vuoto, mescolarlo in modo casuale. Ci sono alcune regole però:

  • Ogni possibile permutazione deve essere restituita con la stessa probabilità (quindi lo shuffle dovrebbe avere una distribuzione uniforme). Puoi verificare se il tuo algoritmo è uniforme / imparziale implementandolo in JavaScript su Will It Shuffle , che produrrà una matrice dei pregiudizi - il risultato dovrebbe apparire uniforme come i loro Fisher-Yates o l' ordinamento (ordine casuale) .
  • Non è necessario utilizzare alcun metodo incorporato o di terze parti per mescolare l'array o generare una permutazione casuale (o enumerare tutte le permutazioni). In particolare, l'unica funzione casuale incorporata che è possibile utilizzare è ottenere un singolo numero casuale alla volta . Si può supporre che qualsiasi built-in casuali piste metodo numero in O (1) ed è perfettamente uniforme sull'intervallo richiesto (in senso matematico - puoi ignorare i dettagli della rappresentazione in virgola mobile qui). Se la tua lingua ti consente di ottenere un elenco di m numeri casuali contemporaneamente, puoi utilizzare questa funzione, a condizione che i numeri m siano indipendenti l'uno dall'altro e lo conti come O (m).
  • L'implementazione non deve superare una complessità temporale di O (N) , in cui N è la dimensione dell'array da mescolare. Ad esempio, non è possibile "ordinare per numeri casuali".
  • Puoi mescolare l'array in posizione oppure creare un nuovo array (nel qual caso il vecchio array può essere modificato come preferisci).

È possibile scrivere un programma completo o una funzione e accettare input tramite STDIN, argomento della riga di comando, argomento della funzione o prompt e produrre output tramite il valore restituito o stampando su STDOUT (o l'alternativa più vicina). Se si scrive una funzione che mescola l'array in posizione, non è necessario restituirlo naturalmente (a condizione che la propria lingua consenta di accedere all'array modificato dopo il ritorno della funzione).

L'input e l'output possono essere in qualsiasi elenco o formato stringa conveniente, ma devono supportare numeri interi arbitrari nell'intervallo -2 31 ≤ x <2 31 . In linea di principio, il codice dovrebbe funzionare per array fino alla lunghezza 2 31 , sebbene ciò non debba necessariamente adattarsi alla memoria o completarsi entro un ragionevole lasso di tempo. (Non voglio vedere limiti di dimensione arbitraria per loop hardcode o qualcosa del genere.)

Questo è il golf del codice, quindi vince l'invio più breve (in byte).

Classifica

Il frammento seguente genererà una classifica in tutte le sfide della serie.

Per assicurarti che le tue risposte vengano visualizzate, inizia ogni risposta con un titolo, utilizzando il seguente modello Markdown:

# Language Name, N bytes

dov'è Nla dimensione del tuo invio. Se si migliora il punteggio, è possibile mantenere i vecchi punteggi nel titolo, colpendoli. Per esempio:

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

(La lingua non è attualmente mostrata, ma lo snippet richiede e analizza, e potrei aggiungere una classifica per lingua in futuro.)


7
Sono deluso dal fatto che non ci sia permesso di essere "intelligenti" e di utilizzare funzioni di libreria diverse da "ottenere un numero casuale" . Vogliamo esaminare ancora altre 69 implementazioni del mescolamento di Fisher-Yates? Si prega di considerare la rimozione di questa regola nelle attività future. Inoltre, perché un limite alla complessità temporale? Per favore, considera di rilassarlo almeno su O (n ^ 2); Penso anche che qualcuno potrebbe trovare un'implementazione particolarmente golfizzata se si consente O (n!).
Anatolyg

7
@anatolyg La rimozione delle restrizioni equivale a ogni risposta sia sortby(random)(il motivo della restrizione temporale) o semplicemente .shuffle()(il motivo della restrizione integrata), che penso sia molto meno intelligente rispetto al dover implementare Fisher-Yates o qualche altro approccio.
Martin Ender,

1
Se viene mischiato in posizione, una funzione deve restituire l'array o è sufficiente che venga modificata? Posso scrivere una funzione per shuffle(array)anziché newArray=shuffle(array)?
Geobits il

1
@Bakuriu Affermare che puoi ordinare in tempo lineare se i numeri sono fissi è un po 'come affermare che puoi fare qualsiasi cosa in O (1) se le dimensioni dell'input sono fisse. Inoltre, la restrizione pertinente è costituita da matrici di dimensioni fisse, non da numeri interi di dimensioni fisse, poiché le dimensioni dell'array determinano la dimensione necessaria per i numeri casuali. Comunque, le limitazioni sulla complessità temporale sono ovviamente per l'algoritmo generale che implementate, mentre i limiti sulle dimensioni di input sono in atto, quindi non dovete usare numeri interi di precisione arbitraria se la vostra lingua non li usa immediatamente .
Martin Ender,

2
Perché la soluzione di Adám arriva a 43319 byte quando in realtà è 14?
boboquack

Risposte:


20

Dyalog APL, 25 24 byte

Primo per la soluzione di 25 caratteri: 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[⍵]

Dopo alcune trasformazioni di equivalenza su quanto sopra:

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

possiamo liberarci del compito i←e salvare un personaggio:

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


3
... mente. soffiato.
danwyand,

1
una lingua che devo leggere da destra a sinistra ?? Wow!
Luminoso

5
@Luminoso come spesso accade con la notazione matematica: sin cos ln sqrt x
ngn

4
@ngn quando lo metti in quel modo, il mio commento precedente sembra ridicolo. ha.
Luminoso

5
@ronalchn Esistono codifiche a 8 bit per APL, come questa o questa ; Ho sentito che Dyalog usa uno di questi, in alternativa a Unicode.
Anatolyg,

12

80386 codice macchina, 44 24 byte

Hexdump del codice:

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

Grazie a FUZxxl, che ha suggerito di usare l' rdrandistruzione.

Ecco il codice sorgente (può essere compilato da 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;
    }
}

Ancora un'altra implementazione di Fisher-Yates. Gran parte del golf è stato ottenuto passando parametri nei registri.


1
Avresti potuto usare anche rdrandper cazzate e risatine.
FUZxxl

@FUZxxl Me ne sono completamente dimenticato! Peccato che rimuova la parte più interessante della mia risposta ...
Anatolyg

9

Java, 88 101

Un shuffle Fisher-Yates di base fa il trucco. Ho la sensazione che verrà usato abbastanza comunemente qui, poiché è rapido e facile da implementare. C'è un po 'di loop / incarichi stipati qui, ma sinceramente non c'è troppo da golf; è solo breve per natura.

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--;}

Con alcune interruzioni di riga:

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--;
}

Questo si mescola sul posto, modificando l'array originale s[]. Programma di test:

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, la sfida afferma che si può presumere che " sia perfettamente uniforme nell'intervallo richiesto ". L'intervallo richiesto Math.random()ha una dimensione che è una potenza di due, quindi questo non soddisfa le specifiche.
Peter Taylor,

1
Le interpretazioni di @PeterTaylor Jan e Geobits sono in effetti il ​​modo in cui intendevo la regola - che non devi preoccuparti dell'effettiva durata del ciclo del tuo PRNG.
Martin Ender,

1
@ MartinBüttner la durata del ciclo non è il problema qui - che è coperto dalla tua regola. La grossolanità dei galleggianti è.
John Dvorak,

3
@TheBestOne È più corto di un byte rispetto all'unica soluzione python attualmente pubblicata;)
Geobits

1
Non più! : D
Sp3000,

8

Python 2, 86 byte

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

Questa è una funzione che mescola l'array in posizione senza restituirlo, usando un'implementazione diretta del riordino Fisher-Yates . Ottenere numeri casuali da Python è costoso ...

Grazie a @xnor e @colevk per i suggerimenti.


L'espressione di gamma sembra piuttosto ingombrante. Sicuramente è più breve il conto alla rovescia manualmente come while i:i-=1;...?
xnor

@xnor Sì, grazie. Continuo a dimenticare che whiletende ad essere più breve rispetto fora questo genere di cose ...
Sp3000,

1
Awww ... ora la mia risposta Java non sta battendo questo. Sono stato abbastanza felice per un breve periodo :(
Geobits

È possibile salvare altri 2 byte effettuando i=len(L)e inserendo il decremento all'inizio del ciclo while.
Colevk,

8

J, 45 44 caratteri

Questo è stato difficile.

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

Ecco una spiegazione:

  1. # y: Il conteggio di y, cioè il numero di elementi in y.
  2. ?@# y: Un numero casuale distribuito uniformemente nell'intervallo da 1a (#y)-1.
  3. x { y: La voce dal y di indice x.
  4. (<<<x) { y: Tutti gli articoli tranne l'articolo all'indice xin y.
  5. x , y: y aggiunto a x.
  6. x ({ , <^:3@[ { ]) y: L'elemento all'indice xin y, quindi tutti gli altri elementi.
  7. (?@# ({ , <^:3@[ { ]) ]) yA caso y, poi tutti gli altri oggetti.
  8. x {. y: I primi xelementi presi da y.
  9. x }. y: Le prime xvoci caduto da y.
  10. x ({. , }.) y: I primi xoggetti presi da y, poi i primi xoggetti caduti day
  11. x ({. , (?@# ({ , <^:3@[ { ]) ])@}.) y: I primi xarticoli presi da y, quindi i primi xarticoli yelaborati come al numero 7.
  12. x ({. , ?@#@}. ({ , <^:3@[ { ]) }.) y: La stessa cosa con il drop tirato dentro per salvare un personaggio.
  13. u/ y: u inserito tra gli elementi di y.
  14. < y: in y scatola .
  15. <"0 y: Ogni articolo in y scatola .
  16. i. y: numeri interi da 0a y - 1.
  17. i.@# y: numeri interi da 0a (#y) - 1.
  18. (<"0@i.@# , <) y: Numeri interi da 0ad (#y) - 1ogni inscatolati e poi yin un unico box. Ciò è necessario perché le matrici in J sono uniformi. Una casella nasconde la forma del suo contenuto.
  19. x u&v y: mi piace (v x) u (v y).
  20. > y: y aperto , cioè senza la sua scatola.
  21. x ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&> y la frase del numero 12 si applicava ai suoi argomenti non in scatola.
  22. ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&>/ yla frase del numero 21 inserita tra le voci di y.
  23. ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&>/@(<"0@i.@# , <) yla frase del numero 22 si applicava al risultato della frase del numero 18, oppure una permutazione uniforme degli elementi di y.

1
Non riesco proprio a distinguere tutte le parentesi. E quel triplo pugilato <@<@<@[è anche un mistero ... In attesa di spiegazioni. :)
randomra,

2
Una volta spiegato questo, potrei essere molto più propenso a votare questa risposta ;-)
John Dvorak,

@randomra Ecco qua.
FUZxxl,

@JanDvorak La spiegazione è soddisfacente?
FUZxxl,

Grande spiegazione! Non sapevo di tutto l'uso in scatola di from( {). E mi piace molto il &>/trucco per manipolare un elenco. Sono sicuro che avrei potuto usarlo un paio di volte prima.
randomra,

5

Pyth, 25 byte

Provalo qui.

Ancora un'altra implementazione di Fisher-Yates. È essenzialmente lo stesso della soluzione python @ Sp3000, solo in pyth.

FNrlQ1KONJ@QN XXQN@QKKJ)Q

Grazie a @Jakube per il trucco di scambio

<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

Puoi salvare due byte combinando queste due assegnazioni di elenco: `XXQN @ QKKJ` invece di` XQN @ QK XQKJ`.
Jakube

@Jakube grazie per il suggerimento. Sapevo che doveva esserci un modo per scambiare valori in un elenco, e questo è davvero intelligente. Dovresti aggiungerlo all'elenco dei suggerimenti.
Maltysen,

4

Perl, 68 56 44

Come molte altre soluzioni, questo utilizza l' algoritmo Fisher-Yates .

Usando il commento di nutki , 12 caratteri vengono salvati usando $_invece $ied eseguendo le operazioni negli indici di array.

44:

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

56:

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

Questo è il mio primo codegolf.


Non è un brutto inizio, non sapevo che si potesse usare @_[...]come valore come quello. Può essere ulteriormente approfondito sub f{@_[$_,$j]=@_[$j=rand$_,--$_]for 1..@_}.
nutki,

3

C, 63 61 60 byte

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

Solo un'implementazione diretta di Fischer-Yates che ordina la matrice data in atto. Compila e collega perfettamente con il compilatore di Visual Studio (vs2013, non ho testato le altre versioni) e il compilatore Intel. La firma della funzione è piacevole s(int array[], int length). Sono legittimamente colpito dal battere Python e Ruby.

Questo presuppone che srand()sia chiamato e rand () sia implementato correttamente, ma credo che questa regola lo consenta:

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

Versione ben formattata:

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

Penso che sia sufficiente creare l'intestazione della funzione s(a,m)*a{, ma non ne sono sicuro e non voglio nemmeno provarlo. Potresti voler fare uno xorswap, come in a[i]^=a[m]^=a[i]^=a[m]. Ciò evita anche la necessità di dichiarare t.
FUZxxl,

@FUZxxl Credo che uno scambio xor causi problemi se i==m.
Geobits,

@Geobits davvero. Ho perso quella possibilità.
FUZxxl,

Stavo solo cercando di capire perché non funzionasse ... avrei dovuto ricordarlo. Inoltre ho bisogno s(a,m)int*adi Visual Studio e del compilatore Intel. Non ho gcc o clang installati per testare, ma presumo che si lamentino anche.
pseudonimo117,

Questo è abbastanza impressionante da golf. Dopo aver provato molte modifiche che non hanno salvato nulla, sono riuscito a vedere un modo per salvare 2 caratteri. Se si modifica l'ordine di scambio in modo che diventi la prima istruzione di scambio t=a[i], è possibile spostare l' i=rand()%m--istruzione all'interno come indice dell'array.
Runer112

3

Ottava, 88 77 byte

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

Ancora un'altra implementazione di Fisher-Yates ... Dovrei essere abbastanza semplice se aggiungo i soliti ritorni di linea e spaziatura:

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

Sfortunatamente, le parole chiave "fine" uccidono davvero il punteggio del golf qui. Ehi, posso usare "end" invece di "endfor" e "endfunction"!


1
Cordiali saluti, i "byte" non sono richiesti dal codice, si accerta solo che ci sia un titolo, che contiene una virgola (per separare la lingua) e almeno un numero dopo la virgola, quindi sceglie solo l'ultimo numero non barrato. Avere "byte" è comunque bello. ;)
Martin Ender,

1
È possibile salvare 1 byte utilizzando numelinvece di lenght. Come bonus il tuo programma funzionerebbe anche con array 2-D aka matrici;)
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--;};

È un lambda che prende int[]e ritorna vuoto. Il mio primo tentativo non è sembrato molto interessante, quindi ho deciso di farlo uscire lanciando un'eccezione.

Programma di test:

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
Non è imbarazzante usare un lambda per aggirare la necessità di scrivere una firma di funzione, quando è necessario fornire un delegato per usare il lambda ovunque? Inoltre ... non riesci a rilasciare le parentesi Math.random()?
Rawling

1
@Rawling Potresti votare in questa meta domanda . Attualmente, ci sono 9 voti a favore di lambdas e 0 contro. Sì, le parentesi possono essere rimosse.
feersum

Eh, se c'è un meta post e un consenso così lontano, allora sparalo. (E godetevi il punteggio di golf inferiore a due su di me: p)
Rawling

3
Penso, non è giusto che la funzione si fermi per eccezione in un caso normale, vero?
Qwertiy,

1
@Qwertiy A ciascuno il suo ... Pensi che sia ingiusto, penso che sia grandioso.
feersum

2

Golflua, 37

Come eseguire Golflua?

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

L'input viene fornito come tabella nella variabile X. La tabella viene mescolata in posizione.

Esempio di utilizzo:

> 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 byte

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}

Questa è un'implementazione diretta del riordino Fisher-Yates. La funzione R sampledisegna un semplice campione casuale di una determinata dimensione da un dato vettore con uguale probabilità. Qui stiamo disegnando un campione casuale di dimensione 1 ad ogni iterazione dagli interi i, ..., n. Come indicato nella domanda, questo può essere assunto come O (1), quindi in tutta questa implementazione dovrebbe essere O (N).


2

Matlab, 67

Anche l'implementazione di Fisher-Yates.

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

Ho pensato che fosse un peccato non poter usare la randpermfunzione di Matlab . Ma dopo aver giocherellato un po ', ho pensato di guardare la fonte randpermper vedere come è fatto, e sono rimasto sorpreso nel vedere che c'era solo una riga: [~,p] = sort(rand(1,n))=)


2

Perl, 44

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

Un altro perl in 44 caratteri. Esempio di utilizzo:

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

2

Mathematica, 82 90 83 93 byte

Nota: questa variante del shuffle Fisher-Yates è in realtà la soluzione di Martin Büttner, con un po 'di codice di alephalpha. sè l'array di input. Niente di speciale, ma a volte le cose semplici sono le più sfuggenti.

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)

Puoi usare Doqui. È più corto di While.
alephalpha,

2

Rubino, 57 byte

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

Input (come funzione lambda):

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

Produzione:

[2, 1, 4, 3, 5]


2

K, 31 caratteri

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

Non abbastanza basso come quello che ho messo prima (che è stato squalificato) ... vabbè.

È un shuffle Fisher-Yates di base. Questo è stato creato con molto aiuto dalla mailing list di Kona .


2

JavaScript (ES6), 66

Questa funzione mescola l'array in posizione. Restituisce anche un array di sottoprodotti che NON è l'output mischiato e non deve essere considerato.

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

2

MATL , 16 byte

XH`HnYr&)XHxvHHn

Provalo online!

Fisher-Yates in MATL. Quasi un terzo di questo programma è dedicato alla lettera H, che corrisponde alla funzione Appunti in MATL.

Fondamentalmente, Hmemorizza gli elementi inutilizzati dall'input, mentre lo stack tiene traccia dell'elenco mescolato.


2

Japt, 12

rÈiMqZÄ Y}[]

Provalo!

-10 (circa la metà;) grazie a @Shaggy!

Volevo provare un linguaggio da golf e l'interprete Japt aveva una buona documentazione e un modo per provare le cose nel browser.

Di seguito è la strategia che ho preso:

  • Ridurre il seeding di input con un array vuoto
  • Ad ogni passaggio, trova uno slot casuale per inserire l'elemento corrente

1
Benvenuto in Japt, è un piacere averti con noi. Penso che questo funzioni per 9 byte, usando lo stesso metodo. Se l'RNG non è soddisfacente, prova invece questo .
Shaggy,

@Shaggy - Grazie per i suggerimenti! :) Ho finito per usare una versione leggermente modificata della tua seconda soluzione. Poiché il 3o parametro della funzione di riduzione è un indice, conosciamo già la lunghezza.
dana,

1

Javascript ES6, 69

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

Sono Fisher-Yates.

PS: può essere testato in Firefox


@ MartinBüttner, rimosso :)
Qwertiy


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

Un'altra soluzione Fisher-Yates ispirata all'algoritmo su https://wiki.haskell.org/Random_shuffle .

s è una funzione che ha la firma: IOArray Int a -> IO [a]


1

CJam - 30

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

Provalo su http://cjam.aditsu.net/

Esempio di input: [10 20 30 40 50]
Esempio di output: 3020401050(aggiungi pa alla fine del codice per una stampa carina)

Se al codice è consentito prendere l'input dallo stack (come una funzione), è possibile rimuovere i primi 2 caratteri, riducendo la dimensione a 28.

Spiegazione:

Il codice è più lungo di quanto sperassi, a causa della mancanza di un operatore "swap" per gli array
(da implementare in seguito: 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]

Come accennato nei commenti, temo che ciò non sia valido. Per lo meno _è O (N) (all'interno di un ciclo O (N)). Sfortunatamente, non vedo un modo per aggirare questo problema in CJam.
Martin Ender,

Gli elenchi vengono gestiti come oggetti immutabili, quindi la duplicazione viene implementata semplicemente come duplicazione del riferimento. In realtà è quello tche lo uccide, in quanto non può mutare l'elenco e ora deve crearne una copia.
Runer112,

@ MartinBüttner Stavo per pubblicare la stessa cosa di Runer112; sì, potrebbe esserci un problema t, mi piacerebbe migliorarlo nelle versioni future ..
aditsu,

Quindi questo codice segue lo spirito della domanda, ma non la "lettera", a causa di problemi di implementazione del linguaggio interno.
aditsu,

1

JavaScript (ES 6), 61

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

Puoi provarlo qui semplicemente aggiungendo una riga che dice shuffle = S(solo Firefox).


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

Prevede input come numeri separati da spazio. Se lo desideri, posso rimuovere le intestazioni e i numeri di osservazione dall'output, ma altrimenti è più breve.


Cosa c'è _nin questo?
Martin Ender,

_n è il numero dell'osservazione corrente.
segna il


1

SQF, 91 byte

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

1
Questo è di parte (vedi "swap (i <-> random)" su Will It Shuffle), ma puoi trasformarlo in Fisher-Yates (che è imparziale) sostituendolo %xcon %i.
Martin Ender,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.