CQoKICAgIHBhY2thZ2UgbWFuYWJhc2U7CiAgICAgCiAgICBpbXBvcnQgamF2YS51dGlsLkFycmF5cy4qOwogICAgaW1wb3J0IGphdmEudXRpbC5SYW5kb207CiAgICAgCiAgICBwdWJsaWMgY2xhc3MgTWFuYUJhc2UgewogICAgIAogICAgICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpIHsKICAgICAKICAgICAgICAgICAgRGVjayBkZWNrPW5ldyBEZWNrKCk7CiAgICAgICAgICAgIGludCBOckl0ZXJhdGlvbnM9MTAwMDAwMDsKICAgICAgICAgICAgaW50IE5yR29vZExhbmRzTmVlZGVkPTI7CiAgICAgICAgICAgIGludCBUdXJuQWxsb3dlZD0yOwogICAgICAgICAgICBpbnQgTnJDYXJkcz05OTsKICAgICAgICAgICAgaW50IE5yTGFuZHM9NDA7CiAgICAgICAgICAgIGludCBDYXJkVHlwZTsKICAgICAgICAgICAgaW50IExhbmRzSW5IYW5kOwogICAgICAgICAgICBpbnQgR29vZExhbmRzSW5IYW5kOwogICAgICAgICAgICBib29sZWFuIE11bGxpZ2FuOwogICAgICAgICAgIAogICAgICAgICAgICBmb3IgKGludCBOckdvb2RMYW5kcz02OyBOckdvb2RMYW5kcyZsdDs9MjQ7IE5yR29vZExhbmRzKyspewogICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIGRvdWJsZSBDb3VudE9LPTAuMDsKICAgICAgICAgICAgICAgIGRvdWJsZSBDb3VudENvbmRpdGlvbmFsPTAuMDsKICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBmb3IgKGludCBpPTE7IGkmbHQ7PU5ySXRlcmF0aW9uczsgaSsrKXsKICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIC8vRHJhdyBvcGVuaW5nIDcKICAgICAgICAgICAgICAgICAgICBkZWNrLlNldERlY2soTnJMYW5kcywgTnJHb29kTGFuZHMsIE5yQ2FyZHMpOwogICAgICAgICAgICAgICAgICAgIExhbmRzSW5IYW5kPTA7CiAgICAgICAgICAgICAgICAgICAgR29vZExhbmRzSW5IYW5kPTA7CiAgICAgICAgICAgICAgICAgICAgZm9yIChpbnQgaj0xOyBqJmx0Oz03OyBqKyspewogICAgICAgICAgICAgICAgICAgICAgICBDYXJkVHlwZT1kZWNrLkRyYXdDYXJkKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChDYXJkVHlwZSZsdDszKSB7TGFuZHNJbkhhbmQrKzt9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChDYXJkVHlwZT09MSkge0dvb2RMYW5kc0luSGFuZCsrO30gIAogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBNdWxsaWdhbj1mYWxzZTsKICAgICAgICAgICAgICAgICAgICBpZiAoTGFuZHNJbkhhbmQmbHQ7Mikge011bGxpZ2FuPXRydWU7fQogICAgICAgICAgICAgICAgICAgIGlmIChMYW5kc0luSGFuZCZndDs1KSB7TXVsbGlnYW49dHJ1ZTt9CiAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAvL011bGxpZ2FuIHRvIDYKICAgICAgICAgICAgICAgICAgICBpZiAoTXVsbGlnYW4pewogICAgICAgICAgICAgICAgICAgICAgICBkZWNrLlNldERlY2soTnJMYW5kcywgTnJHb29kTGFuZHMsIE5yQ2FyZHMpOwogICAgICAgICAgICAgICAgICAgICAgICBMYW5kc0luSGFuZD0wOwogICAgICAgICAgICAgICAgICAgICAgICBHb29kTGFuZHNJbkhhbmQ9MDsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpbnQgaj0xOyBqJmx0Oz02OyBqKyspewogICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2FyZFR5cGU9ZGVjay5EcmF3Q2FyZCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKENhcmRUeXBlJmx0OzMpIHtMYW5kc0luSGFuZCsrO30KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChDYXJkVHlwZT09MSkge0dvb2RMYW5kc0luSGFuZCsrO30gIAogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIE11bGxpZ2FuPWZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoTGFuZHNJbkhhbmQmbHQ7Mikge011bGxpZ2FuPXRydWU7fQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoTGFuZHNJbkhhbmQmZ3Q7NCkge011bGxpZ2FuPXRydWU7fQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIC8vTXVsbGlnYW4gdG8gNQogICAgICAgICAgICAgICAgICAgIGlmIChNdWxsaWdhbil7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlY2suU2V0RGVjayhOckxhbmRzLCBOckdvb2RMYW5kcywgTnJDYXJkcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIExhbmRzSW5IYW5kPTA7CiAgICAgICAgICAgICAgICAgICAgICAgIEdvb2RMYW5kc0luSGFuZD0wOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGludCBqPTE7IGombHQ7PTU7IGorKyl7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBDYXJkVHlwZT1kZWNrLkRyYXdDYXJkKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoQ2FyZFR5cGUmbHQ7Mykge0xhbmRzSW5IYW5kKys7fQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKENhcmRUeXBlPT0xKSB7R29vZExhbmRzSW5IYW5kKys7fSAgCiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgTXVsbGlnYW49ZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChMYW5kc0luSGFuZCZsdDsxKSB7TXVsbGlnYW49dHJ1ZTt9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChMYW5kc0luSGFuZCZndDs0KSB7TXVsbGlnYW49dHJ1ZTt9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgLy9NdWxsaWdhbiB0byA0CiAgICAgICAgICAgICAgICAgICAgaWYgKE11bGxpZ2FuKXsKICAgICAgICAgICAgICAgICAgICAgICAgZGVjay5TZXREZWNrKE5yTGFuZHMsIE5yR29vZExhbmRzLCBOckNhcmRzKTsKICAgICAgICAgICAgICAgICAgICAgICAgTGFuZHNJbkhhbmQ9MDsKICAgICAgICAgICAgICAgICAgICAgICAgR29vZExhbmRzSW5IYW5kPTA7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaW50IGo9MTsgaiZsdDs9NDsgaisrKXsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIENhcmRUeXBlPWRlY2suRHJhd0NhcmQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChDYXJkVHlwZSZsdDszKSB7TGFuZHNJbkhhbmQrKzt9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoQ2FyZFR5cGU9PTEpIHtHb29kTGFuZHNJbkhhbmQrKzt9ICAKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgIC8vRHJhdyBjYXJkcyBmb3IgdGhlIG51bWJlciBvZiB0dXJucyBhdmFpbGFibGUKICAgICAgICAgICAgICAgICAgICBmb3IgKGludCB0dXJuPTE7IHR1cm4mbHQ7PVR1cm5BbGxvd2VkLTE7IHR1cm4rKyl7CiAgICAgICAgICAgICAgICAgICAgICAgIENhcmRUeXBlPWRlY2suRHJhd0NhcmQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKENhcmRUeXBlJmx0OzMpIHtMYW5kc0luSGFuZCsrO30KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKENhcmRUeXBlPT0xKSB7R29vZExhbmRzSW5IYW5kKys7fSAgCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgaWYgKEdvb2RMYW5kc0luSGFuZCZndDs9TnJHb29kTGFuZHNOZWVkZWQpIHtDb3VudE9LKys7fQogICAgICAgICAgICAgICAgICAgIGlmIChMYW5kc0luSGFuZCZndDs9TnJHb29kTGFuZHNOZWVkZWQpIHtDb3VudENvbmRpdGlvbmFsKys7fQogICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB9IC8vIGVuZCBvZiAxMDAwMDAwIGl0ZXJhdGlvbnMKICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oJnF1b3Q7V2l0aCAmcXVvdDsrTnJHb29kTGFuZHMrJnF1b3Q7IGdvb2QgbGFuZHM6IFByb2I9JnF1b3Q7K0NvdW50T0svQ291bnRDb25kaXRpb25hbCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAKICAgIH0KICAgICAKICAgIGNsYXNzIERlY2sgewogICAgICAgIGludCBOdW1iZXJPZkxhbmRzOwogICAgICAgIGludCBOdW1iZXJPZkdvb2RMYW5kczsKICAgICAgICBpbnQgTnVtYmVyT2ZDYXJkczsKICAgICAKICAgICAgICB2b2lkIFNldERlY2sgKGludCBOckxhbmRzLCBpbnQgTnJHb29kTGFuZHMsIGludCBOckNhcmRzKSB7CiAgICAgICAgICAgIE51bWJlck9mTGFuZHM9TnJMYW5kczsKICAgICAgICAgICAgTnVtYmVyT2ZHb29kTGFuZHM9TnJHb29kTGFuZHM7CiAgICAgICAgICAgIE51bWJlck9mQ2FyZHM9TnJDYXJkczsKICAgICAgICB9CiAgICAgICAKICAgICAgICBpbnQgRHJhd0NhcmQgKCl7CiAgICAgICAgICAgICAgICBSYW5kb20gZ2VuZXJhdG9yID0gbmV3IFJhbmRvbSgpOwogICAgICAgICAgICAgICAgaW50IFJhbmRvbUludGVnZXJCZXR3ZWVuT25lQW5kRGVja1NpemU9Z2VuZXJhdG9yLm5leHRJbnQoIHRoaXMuTnVtYmVyT2ZDYXJkcykrMTsKICAgICAgICAgICAgICAgIGludCBDYXJkVHlwZT0wOwogICAgICAgICAgICAgICAgaW50IEdvb2RMYW5kQ3V0b2ZmPU51bWJlck9mR29vZExhbmRzOwogICAgICAgICAgICAgICAgaW50IExhbmRDdXRvZmY9TnVtYmVyT2ZMYW5kczsKICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBpZiAoUmFuZG9tSW50ZWdlckJldHdlZW5PbmVBbmREZWNrU2l6ZSZsdDs9R29vZExhbmRDdXRvZmYpIHtDYXJkVHlwZT0xOyB0aGlzLk51bWJlck9mR29vZExhbmRzLS07IHRoaXMuTnVtYmVyT2ZMYW5kcy0tOyB0aGlzLk51bWJlck9mQ2FyZHMtLTt9CiAgICAgICAgICAgICAgICBpZiAoUmFuZG9tSW50ZWdlckJldHdlZW5PbmVBbmREZWNrU2l6ZSZndDtHb29kTGFuZEN1dG9mZiAmYW1wOyZhbXA7IFJhbmRvbUludGVnZXJCZXR3ZWVuT25lQW5kRGVja1NpemUmbHQ7PUxhbmRDdXRvZmYpIHtDYXJkVHlwZT0yOyB0aGlzLk51bWJlck9mTGFuZHMtLTsgdGhpcy5OdW1iZXJPZkNhcmRzLS07fQogICAgICAgICAgICAgICAgaWYgKFJhbmRvbUludGVnZXJCZXR3ZWVuT25lQW5kRGVja1NpemUmZ3Q7TGFuZEN1dG9mZikge0NhcmRUeXBlPTM7IHRoaXMuTnVtYmVyT2ZDYXJkcy0tO30KICAgICAgICAgICAgICAgIHJldHVybiBDYXJkVHlwZTsKICAgICAgICB9CiAgICB9Cgo=
package manabase;
import java.util.Arrays.*;
import java.util.Random;
public class ManaBase {
public static void main(String[] args) {
Deck deck=new Deck();
int NrIterations=1000000;
int NrGoodLandsNeeded=2;
int TurnAllowed=2;
int NrCards=99;
int NrLands=40;
int CardType;
int LandsInHand;
int GoodLandsInHand;
boolean Mulligan;
for (int NrGoodLands=6; NrGoodLands<=24; NrGoodLands++){
double CountOK=0.0;
double CountConditional=0.0;
for (int i=1; i<=NrIterations; i++){
//Draw opening 7
deck.SetDeck(NrLands, NrGoodLands, NrCards);
LandsInHand=0;
GoodLandsInHand=0;
for (int j=1; j<=7; j++){
CardType=deck.DrawCard();
if (CardType<3) {LandsInHand++;}
if (CardType==1) {GoodLandsInHand++;}
}
Mulligan=false;
if (LandsInHand<2) {Mulligan=true;}
if (LandsInHand>5) {Mulligan=true;}
//Mulligan to 6
if (Mulligan){
deck.SetDeck(NrLands, NrGoodLands, NrCards);
LandsInHand=0;
GoodLandsInHand=0;
for (int j=1; j<=6; j++){
CardType=deck.DrawCard();
if (CardType<3) {LandsInHand++;}
if (CardType==1) {GoodLandsInHand++;}
}
Mulligan=false;
if (LandsInHand<2) {Mulligan=true;}
if (LandsInHand>4) {Mulligan=true;}
}
//Mulligan to 5
if (Mulligan){
deck.SetDeck(NrLands, NrGoodLands, NrCards);
LandsInHand=0;
GoodLandsInHand=0;
for (int j=1; j<=5; j++){
CardType=deck.DrawCard();
if (CardType<3) {LandsInHand++;}
if (CardType==1) {GoodLandsInHand++;}
}
Mulligan=false;
if (LandsInHand<1) {Mulligan=true;}
if (LandsInHand>4) {Mulligan=true;}
}
//Mulligan to 4
if (Mulligan){
deck.SetDeck(NrLands, NrGoodLands, NrCards);
LandsInHand=0;
GoodLandsInHand=0;
for (int j=1; j<=4; j++){
CardType=deck.DrawCard();
if (CardType<3) {LandsInHand++;}
if (CardType==1) {GoodLandsInHand++;}
}
}
//Draw cards for the number of turns available
for (int turn=1; turn<=TurnAllowed-1; turn++){
CardType=deck.DrawCard();
if (CardType<3) {LandsInHand++;}
if (CardType==1) {GoodLandsInHand++;}
}
if (GoodLandsInHand>=NrGoodLandsNeeded) {CountOK++;}
if (LandsInHand>=NrGoodLandsNeeded) {CountConditional++;}
} // end of 1000000 iterations
System.out.println("With "+NrGoodLands+" good lands: Prob="+CountOK/CountConditional);
}
}
}
class Deck {
int NumberOfLands;
int NumberOfGoodLands;
int NumberOfCards;
void SetDeck (int NrLands, int NrGoodLands, int NrCards) {
NumberOfLands=NrLands;
NumberOfGoodLands=NrGoodLands;
NumberOfCards=NrCards;
}
int DrawCard (){
Random generator = new Random();
int RandomIntegerBetweenOneAndDeckSize=generator.nextInt( this.NumberOfCards)+1;
int CardType=0;
int GoodLandCutoff=NumberOfGoodLands;
int LandCutoff=NumberOfLands;
if (RandomIntegerBetweenOneAndDeckSize<=GoodLandCutoff) {CardType=1; this.NumberOfGoodLands--; this.NumberOfLands--; this.NumberOfCards--;}
if (RandomIntegerBetweenOneAndDeckSize>GoodLandCutoff && RandomIntegerBetweenOneAndDeckSize<=LandCutoff) {CardType=2; this.NumberOfLands--; this.NumberOfCards--;}
if (RandomIntegerBetweenOneAndDeckSize>LandCutoff) {CardType=3; this.NumberOfCards--;}
return CardType;
}
}