30 votes

Secret Santa - Générer des permutations "valides

Mes amis m'ont invitée à la maison pour jouer au jeu du Père Noël secret, où nous sommes censés dessiner un lot et jouer le rôle du "Père Noël" pour un ami du groupe.

Nous écrivons donc tous nos noms et choisissons un nom au hasard. Si l'un d'entre nous se retrouve avec son propre nom, nous procédons à un remaniement et choisissons à nouveau des noms (le raisonnement étant que l'on ne peut pas être son propre Père Noël).

Comme nous sommes sept à jouer, j'ai considéré la "répartition du Père Noël" finale comme une permutation de (1:7) sur elle-même, avec quelques restrictions.

J'aimerais solliciter diverses idées sur la manière dont nous pourrions utiliser Mathematica en particulier ou tout autre langage de programmation ou même un algorithme :

  • Liste/impression de TOUTES les allocations "valides" du Père Noël
  • Est modulable en fonction du nombre d'amis qui jouent à "Secret Santa".

2 votes

Pardonnez mon ignorance, mais ne s'agit-il pas d'une résolution à 7 ! ? C'est-à-dire le nombre de possibilités. Pas le contenu exact de ces possibilités.

3 votes

@Sheriff Non, ce n'est pas le cas. Il demande les permutations qui ne laissent aucun élément en place. Pour trois éléments, (123) (132) (321) (213) sont rejetés, (231) et (312) sont corrects.

1 votes

@Sheriff, oui, tout à fait. n ! sera le nombre total de permutations, mais certaines d'entre elles seront "non valides" et devront être prises en compte. La règle simple est que si la personne "i" choisit "i", cette "permutation" n'est pas valable. Si 1,2,3,...n sont des personnes et que P(1), P(2)...P(n) sont les emplacements qu'elles choisissent, alors pour chaque 1<=i<=n, i ne doit pas être égal à P(i). Je sais qu'il s'agit d'une condition assez simple, mais je suis curieux d'apprendre les différents "idiomes" qui peuvent être "programmés", disons en Mathematica... et de voir si nous pouvons trouver une simplification/un modèle intéressant...

29voto

Jason S Points 58434

Ce que vous recherchez est appelé dérèglement (un autre joli mot latin à connaître, comme exsanguination et défenestration).

La fraction de toutes les permutations qui sont des dérangements est proche de 1/e = environ 36,8 % -- donc si vous générez des permutations aléatoires, continuez à les générer, et il y a une très forte probabilité que vous en trouviez une dans les 5 ou 10 sélections d'une permutation aléatoire. (10,1 % de chances de ne pas en trouver dans 5 permutations aléatoires, chaque 5 permutations supplémentaires réduisant les chances de ne pas trouver de dérèglement d'un autre facteur de 10).

Cette présentation est assez terre-à-terre et donne un algorithme récursif pour générer des dérogations directement, plutôt que de devoir rejeter les permutations qui ne sont pas des dérogations.

2 votes

En effet, ce fut pour moi une agréable introduction à la communauté des stack-over-flow... ! Je n'avais jamais pensé qu'il existait un terme spécial pour une idée aussi "dérangée et stupide" (comme le pensaient peut-être mes amis ?!) que j'étais bien décidé à poursuivre... Merci beaucoup pour votre aide rapide !

0 votes

@fritz Bienvenue sur StackOverflow, et n'oubliez pas d'accepter une réponse à la question (s'il y en a une qui convient !) :-)

16voto

Mr.Wizard Points 19820

Je propose ceci :

f[s_List] := Pick[#, Inner[SameQ, #, s, Nor]] & @ Permutations@s

f @ Range @ 4

{{2, 1, 4, 3}, {2, 3, 4, 1}, {2, 4, 1, 3}, {3, 1, 4, 2}, {3, 4, 1, 2},
 {3, 4, 2, 1}, {4, 1, 2, 3}, {4, 3, 1, 2}, {4, 3, 2, 1}}

C'est nettement plus rapide que la fonction de Heike.

f @ Range @ 9; //Timing
secretSanta[9]; //Timing

{0.483, Null}    {1.482, Null}

Si l'on ne tient pas compte de la transparence du code, il est possible d'accélérer encore le processus de plusieurs fois :

f2[n_Integer] := With[{s = Range@n},
    # ~Extract~ 
       SparseArray[Times@@BitXor[s, #] & /@ #]["NonzeroPositions"] & @ Permutations@s
  ]

f2[9]; //Timing

{0.162, Null}

1 votes

(1) J'ai eu l'intuition que SparseArray pouvait être utilisé pour accélérer le processus. Bon travail. (2) Pour ce que ça vaut, il (semble) y avoir une fonction intégrée qui peut donner la valeur de nombre de "dérèglements", mais pas les "dérèglements" proprement dits, automatiquement. Voir les Subfactorial fonction.

2 votes

Merci pour ces deux "perles @Mr.Wizard, j'ai moi aussi adoré votre utilisation du SparseArray - j'ai vraiment appris beaucoup de choses grâce à ce jeu ! :) Joyeuses fêtes et une nouvelle année pleine de merveilles à TOUS !

15voto

wnoise Points 6448

Une permutation qui ne fait correspondre aucun élément à lui-même est une dérèglement . Au fur et à mesure que n augmente, la fraction des dérèglements se rapproche de la constante 1/e. Il faut donc (en moyenne) e essais pour obtenir un dérèglement, si l'on choisit une permutation au hasard.

L'article de wikipedia contient des expressions permettant de calculer des valeurs explicites pour de petits n.

1 votes

Merci beaucoup pour ces informations ! Bien qu'il semble s'agir d'un "filtrage" trivial de certaines permutations à partir du total de n ! arrangements, j'ai eu l'intuition qu'il devait y avoir un certain "modèle" dans tout cela... ! :) Je vais essayer de mettre en œuvre des moyens de "dénombrer" les dérèglements dans Mathematica et d'explorer... ! Merci encore... !

0 votes

@wnoise - Vous soulignez que lorsque n augmente, "...la fraction des dérèglements se rapproche de la constante 1/e". Cela me rappelle une classe générale de problèmes d'arrêt/de recherche optimaux appelés "problèmes de secrétaire", où le même résultat 1/e apparaît. Si cela vous est familier, pouvez-vous commenter la relation entre les dérangements et le "problème de la secrétaire" ? (Je pense que ce serait une bonne question à poser formellement quelque part dans l'univers de la pile, mais probablement pas sur SO. N'hésitez pas à récolter l'idée de la question si elle en vaut la peine et si y répondre ici serait une perte de temps).

0 votes

@telefunkenvf14 : Je n'ai jamais entendu parler de "problèmes de secrétaire", je ne peux donc pas faire de commentaire.

13voto

Heike Points 16279

Dans Mathematica, vous pourriez faire quelque chose comme

secretSanta[n_] := 
  DeleteCases[Permutations[Range[n]], a_ /; Count[a - Range[n], 0] > 0]

donde n est le nombre de personnes dans la piscine. Ainsi, par exemple secretSanta[4] retours

{{2, 1, 4, 3}, {2, 3, 4, 1}, {2, 4, 1, 3}, {3, 1, 4, 2}, {3, 4, 1, 2}, 
  {3, 4, 2, 1}, {4, 1, 2, 3}, {4, 3, 1, 2}, {4, 3, 2, 1}}

Editer

Il semble que le Combinatorica dans Mathematica possède en fait un paquetage Derangements Vous pouvez donc également faire quelque chose comme

Needs["Combinatorica`"]
Derangements[Range[n]]

bien que sur mon système Derangements[Range[n]] est environ 2 fois plus lente que la fonction ci-dessus.

1 votes

Votre fonction peut être rédigée de manière plus concise : secretSanta[n_] := Cases[Permutations@Range@n, a_ /; FreeQ[a - Range[n], 0]]

2voto

jfgagne Points 4307

Cela ne répond pas à votre question sur le comptage des dérangements valides, mais donne un algorithme pour en générer un (ce qui pourrait être ce que vous voulez) avec les propriétés suivantes :

  1. il garantit qu'il n'y a qu'un seul cycle dans la relation du Père Noël (si vous jouez à 4, vous ne vous retrouvez pas avec 2 couples de Père Noël --> 2 cycles),
  2. il fonctionne efficacement même avec un très grand nombre de joueurs,
  3. si elle est appliquée équitablement, personne ne sait qui est le Père Noël,
  4. il n'y a pas besoin d'ordinateur, seulement de papier.

Voici l'algorithme :

  • Chaque joueur écrit son nom sur une enveloppe et place son nom dans un papier plié dans l'enveloppe.
  • Un joueur de confiance (pour la propriété n° 3 ci-dessus) prend toutes les enveloppes et les mélange en regardant le verso (où aucun nom n'est écrit).
  • Une fois que les enveloppes sont suffisamment bien mélangées, il faut toujours regarder un peu plus loin.
  • A

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X