Genera uno squilibrio casuale


30

Descrizione della sfida

Uno "squilibrio" di una sequenza è una permutazione in cui nessun elemento appare nella sua posizione originale. Ad esempio ECABDè un disordine di ABCDE, ma CBEDAnon è:

ABCDE
 | |   <- B and D are in their orignal positions
CBEDA

Data una sequenza, genera un suo disordine casuale.

Gli appunti

  • Puoi prendere una stringa come input o un array / elenco di elementi (numeri interi, caratteri, oggetti ...)

  • Invece di restituire un nuovo oggetto, è possibile modificarne uno esistente scambiandone gli elementi

  • Ogni derangement dovrebbe avere la stessa probabilità di essere generato

  • Puoi presumere che ci sia più di un elemento nella sequenza e nessuno appare più di una volta



3
@VotoToChiudi: ahah, totalmente distrutto
shooqie

Non so molto di tutto questo, ma è in qualche modo correlato al teorema del punto fisso ... secondo il quale le cose finiranno sempre nella loro posizione o qualcosa del genere ...? Scommetto che mi sbaglio ma qualcuno, per favore, mi corregga :)
Farhan Anam,

C'è qualche garanzia che gli elementi saranno unici o che possano contenere duplicati?
Carcigenicato il

1
@Carcigenicato: è proprio lì nella descrizione; puoi presumere che non ci siano duplicati
shooqie,

Risposte:


12

CJam , 14 byte

q:X{mr_X.=:|}g

Provalo online!

Continua a mescolare l'input fino a quando non è un disordine.

Spiegazione

q:X   e# Read input and store it in X.
{     e# While the condition at the end of the loop is truthy...
  mr  e#   Shuffle the string.
  _X  e#   Duplicate it and push the input.
  .=  e#   Element-wise equality check.
  :|  e#   Reduce OR over the list, gives something truthy if any character
      e#   remained in its original position.
}g

1
Vorrei che OP avesse specificato che le soluzioni avrebbero dovuto garantire che finissero sempre.
John Dvorak,

4
@JanDvorak Bene, la probabilità che ciò non finisca è 0. Ma hai ragione nel richiedere che un tempo di esecuzione deterministico avrebbe reso la sfida più interessante.
Martin Ender,

La probabilità è effettivamente 0? L'operazione di shuffle non sarà perfetta, come funziona davvero? Penso che questa sia probabilmente una buona approssimazione di ciò che l'OP ha richiesto, ma dubito che le probabilità di ogni derangement siano le stesse (probabilmente dipende da un valore di base del PRNG che è probabilmente usato dall'operazione shuffle).
Nessuno il

3
@Nobody Dubito che tu possa ottenere risultati perfettamente uniformi da un PRNG usando qualsiasi algoritmo. Tuttavia, supponendo che lo shuffle stesso sia uniforme (cosa che i documenti Java in qualche modo garantiscono con "Tutte le permutazioni si verificano con approssimativamente la stessa probabilità"), una soluzione basata sul rifiuto produrrà anche disparità uniformi, poiché ogni derangement è una permutazione e ciascuna la permutazione ha la stessa probabilità.
Martin Ender,

1
@Nobody Math nerd qui. Una condizione che ha esito positivo o negativo viene chiamata statistica di Bernoulli. Ciò implica che la probabilità di aver bisogno di k prove per il primo successo è (1 - p) ^ (k - 1) * p, dove p è la probabilità di un disallineamento riuscito. È facile vedere che man mano che k cresce, la probabilità di aver bisogno di prove k diventa sempre più piccola. Pertanto, diciamo che l'algoritmo si arresta con probabilità 1 ("quasi sicuramente"), ma non è impossibile che non si fermi mai.
Maservant,

9

Gelatina , 6 byte

Ẋ=³S$¿

Provalo online!

Spiegazione

Ẋ    ¿    Shuffle the given list while this is nonzero for it:
    $       A two-step process:
 =³           Element-wise equality of it and L (the original list)...
   S          Sum the ones in this binary array.

Jonathan Allan ha salvato un byte.


5
Quindi hai il tuo cappello Winter Bash in anticipo? :-)
Luis Mendo il

2
È ora di disegnare una bella nuova immagine, Ẋ=³S$¿salva un byte.
Jonathan Allan il

2
Eh, non l'ho mai saputo $. Grazie!
Lynn il

Sono 6 caratteri, ma più di 6 byte. Ẋ = ³S $ ¿le lunghezze di byte sono: 312112. Quindi 10 byte in totale.
mxfh,

6

Python, 85 byte

Modifica l'elenco passato ad esso (consentito da meta e nella domanda).

from random import*
def D(l):
 o=l[:]
 while any(x==y for x,y in zip(o,l)):shuffle(l)

Provalo online qui!


1
Se specifichi Python 2, penso che potresti sostituirlo def D(l):con l=input()e quindi salvare gli spazi di rientro nelle righe seguenti (quindi hai un programma invece di una funzione). Non ha votato, però!
Mathmandan,

@mathmandan buona idea, ma poi dovrei stamparlo di nuovo se è un programma completo, che costa più byte.
FlipTack

1
Ok se lo dici tu. Immagino che le specifiche sembrassero dire che non dovevi stampare o restituire il risultato - che prendere un elenco [dall'input dell'utente] e rimescolarlo sarebbe sufficiente. Ma è ragionevole leggere "esistente" come "esistente prima di eseguire qualsiasi codice", nel qual caso sono d'accordo con te. (Forse c'è un consenso consolidato su questo.) :)
Mathmandan,

5

ES6 (Javascript), 71, 69 byte

L'input e l'output sono array, dovrebbero funzionare con qualsiasi tipo di elemento (stringhe, numeri ecc.), Purché possano essere confrontati con "==".

golfed

F=s=>(r=[...s]).sort(_=>Math.random()-.5).some((e,i)=>s[i]==e)?F(s):r

Test

F=s=>(r=[...s]).sort(_=>Math.random()-.5).some((e,i)=>s[i]==e)?F(s):r

F(['A','B','C','D'])
Array [ "D", "C", "A", "B" ]

F(['A','B','C','D'])
Array [ "D", "A", "B", "C" ]

F(['A','B','C','D'])
Array [ "C", "D", "B", "A" ]

F(['A','B','C','D'])
Array [ "D", "C", "B", "A" ]

F(['A','B','C','D'])
Array [ "C", "D", "B", "A" ]

Snippet interattivo

F=s=>(r=[...s]).sort(_=>Math.random()-.5).some((e,i)=>s[i]==e)?F(s):r

function G() {
    console.log(F(T.value.split``).join``); 
}
<input id=T value="ABCDEF"><button id=G onclick="G()">GENERATE</button>


5

Perl 6 , 33 byte

{first (*Zne$_).all,.pick(*)xx *}

Un lambda che accetta come input un elenco di numeri interi o caratteri e restituisce un nuovo elenco.

Se deve supportare elenchi di valori arbitrari , nedovrebbe essere sostituito con !eqv(+2 byte).

( Provalo online. )

Spiegazione:

  • { }: Definisce un lambda.
  • .pick(*): Genera un riordino casuale dell'elenco di input.
  • .pick(*) xx *: Crea una sequenza pigra e infinita di tali shuffle.
  • (* Zne $_).all: Un lambda che comprime due elenchi (il suo argomento *e l'argomento del lambda esterno $_) con l' neoperatore (uguaglianza stringa negativa), producendo un elenco di valori booleani, quindi crea una allgiunzione per comprimerli in un singolo stato booleano.
  • first PREDICATE, SEQUENCE: Prende il primo elemento dalla nostra sequenza infinita di permutazioni che soddisfa il test di "squilibrio".

4

Brachylog , 19 18 15 13 byte

@~.:?z:#da;?&

Provalo online!

Spiegazione

@~.                Output is a shuffle of the input
  .:?z             Zip the output with the input
      :#da         All couples of integers of the zip must be different
          ;      Or
           ?&      Call recursively this predicate with the same input

3

Perl 6 , 45 byte

{(@^a,{[.pick(*)]}...{none @a Zeqv@$_})[*-1]}
{(@^a,{[.pick(*)]}...{!sum @a Zeqv@$_})[*-1]}

Provalo

L'input è una matrice di qualsiasi cosa.

Allargato:

{
  (

    @^a,          # declare parameter, and seed sequence generator

    {             # lambda with implicit parameter 「$_」
      [           # store into an array
        .pick(*)  # shuffle 「$_」
      ]
    }

    ...           # keep generating the sequence until

    {
      none        # none
      @a          # of the outer blocks input
      Z[eqv]      # is zip equivalent
      @$_         # with the current value being tested
    }

  )[ * - 1 ]      # return the last value
}

3

MATL, 7 byte

Questa è una traduzione del mio post di Octave (e simile ad alcune delle altre osservazioni qui). Ieri ho pubblicato il mio primo post MATL (crack CNR), quindi credo che questo non sia ottimale, ma è il migliore che abbia finora.

Ad essere sincero, non sono del tutto sicuro che ci tsia bisogno, ma è l'unico modo per farlo funzionare. È usato in modo da poter confrontare l'input dell'utente (recuperato con G), con la permutazione casuale. Penserei di poter confrontare i due senza di essa, ma ...?

Ad ogni modo, ecco qui:

`Z@tG=a

`          % Loop
 Z@        % Random permutation of input
   t       % Duplicating the stack
    G      % Paste from clipboard G (user input)
     =     % Comparing the random permutation with the input (retrieved from clipboard)
      a    % any(input == random permutation)
           % Implicit end and display

Provalo online!


Qualche miglioramento? Ne ho davvero bisogno to posso liberarmene? È stato divertente provare a giocare a golf in MATL ... :)
Stewie Griffin il

:-) Non vedo come liberarmene t(o equivalentemente un altro G) Devi lasciare qualcosa in pila per la prossima iterazione o come risultato finale
Luis Mendo,

3

In realtà , 13 byte

;;WX╚│♀=ΣWX)X

Provalo online!

Spiegazione:

;;WX╚│♀=ΣWX)X
;;             make two copies of input
  WX╚│♀=ΣW     while top of stack is truthy:
   X             discard top of stack
    ╚            shuffle array
     │           duplicate entire stack
      ♀=         compare corresponding elements in shuffled and original for equality
        Σ        sum (truthy if any elements are in the same position, else falsey)
          X)X  discard everything but the derangement

2

Ottava, 56 55 byte

x=input('');while any(x==(y=x(randperm(nnz(x)))));end,y

Dobbiamo usare input('') poiché questa non è una funzione. Inoltre, dato che posso scegliere di avere l'input come stringa, possiamo usare il trucco nnz(x)==numel(x).

Spiegazione:

x=input('')            % Self-explanatory
while any(x==y)        % Loop until x==y has only 0s (i.e. no elements are equal)
y=x(randperm(nnz(x)))  % Continue to shuffle the indices and assign x(indices) to y
end                    % End loop
y                      % Display y

Grazie a Luis per aver notato che l'input può essere una stringa, quindi ho potuto usare nnzinvece di numelsalvare due byte.


Nota per sé: leggi l'intera domanda la prossima volta :) Grazie!
Stewie Griffin,

1
Mi succede sempre :-)
Luis Mendo il

2

MATL, 13 byte

Questo è uno sforzo congiunto di @LuisMendo e me. Contrariamente a molte altre risposte qui, questa è deterministica, nel senso che non campiona permutazioni casuali fino a quando non ottiene uno squilibrio, ma genera tutti gli squilibri e ne sceglie uno a caso.

Y@tG-!Af1ZrY)

Provalo online!

Spiegazione

Y@tG-!Af1ZrY)
Y@             generate all permutatoins
  t            create a duplicate
   G-!A        find the (logical) indices of all valid derangements (where no character of the string is in the same position as the original string)
       f       convert logical to linear indices
        1Zr    choose one of those indices randomly
           Y)  get the derangement (from the ones we generated earlier) at this index

2

Pyth - 10 9 byte

Questo continua a mescolare l'input mentre uno qualsiasi dei caratteri è uguale ai caratteri nel loro indice nell'input.

.WsqVHQ.S

Provalo online qui .

.W           Iterate while
 s           Sum, this is works as any() on a boolean list
  qV         Vectorized equality
   H         The lambda variable for the check step
   Q         The input
 .S          Shuffle
  (Z)        Lambda variable, implicit
 (Q)         Start .W with input, implicit

Potete per favore aggiungere una spiegazione. Volevo scrivere una risposta Pyth. Non ne so molto.
Gurupad Mamadapur,

@GurupadMamadapur certo, sarebbe anche felice.
Maltysen,

1
@GurupadMamadapur aggiunto. Abbiamo un tutorial . È piuttosto obsoleto, ma ti insegnerà le basi. Se hai bisogno di aiuto con qualsiasi cosa relativa a Pyth, sentiti libero di chiamarmi in chat.
Maltysen,

2

Mathematica, 57 byte

#/.x_:>RandomChoice@Select[Permutations@x,FreeQ[#-x,0]&]&

Funzione senza nome che prende un elenco di whatevers come input e produce un elenco. Dopo aver generato tutte le permutazioni #dell'input x, conserviamo solo quelle per le quali l'insieme #-xdelle differenze sagge agli elementi non contiene un 0; quindi facciamo una scelta (uniformemente) casuale da quell'insieme.


1
simpatico! Leggermente più lungo, #/.x_:>NestWhile[RandomSample[#,Length@#]&,#,Not@FreeQ[#-x,0]&]&ovviamente, più veloce in pratica per le corde lunghe
martin

Aspetta, mi stai dicendo che in Mathematica non è integrato per gli squilibri? : o
shooqie,

Me lo aspettavo per metà un built-in :) :)
Greg Martin,

0

PHP, 85 byte

for($a=$b=str_split($argv[1]);array_diff_assoc($a,$b)!=$a;)shuffle($b);echo join($b);

Copia l'argomento stringa in due matrici, mescola una di esse fino a quando la differenza tra loro (confrontando anche gli indici degli elementi) è uguale all'altra. Corri con -r.


0

R, 59 byte

z=x=1:length(y<-scan(,""));while(any(x==z))z=sample(x);y[z]

Legge un elenco di elementi su STDIN, prende la lunghezza dell'elenco e avvia intervalli di campionamento da 1 alla lunghezza, fino a quando non trova uno che non condivide alcun posto con l'elenco ordinato. Quindi stampa l'elenco.


0

Meraviglia , 32 byte

f\@[/>#I zip#=[#0a\shuf#0]?f a?a

Uso:

f\@[/>#I zip#=[#0a\shuf#0]?f a?a];f[1 2 3 4 5]

Spiegazione

Più leggibile:

f\@[
  some #I zip #= [#0; a\ shuf #0]
    ? f a
    ? a
]

Funzione ricorsiva f. Esegue un confronto in termini di elementi tra fl'elenco di input e una versione casuale dell'elenco di input. Se il confronto produce valori uguali, fviene chiamato nell'elenco mischiato. Altrimenti, restituiamo semplicemente l'elenco mischiato.


0

Rubino, 67 byte

def f a
while (a.zip(o=a.shuffle).map{|x,y|x-y}.index 0);end
o
end

0

Ottava, 54 53 byte

@(a)((p=perms(a))(L=!any(p==a,2),:))(randi(sum(L)),:)

Genera tutte le permutazioni ae seleziona a caso una riga che non ha un elemento comune cona .

nota: è accidentalmente lo stesso della risposta MATL di @flawr!


0

Clojure, 94 90 79 byte

#(let[s(shuffle %)](if(not(some(fn[[x y]](= x y))(map vector % s)))s(recur %)))

-4 byte modificando il condizionale all'interno della riduzione in un ande inline done?.

-11 byte convertendo la riduzione in some.

WOOT! Batti PHP.

Metodo della forza bruta. Mescola l'elenco mentre non è valido. Questo finisce stupidamente veloce considerando che è un metodo di forza bruta che non fa nulla per impedire tentativi duplicati. Ha trovato 1000 elementi di una lunga lista di 1000 elementi in meno di un secondo.

Ungolfed:

(defn dearang [ls]
  (let [s (shuffle ls)
        bad? (some (fn [[x y]] (= x y))
                (map vector ls s))]
    (if (not bad?) s (recur ls))))

0

Clojure, 56 byte

#(let[s(shuffle %)](if((set(map = % s))true)(recur %)s))

Si noti che una stringa non può essere mescolata, deve essere passata attraverso seqo vec.

Inizialmente ho provato, #(first(remove(fn[s]((set(map = % s))true))(iterate shuffle %)))ma l' recurapproccio è davvero più breve di iterate.

La magia è che (set(map = % s))restituisce un insieme di falso, un insieme di vero o un insieme di vero e falso. Questo può essere usato come una funzione, se contiene trueallora la risposta è true, altrimenti falsa nil. =è felice di prendere due argomenti di input, non c'è bisogno di avvolgerlo con qualcosa.

((set [false]) true)
nil

Forse c'è un modo ancora più breve per verificare se qualcuno dei valori è vero?


0

APL, 11 byte.

Con la stringa nell'argomento giusto:

⍵[⍋(⍴⍵)?⍴⍵]

Spiegazione

ρ⍵ ottiene la lunghezza (o la forma) dell'argomento giusto.

?restituisce una matrice casuale (⍴⍵)di questi numeri.

restituisce l'ordine di questi al fine di garantire che non vi siano duplicati.

⍵[..] rappresenta l'assortimento casuale della stringa usando questo indice.


Benvenuti in PPCG! Richiediamo che tutte le voci siano funzioni valide o programmi completi, quindi la tua risposta deve accettare input tramite un argomento di funzione o un metodo di input.
ETHproductions

Penso che dovrebbe soddisfare i requisiti ora. Prende l'argomento giusto, o .
Jacob Utley,
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.