Générer un dérangement aléatoire


30

Description du défi

Un "dérangement" d'une séquence est une permutation où aucun élément n'apparaît dans sa position d'origine. Par exemple, ECABDest un dérangement de ABCDE, mais CBEDAn'est pas:

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

Étant donné une séquence, générez-en un dérangement aléatoire.

Remarques

  • Vous pouvez prendre soit une chaîne en entrée soit un tableau / liste d'éléments (entiers, caractères, objets ...)

  • Au lieu de renvoyer un nouvel objet, vous pouvez modifier un objet existant en échangeant ses éléments

  • Chaque dérangement devrait avoir une probabilité égale d'être généré

  • Vous pouvez supposer qu'il y a plus d'un élément dans la séquence et qu'aucun n'apparaît plus d'une fois



3
@VoteToClose: haha, totalement éclaté
shooqie

Je ne sais pas grand-chose sur tout cela, mais est-ce lié de quelque façon au théorème du point fixe ... selon lequel les choses finiront toujours dans leur propre position ou quelque chose comme ça ...? Je parie que je me trompe mais quelqu'un s'il vous plaît corrigez-moi :)
Farhan Anam

Y a-t-il une garantie que les éléments seront uniques ou peuvent-ils contenir des doublons?
Carcigenicate

1
@Carcigenicate: c'est juste là dans la description; vous pouvez supposer qu'il n'y a pas de doublons
shooqie

Réponses:


12

CJam , 14 octets

q:X{mr_X.=:|}g

Essayez-le en ligne!

Continue à mélanger l'entrée jusqu'à ce qu'elle soit un dérangement.

Explication

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
Je souhaite que OP ait spécifié que les solutions devraient garantir qu'elles finissent toujours.
John Dvorak

4
@JanDvorak Eh bien, la probabilité que cela ne se termine pas est de 0. Mais vous avez raison, exiger un temps de fonctionnement déterministe aurait rendu le défi plus intéressant.
Martin Ender

La probabilité est-elle réellement de 0? L'opération de lecture aléatoire ne sera pas parfaite, comment cela fonctionne-t-il réellement? Je pense que c'est probablement une bonne approximation de ce que l'OP a demandé, mais je doute que les probabilités de chaque dérangement soient les mêmes (cela dépend probablement d'une certaine valeur de départ du PRNG qui est probablement utilisée par l'opération de mélange).
Personne

3
@Personne, je doute que vous puissiez obtenir des résultats parfaitement uniformes à partir d'un PRNG en utilisant n'importe quel algorithme. Cependant, en supposant que le shuffle lui-même est uniforme (ce que les documents Java garantissent avec "Toutes les permutations se produisent avec une probabilité approximativement égale."), Une solution basée sur le rejet produira également des dérangements uniformes, car chaque dérangement est une permutation, et chaque la permutation a la même probabilité.
Martin Ender

1
@Nobody Math nerd here. Une condition qui réussit ou échoue est appelée un essai de Bernoulli en statistique. Cela implique que la probabilité que k essais soient nécessaires au premier succès soit (1 - p) ^ (k - 1) * p, où p est la probabilité d'un dérangement réussi. Il est facile de voir qu'à mesure que k augmente, la probabilité d'avoir besoin de k essais devient extrêmement faible. Par conséquent, nous disons que l'algorithme s'arrête avec la probabilité 1 ("presque sûrement"), mais il n'est pas impossible qu'il n'arrête jamais.
maservant

9

Gelée , 6 octets

Ẋ=³S$¿

Essayez-le en ligne!

Explication

Ẋ    ¿    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 a enregistré un octet.


5
Vous avez donc votre chapeau Winter Bash à l'avance? :-)
Luis Mendo

2
Il est temps de dessiner une belle nouvelle image, Ẋ=³S$¿économise un octet.
Jonathan Allan

2
Huh, je n'ai jamais su ça $. Merci!
Lynn

C'est 6 caractères, mais plus de 6 octets. Ẋ = ³S $ ¿les longueurs d'octets sont: 312112. Donc 10 octets au total.
mxfh

6

Python, 85 octets

Modifie la liste qui lui est passée (autorisée par la méta et dans la question).

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

Essayez-le en ligne ici!


1
Si vous spécifiez Python 2, je pense que vous pouvez remplacer def D(l):par l=input()puis enregistrer les espaces d'indentation dans les lignes suivantes (vous avez donc un programme au lieu d'une fonction). Mais je n'ai pas baissé les voix!
mathmandan

@mathmandan bonne idée, mais il faudrait que je l'imprime à nouveau s'il s'agit d'un programme complet, qui coûte plus d'octets.
FlipTack

1
OK si vous le dites. Je suppose que la spécification semblait dire que vous n'aviez pas besoin d'imprimer ou de renvoyer le résultat - que prendre une liste [à partir de la saisie de l'utilisateur] et la mélanger serait suffisant. Mais il est raisonnable de lire «existant» comme «existant avant d'exécuter l'un de vos codes», auquel cas je suis d'accord avec vous. (Peut-être y a-t-il un consensus bien établi à ce sujet.) :)
mathmandan

5

ES6 (Javascript), 71, 69 octets

L'entrée et la sortie sont des tableaux, devraient fonctionner avec tous les types d'éléments (chaînes, nombres, etc.), à condition qu'ils puissent être comparés à "==".

Golfé

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

Tester

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" ]

Extrait interactif

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 octets

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

Un lambda qui prend en entrée une liste d'entiers ou de caractères et renvoie une nouvelle liste.

S'il doit prendre en charge des listes de valeurs arbitraires , il nedevrait être remplacé par !eqv(+2 octets).

( Essayez-le en ligne. )

Explication:

  • { }: Définit un lambda.
  • .pick(*): Génère une lecture aléatoire de la liste d'entrée.
  • .pick(*) xx *: Crée une séquence infinie paresseuse de tels mélanges.
  • (* Zne $_).all: Lambda qui zippe deux listes (son argument *et l' argument externe de lambda $_) avec l' neopérateur (égalité de chaîne négative), produisant une liste de booléens, puis crée une alljonction pour les réduire à un seul état booléen.
  • first PREDICATE, SEQUENCE: Prend le premier élément de notre séquence infinie de permutations qui remplit le test de "dérangement".

4

Brachylog , 19 18 15 13 octets

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

Essayez-le en ligne!

Explication

@~.                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 octets

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

Essayez-le

L'entrée est un tableau de n'importe quoi.

Étendu:

{
  (

    @^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 octets

Ceci est une traduction de mon post Octave (et similaire à certaines des autres soumissions ici). J'ai posté mon premier post MATL hier (crack CNR), donc je suppose que ce n'est pas optimal, mais c'est le meilleur que j'ai eu jusqu'à présent.

Pour être honnête, je ne suis pas tout à fait sûr que cela tsoit nécessaire, mais c'est la seule façon de faire en sorte que cela fonctionne. Il est utilisé pour que je puisse comparer l'entrée utilisateur (récupérée avec G), avec la permutation aléatoire. Je pense que je pourrais comparer les deux sans ça, mais ...?

Quoi qu'il en soit, voici:

`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

Essayez-le en ligne!


Des améliorations? En ai-je vraiment besoin tou puis-je m'en débarrasser? C'était amusant d'essayer de jouer au golf en MATL ... :)
Stewie Griffin

:-) Je ne vois pas comment m'en débarrasser t(ou équivalent G) Vous devez laisser quelque chose sur la pile pour la prochaine itération ou comme résultat final
Luis Mendo

3

En fait , 13 octets

;;WX╚│♀=ΣWX)X

Essayez-le en ligne!

Explication:

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

Octave, 56 55 octets

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

Nous devons utiliser input('') car ce n'est pas une fonction. De plus, comme je peux choisir d'avoir l'entrée sous forme de chaîne, nous pouvons utiliser l'astuce qui nnz(x)==numel(x).

Explication:

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

Merci à Luis d'avoir remarqué que l'entrée peut être une chaîne, donc j'ai pu utiliser nnzau lieu d' numelenregistrer deux octets.


Note à soi-même: lisez la question entière la prochaine fois :) Merci!
Stewie Griffin

1
Cela m'arrive tout le temps :-)
Luis Mendo

2

MATL, 13 octets

Il s'agit d'un effort conjoint de @LuisMendo et moi. Contrairement à de nombreuses autres réponses, celle-ci est déterministe dans le sens où elle n'échantillonne pas les permutations aléatoires jusqu'à ce qu'elle obtienne un dérangement, mais elle génère tous les dérangements et en choisit une au hasard.

Y@tG-!Af1ZrY)

Essayez-le en ligne!

Explication

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 octets

Cela continue de mélanger l'entrée tandis que l'un des caractères est égal à celui de son index dans l'entrée.

.WsqVHQ.S

Essayez-le en ligne ici .

.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

Pouvez-vous s'il vous plaît ajouter une explication. Je voulais écrire une réponse pyth. Je n'en sais pas grand-chose.
Gurupad Mamadapur

@GurupadMamadapur bien sûr, serait heureux aussi.
Maltysen

1
@GurupadMamadapur ajouté. Nous avons un tutoriel . C'est assez obsolète, mais vous apprendra les bases. Si vous avez besoin d'aide pour tout ce qui concerne le pyth, n'hésitez pas à me cingler dans le chat.
Maltysen

2

Mathematica, 57 octets

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

Fonction sans nom prenant une liste de whatevers comme entrée et sortie d'une liste. Après avoir généré toutes les permutations #de l'entrée x, nous ne gardons que celles pour lesquelles l'ensemble #-xdes différences élément par élément ne contient pas a 0; puis nous faisons un choix aléatoire (uniforme) à partir de cet ensemble.


1
agréable! Légèrement plus long #/.x_:>NestWhile[RandomSample[#,Length@#]&,#,Not@FreeQ[#-x,0]&]&évidemment plus rapide à l'entraînement pour les cordes longues
martin

Attendez, vous me dites qu'il n'y a pas de dérangements intégrés dans Mathematica? : o
shooqie

Je m'attendais à moitié à un intégré moi-même :)
Greg Martin

0

PHP, 85 octets

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

Copie l'argument chaîne dans deux tableaux, mélange l'un d'eux jusqu'à ce que la différence entre eux (comparant également les index des éléments) soit égale à l'autre. Courez avec -r.


0

R, 59 octets

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

Lit une liste d'éléments dans STDIN, prend la longueur de la liste et commence les plages d'échantillonnage de 1 à la longueur, jusqu'à ce qu'il en trouve un qui ne partage aucun emplacement avec la liste ordonnée. Imprime ensuite cette liste.


0

Wonder , 32 octets

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

Usage:

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

Explication

Plus lisible:

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

Fonction récursive f. Effectue une comparaison élément par élément entre fla liste d'entrée de et une version mélangée de la liste d'entrée. Si la comparaison donne des valeurs égales, elle fest appelée dans la liste mélangée. Sinon, nous renvoyons simplement la liste mélangée.



0

Octave, 54 53 octets

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

Générez toutes les permutations de aet sélectionnez au hasard une ligne qui n'a pas d'élément commun avec a.

note: C'est accidentellement la même chose que la réponse @flawr MATL!


0

Clojure, 94 90 79 octets

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

-4 octets en changeant le conditionnel à l'intérieur de la réduction en an and, et en insérantdone? .

-11 octets en convertissant la réduction en some .

WOOT! Battez PHP.

Méthode de la force brute. Mélange la liste lorsqu'elle n'est pas valide. Cela se termine rapidement stupide étant donné qu'il s'agit d'une méthode de force brute qui ne fait rien pour empêcher les essais en double. Il a trouvé 1000 dearangments d'une longue liste de 1000 éléments en moins d'une seconde.

Non golfé:

(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 octets

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

Notez qu'une chaîne ne peut pas être mélangée, doit être traversée seqouvec .

A l'origine j'ai essayé #(first(remove(fn[s]((set(map = % s))true))(iterate shuffle %)))mais l' recurapproche est en effet plus courte queiterate .

La magie est que (set(map = % s))renvoie soit un ensemble de faux, un ensemble de vrais ou un ensemble de vrais et faux. Cela peut être utilisé comme une fonction, s'il contient truealors la réponse est true, sinon fausse nil. =est heureux de prendre deux arguments d'entrée, pas besoin de l'envelopper avec quelque chose.

((set [false]) true)
nil

Peut-être existe-t-il un moyen encore plus court de vérifier si l'une des valeurs est vraie?


0

APL, 11 octets.

Avec la chaîne dans le bon argument:

⍵[⍋(⍴⍵)?⍴⍵]

Explication

ρ⍵ obtient la longueur (ou la forme) de l'argument de droite.

?renvoie un tableau aléatoire (⍴⍵)de ces nombres.

retourne la commande d'entre eux afin de s'assurer qu'il n'y a pas de doublons.

⍵[..] représente l'assortiment aléatoire de la chaîne utilisant cet index.


Bienvenue chez PPCG! Nous exigeons que toutes les entrées soient des fonctions valides ou des programmes complets, donc votre réponse doit prendre en compte un argument de fonction ou une méthode d'entrée.
ETHproductions du

Je pense que cela devrait répondre aux exigences maintenant. Il prend le bon argument, ou .
Jacob Utley
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.