Votre valeur attendue globale est celle à laquelle vous pourriez vous attendre : 3,1121.
En d'autres termes, vous devriez presque toujours obtenir votre jeu de 3 ou votre jeu de 4.
J'ai mis au point un simulateur pour vous aider. Maintenant, parce que je suis un lamer, j'ai utilisé Java. Il nécessite Java 7 car il utilise <>
notation. Si vous utilisez une version plus ancienne, soyez prévenus. Voici le simulateur, tout d'abord. N'hésitez pas à le décortiquer pour ses fonctionnalités, mais pour ce qui est du style, je sais qu'il y a un million d'améliorations à apporter. C'est un script à jeter, si jamais il y en a un. Il peut y avoir des erreurs de copier/coller et autres, mais le code est en fait assez lisible. J'ajouterai des commentaires et modifierai si nécessaire, mais je regrouperai les modifications pour retarder la wikification de la communauté.
import java.util.*;
import java.text.*;
class Tokyo {
// shortcut for iterating over the faces of a die roll
static final int[] face = {0,0,0,1,2,3};
public static void main(String...args) {
// the initial roll - there's no control over this
final Roll init = new Roll(3,3,2,2,0,0);
// strat1: reroll all non 3s
// this gets all possible results and their counts from
// using strat 1 as our guide. see rollStrat1 on the Roll class
Map<Roll,Integer> strat1roll1 = init.rollStrat1();
report(strat1roll1);
// now, for each of those rolls, we need to simulate using the same
// strategy - the addTo makes sure we give proper credit to rolls that
// come up more often
Map<Roll,Integer> strat1roll2 = new HashMap<>();
for(Roll roll : strat1roll1.keySet()) { // for each roll from roll 1
Map<Roll,Integer> curr = roll.rollStrat1(); // reroll according to the strat
addTo(strat1roll2, curr); // and store them all in the master map
}
// now count the results
report(strat1roll2);
// strat2: reroll all non doubles - comments ommited because it's the same as above
Map<Roll,Integer> strat2roll1 = init.rollStrat2();
report(strat2roll1);
Map<Roll,Integer> strat2roll2 = new HashMap<>();
for(Roll roll : strat2roll1.keySet()) {
Map<Roll,Integer> curr = roll.rollStrat2();
addTo(strat2roll2, curr);
}
report(strat2roll2);
// strat3: mix the two
Map<Roll,Integer> strat3roll2 = new HashMap<>();
for(Roll roll : strat2roll1.keySet()) {
Map<Roll,Integer> curr = roll.rollStrat3();
addTo(strat3roll2, curr);
}
report(strat3roll2);
}
static DecimalFormat df = new DecimalFormat("###.00000");
static void report(Map<Roll,Integer> map) {
int sum = 0;
int count = 0;
for(Roll roll : map.keySet()) {
sum += roll.score() * map.get(roll);
count += map.get(roll);
}
double exval = ((double)sum) / (double)count;
System.out.println("total: " + sum);
System.out.println("count: " + count);
System.out.println("exval: " + df.format(exval));
}
// just merge the slave map into the master map
static void addTo(Map<Roll,Integer> master, Map<Roll,Integer> slave) {
for(Roll roll : slave.keySet()) {
Integer count = master.get(roll);
if(count == null) count = 0;
master.put(roll, count + slave.get(roll));
}
}
// reroll anything that isn't a 0 in the mask
// if it is a non-0, that is the number that will show up in the roll
// so if you want to re-roll a 2, in your strat method, turn that 2 into a
// 0 so it gets re-rolled
static Map<Roll,Integer> roll(Roll mask) {
Map<Roll, Integer> rolls = new HashMap<>();
// iterate over every possibly die roll
for(int a = 0; a < 6; a++) {
for(int b = 0; b < 6; b++) {
for(int c = 0; c < 6; c++) {
for(int d = 0; d < 6; d++) {
for(int e = 0; e < 6; e++) {
for(int f = 0; f < 6; f++) {
int ra = mask.a == 0 ? face[a] : mask.a;
int rb = mask.b == 0 ? face[b] : mask.b;
int rc = mask.c == 0 ? face[c] : mask.c;
int rd = mask.d == 0 ? face[d] : mask.d;
int re = mask.e == 0 ? face[e] : mask.e;
int rf = mask.f == 0 ? face[f] : mask.f;
Roll roll = new Roll(ra, rb, rc, rd, re, rf);
roll = roll.sort();
if(rolls.containsKey(roll)) {
rolls.put(roll, rolls.get(roll) + 1);
} else {
rolls.put(roll, 1);
}
}}}}}} // my code-review spidy sense is very pissed at me for this
return rolls;
}
// unused, YAGNI I know... but this does illustrate all possible rolls
static Map<Roll,Integer> possibleRolls() {
return roll(new Roll(0,0,0,0,0,0));
}
// this represnts a roll, but it also represents a mask - lame, I know
static class Roll {
final int a,b,c,d,e,f; // the dice you have
Roll(int a, int b, int c, int d, int e, int f) {
this.a=a; this.b=b; this.c=c;
this.d=d; this.e=e; this.f=f;
}
// welcome to Java - assumes they are properly sorted - a bad practice that
// should be fixed if this grew beyond its current scope
public boolean equals(Object o) {
Roll ros = (Roll)o;
Roll sor = this;
return ros.a == sor.a && ros.b == sor.b && ros.c == sor.c
&& ros.d == sor.d && ros.e == sor.e && ros.f == sor.f;
}
// order doesn't matter for the result, but this is a perfect hash, that's cool
public int hashCode() {
return (a+1) * (b+1) * (c+1) * (d+1) * (e+1) * (f+1);
}
Roll sort() { // delegate sorting to Arrays =)
int[] p = {a,b,c,d,e,f};
Arrays.sort(p);
return new Roll(p[0],p[1],p[2],p[3],p[4],p[5]);
}
int[] counts() { // convenience method
int[] counts = new int[4];
counts[a]++; counts[b]++; counts[c]++;
counts[d]++; counts[e]++; counts[f]++;
return counts;
}
int score() {
int[] counts = counts();
// trust the math =), or don't and work it out for yourself =)
return (counts[1] > 2 ? counts[1] - 2 : 0)
+ (counts[2] > 2 ? counts[2] - 1 : 0)
+ (counts[3] > 2 ? counts[3] : 0);
}
Map<Roll,Integer> rollStrat1() {
return keepAll(3);
}
Map<Roll,Integer> keepAll(int k) {
// reroll all non ks
int ra = a == k ? k : 0; // the mask will have ks or 0s
int rb = b == k ? k : 0;
int rc = c == k ? k : 0;
int rd = d == k ? k : 0;
int re = e == k ? k : 0;
int rf = f == k ? k : 0;
return roll(new Roll(ra,rb,rc,rd,re,rf));
}
Map<Roll,Integer> rollStrat2() {
// reroll anything that doesn't have 2x of something, except 0 - of course reroll 0s
int[] counts = counts();
int ra = counts[a] > 1 && a > 0 ? a : 0;
int rb = counts[b] > 1 && b > 0 ? b : 0;
int rc = counts[c] > 1 && c > 0 ? c : 0;
int rd = counts[d] > 1 && d > 0 ? d : 0;
int re = counts[e] > 1 && e > 0 ? e : 0;
int rf = counts[f] > 1 && f > 0 ? f : 0;
return roll(new Roll(ra,rb,rc,rd,re,rf));
}
Map<Roll,Integer> rollStrat3() {
int[] counts = counts();
if(counts[3] > 2 && counts[2] > 2) {
Map<Roll,Integer> map = new HashMap<>();
map.put(this,score());
return map;
}
if(counts[3] > 2) {
return keepAll(3);
}
if(counts[2] > 2) {
return keepAll(2);
}
return rollStrat1();
}
}
}
Ce que sont les résultats lorsqu'il est exécuté est (ces valeurs ont changé - voir l'historique des modifications).
c:\files\j>java Tokyo
total: 81756
count: 46656
exval: 1.75231
total: 5081940
count: 1632960
exval: 3.11210
total: 73872
count: 46656
exval: 1.58333
total: 1283040
count: 466560
exval: 2.75000
total: 1165885
count: 419909
exval: 2.77652
Qu'est-ce que cela nous dit ? Eh bien, tout d'abord, il valide le système en donnant des valeurs presque identiques à celles calculées par d'autres méthodes pour le premier lancer. C'est une excellente nouvelle.
Maintenant, regardons les résultats réels. Le nombre de valeurs différentes explose pour la stratégie 1, principalement parce qu'elle relance 4 dés différents lors du premier passage, et probablement une moyenne de 3,5 environ pour le second passage. Le nombre semble beaucoup plus élevé à cause de l'unicité, mais j'ai ajusté ce "problème" dans le code.
La deuxième stratégie part de moins loin et peut être améliorée. Par exemple, si vous n'obtenez pas vos 2 la deuxième fois, ne serait-il pas préférable de jeter tous les 2 et d'aller chercher des 3 ? C'est là que j'applique la troisième stratégie.
Plutôt que de commencer avec les résultats de la strate 1, qui se concentrent uniquement sur les 3, j'utilise plutôt le premier jet de la strate 2 pour me concentrer sur l'acquisition de doubles. Ensuite, je change d'objectif : si j'ai les deux séries, haha, on a fini ici... merci... Si j'ai un jeu de 3 ou un jeu de 2, je le garde et je laisse tomber l'autre jeu : après tout, c'est idiot d'essayer d'avoir 1/6 de chance de ramasser l'autre jeu - j'ai beaucoup plus de chances de laisser tomber ces dés et de les mettre dans quelque chose qui porte déjà ses fruits. Enfin, si je n'ai pas de jeu, je lance par défaut tous les dés qui ne sont pas des 3, ce qui correspond à la "stratégie 1" originale et dont il est prouvé qu'elle donne un meilleur résultat que la stratégie 2. Et cela donne un excellent résultat, mais pas encore meilleur.
Notez les 5 rapports :
strat 1 roll 1
strat 1 roll 2
strat 2 roll 1
strat 2 roll 2
strat 3 roll 2 (its roll 1 is strat 2's roll 1)
Le résultat final est donc que dans ce scénario, jusqu'à présent, les stratégies indiquent que vous devriez simplement garder vos 3 et aller de l'avant.