Aucune combinaison possible ? Ça paraît dingue
Salut !
Contexte du problème :
Dans ma famille, à Noël, nous (13 personnes) faisons chacun des listes de cadeaux qui nous feraient plaisir, puis nous échangeons nos listes au hasard. Chacun a donc la liste de quelqu'un d'autre (hormis son conjoint).
Pour cette année, j'ai décidé que l'on changerait un peu le système. En effet, plutôt que de tirer la liste complète de quelqu'un, chacun obtiendrait une liste avec des cadeaux venant de listes différentes. Jusque là, tout va bien.
J'ai donc conçu un programme qui se charge de cela. Mais voilà, mon programme ne trouve aucune combinaison possible... Je l'ai laissé tourner pendant des heures, il a effectué plus de 116 millions de tirages sans en trouver un seul qui satisfasse aux conditions requises. Ca paraît incroyable...
Donc, entre autres conditions, il faut que les listes que l'on tire fassent entre 22 et 28€. Et de même, le montant des cadeaux que l'on reçoit doit également faire entre 22 et 28€. Et c'est avec cette dernière condition que ça coince ! Comment est-ce possible qu'il n'y parvienne pas ? J'ai vérifié l'algorithme je ne sais pas combien de fois et tout semble correct...
Ce que je voudrais savoir, c'est si, mathématiquement parlant, c'est un problème impossible à résoudre ?
Merci pour vos lumières !
Aucune combinaison possible ?
Bonjour :D
Il manque des données dans ton énoncé:
Citation:
Dans ma famille, à Noël, nous (13 personnes) ... Chacun a donc la liste de quelqu'un d'autre (hormis son conjoint).
Combien y a-t-il de couples ? Et de personnes seules ?
Citation:
... chacun obtiendrait une liste avec des cadeaux venant de listes différentes ...
Combien de cadeaux
a) figurent-ils sur une liste ?
b) chaque personne offre-t-elle en tout, aux autres membres du groupe ?
Aucune combinaison possible ?
Je comprends vite, mais il faut bien m'expliquer :D.
Citation:
Donc ... il faut que les listes que l'on tire fassent entre 22 et 28€. Et de même, le montant des cadeaux que l'on reçoit doit également faire entre 22 et 28€
Donc:
a) le prix total des listes, comme celui des cadeaux, est compris entre 22 et 28 €;
b) le prix de chaque cadeau est obligatoirement compris entre 22/5 = 4.4 = 5 € (en arrondissant à l'entier supérieur) et 28 €;
c) un cadeau donné ne peut être offert plusieurs fois.
L'ensemble des cadeaux, comme celui des donneurs, peut être représenté par une matrice d'entiers au format byte:
Code:
1 2 3 4 5 6 7
| CONST NtotC = 70; NtotP = 13;
TYPE Tab_70 = ARRAY[1..NtotC, 0..2] OF Byte;
TYPE Tab_13 = ARRAY[1..NtotP, 0..1] OF Byte;
VAR ListeC: Tab_70;
ListeP: Tab_13; |
étant admises les conventions suivantes:
Code:
1 2
| ListeC[i, 0]: Prix du cadeau ; ListeC[i, 1]: Donateur ; ListeC[i, 2]: Bénéficiaire ;
ListeP[i, 0]: Prix total payé ; ListeC[i, 1]: Nombre de cadeaux offerts ; |
1°) Un premier tirage aléatoire (ou l'introduction d'une liste constante), accompagné de la mise à zéro des autres termes, permet l'initialisation de la première matrice:
Code:
1 2 3 4 5 6 7 8 9 10
| PROCEDURE Init_LC(VAR L_: Tab_70);
VAR i, m: Byte; Lc: Tab_70;
BEGIN
Randomize;
FOR i:= 1 TO NtotC DO BEGIN
m:= Random(24); Lc[i, 0]:= m + 5; // 5 <= Prix <= 5 +23 = 28
Lc[i, 1]:= 0; Lc[i, 2]:= 0;
END;
L_:= Lc
END; |
2°) Un second tirage simule les choix de toutes les personnes, qui sélectionnent un nouveau cadeau jusqu'à la vérifcation des conditions: ((22 <= Prix total <= 28) et (Ncad <= 5)), et en évitant de prendre un objet déjà réservé.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
PROCEDURE ChoixC(VAR L_p: Tab_13; VAR L_c: Tab_70);
VAR i, j, k, Ncad, PrixT: Byte;
BEGIN
FOR i:= 1 TO NtotP DO
FOR j:= 0 TO 1 DO L_p[i, j]:= 0; // Mise à zéro de tous les termes
FOR i:= 1 TO NtotP DO
BEGIN
Ncad:= 0; PrixT:= 0;
REPEAT
REPEAT
k:= Random[NtotC); Inc(k);
UNTIL (L_c[k, 2]=0); // Tirage d'un objet non réservé
Inc(Ncad); Inc(PrixT, L_c[k]
UNTIL ((22<=PrixT) AND (PrixT<=28)) OR (Ncad=5);
L_c[k, 2]:= i; // Réservation du cadeau par le bénéficiaire potentiel (i)
L_P[i, 1]:= PrixT; L_P[i, 2]:= Ncad // Mémorisation du prix payé et du nombre de cadeaux
END;
END; |
L'appel des deux procédures sera fait par les instructions:
Code:
1 2
| Init_LC(ListeC);
ChoixC(ListeP, ListeC); |
Il vaut mieux que je m'arrête à ce stade, des bourdes ayant pu s'accumuler en l'absence de compilation.
Reste à coder la répartition aléatoire des donneurs sur les cadeaux sélectionnés, en attribuant une valeur positive aux éléments ListeC[i, 1] de la première matrice, sous réserve des restrictions:
a) ListeC[k, 1] <> ListeC[p, 2] : pas de cadeau à soi-même, cela nuit à l'amblaince;
b) ListeC[p, 1]2 + ListeC[p, 1]2 <> 5, 25, 61, 113 et 181 : pas de cadeaux entre conjoints ((1, 2) ; (3, 4) ; (5, 6) ; (7, 8) ; (9, 10)); vérifier l'exclusivité de cette condition écrite à l'improviste.
Vous n'allez pas vous ennuyer, à Noël :D
Aucune combinaison possible ?
J'ai codé l'étalement des prix de 5 à 28 € pour éviter un coût total sur 5 tirages inférieur à 22 € (5 * 4 = 20 €).
Citation:
Ah oui, le montant d'un article va de 1€ à 28€.
Le programme doit normalement conduire à une solution conforme. Il se lit pratiquement comme du pseudo-code.
Pour n'avoir quasiment rien obtenu,
Citation:
... il a effectué plus de 116 millions de tirages sans en trouver un seul ...
tu as sûrement mis quelque part des conditions incompatibles.
Regarde celles qui concernent les prix.
Aucune combinaison possible ?
Citation:
... ce que fait ce morceau de code, c'est de créer 13 listes de cadeaux parallèlement à une liste de 13 personnes ...
Pourquoi 13 listes ? Elles n'ont aucun élément commun, du fait de l'attribution des cadeaux à un destinataire unique; il est beaucoup plus simple de consigner ce dernier dans la "liste" des cadeaux (qui sera une matrice - solution adoptée - ou une liste d'enregistrements).
Ton code doit être épouvantablement compliqué.
# PS:
Citation:
J'ai testé entre temps, avec 15 (au lieu de 22) et 35 (au lieu de 28) et le prog a trouvé un bon tirage au bout de 280000 essais
Avec un semblable rendement (1 / 280000) les conditions de sélection sont vraiment trop sévères !
Aucune combinaison possible ?
Si tu procèdes en gros à 5*13 = 65 tirages indépendants sur les 70 cadeaux disponibles, tu as toutes chances de tirer au moins 2 fois le même, sans même parler des conditions sur les coûts ... Il n'est pas étonnant, dans ces conditions, que cela ne donne rien.
La probabilité de tirer 65 cadeaux différents est
p = (70/70)*(69/70)*(68/70)*(67/70)* ... *(6/70) = (70!)/(5!*7065) = 1.197857E100/(1.2E2*1.435036E129) = 0.695602E-31 (d'après ma calculette).
Autant dire que c'est perdu d'avance ... même si ton code est par ailleurs correct.
Mon programme, qui n'a rien d'extraordinaire, fonctionne (enfin, j'espère ...:P) parce que les conditions de sélection interviennent à chaque tirage.
#
Citation:
Envoyé par
Mike888
Mais comment comprendre qu'avec par exemple une fourchette de 16/34 (au lieu de 22/28), ça fonctionne alors ? :?
Parce que le prix total pouvant descendre à 5*1 = 5 € , la probabilité d'un tirage acceptable est fortement augmentée si tu abaisses le seuil inférieur de 22 à 16 €.
Aucune combinaison possible ?
Il y a pour l'essentiel deux sortes de tirages sous condition:
a) le choix des cadeaux par les bénéficiaires, qui doit s'accompagner d'une marque de réservation afin que les objets ne soient pas demandés plusieurs fois - j'ai tenté de montrer à quelle impasse pouvait conduire une série de tirages indépendants; d'où la nécessité d'attribuer à chaque cadeau au moins deux paramètres: le prix, plus une autre grandeur permettant de savoir s'il a déjà été choisi.
b) la répartition aléatoire des cadeaux sélectionnés sur les donneurs, que je n'ai pas codée, mais dont les contraintes sont beaucoup moins sélectives (il s'agit des incompatibilités de personnes, qui ont été sommairement évoquées).
La procédure ChoixC(ListeP, ListeC) a été écrite et sommairement commentée; si la personne de rang (11) porte son choix sur le 51ème objet valant 25 €, la ligne correspondante passe de
< ListeC[51, 0] = 25 , ListeC[51, 1] = 0 , ListeC[51, 2] = 0 > à
< ListeC[51, 0] = 25 , ListeC[51, 1] = 0 , ListeC[51, 2] = 11 > ;
le 3me élément devient positif, marquant ainsi la réservation du cadeau.
Cette condition d'attribution unique se retrouve dans la même procédure:
Code:
1 2 3
| REPEAT
k:= Random[NtotC); Inc(k);
UNTIL (L_c[k, 2]=0); |
Il y a un ordre de priorité implicite que j'ai allègrement négligé: les cadeaux sont successivement réservés par les personnes de rang ( 1 > 2 > 3 > ... > 13 ) ; rien n'interdit d'employer une liste constante I1[i], pour insérer une permutation appropriée des 13 premiers entiers et définir un nouvel ordre de priorité décroissante:
Code:
CONST I1: Tab_13 = (5, 8, 11, 12, 1, 3, 4, 9, 13, 2, 6, 7, 10);
La procédure décrite deviendrait:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
PROCEDURE ChoixC(VAR L_p: Tab_13; VAR L_c: Tab_70);
CONST I1: Tab_13 = (5, 8, 11, 12, 1, 3, 4, 9, 13, 2, 6, 7, 10);
VAR i, j, k, Ncad, PrixT: Byte;
BEGIN
FOR i:= 1 TO NtotP DO
FOR j:= 0 TO 1 DO L_p[i, j]:= 0; // Mise à zéro de tous les termes
FOR i:= 1 TO NtotP DO
BEGIN
Ncad:= 0; PrixT:= 0;
REPEAT
REPEAT
k:= Random[NtotC); Inc(k);
UNTIL (L_c[k, 2]=0); // Tirage d'un objet non réservé
Inc(Ncad); Inc(PrixT, L_c[k]
UNTIL ((22<=PrixT) AND (PrixT<=28)) OR (Ncad=5);
L_c[k, 2]:= I1[i]; // Réservation du cadeau par le bénéficiaire potentiel (i)
L_P[I1[i], 1]:= PrixT; L_P[I1[i], 2]:= Ncad // Mémorisation du prix payé et du nombre de cadeaux
END;
END; |
Aucune combinaison possible ?
J'en suis sincèrement désolé, moi aussi ... Faute de temps, la rédaction du dernier message (que je viens de compléter) était en effet menée au pas de charge.
Je me doute que le déchiffrement d'un programme peut se révéler éreintant. Peux-tu au moins saisir le plan de ce qui est proposé ? Je pourrais toujours rajouter des précisions, là où cela pourrait être nécessaire.
D'autant que le programme que tu as toi-même mis au point semble fonctionner; la faiblesse rédhibitoire de son rendement vient sans doute de l'ordre défectueux dans lequel interviennent les restrictions.
Mais cela te demandera un sacré travail, parce qu'il te faudra reprendre toute la structure de l'ensemble.