Найти в Дзене
avbukh

Лотерея, в которую выгодно играть математику.

Задача про три двери — это классическая задача теории вероятностей, известная как парадокс Монти Холла. Суть в том, что вы делаете выбор двери, ведущий открывает другую дверь с козой, и вам предлагается поменять свой выбор. Давайте разберем решение этой задачи с помощью витуальных агентов, напишем программу на языке Си++. Для начала создадим функцию, которая возвращает число от 1 до 3 равномерно и случайно: int random3 () { float x = ran(&idum); int res; if (x<(1.0/3.0)) { res=1;} else if (x<(2.0/3.0)) { res=2;} else { res=3; } return res; } Эта функция поможет как ведущему (разместить приз за одной из трех дверей), так и виртуальному игроку (выбрать дверь). В этой функции есть вызов функции ran(long *), которая определена в книге Numerical Recipes. Пусть игрок придерживается такой тактики: никогда не изменяет своего выбора, выбрал одну из дверей и очень верит, что там приз. int main () { int door1prize = 0, door2prize = 0, door3prize = 0, wincounter = 0, totalcounter = 0; for (int i =

Задача про три двери — это классическая задача теории вероятностей, известная как парадокс Монти Холла. Суть в том, что вы делаете выбор двери, ведущий открывает другую дверь с козой, и вам предлагается поменять свой выбор.

Рисунок. Лотерея, в которую выгодно играть математику.
Рисунок. Лотерея, в которую выгодно играть математику.

Давайте разберем решение этой задачи с помощью витуальных агентов, напишем программу на языке Си++.

Для начала создадим функцию, которая возвращает число от 1 до 3 равномерно и случайно:

int random3 () {
float x = ran(&idum); int res;
if (x<(1.0/3.0)) { res=1;}
else if (x<(2.0/3.0)) { res=2;}
else { res=3; }
return res;
}

Эта функция поможет как ведущему (разместить приз за одной из трех дверей), так и виртуальному игроку (выбрать дверь). В этой функции есть вызов функции ran(long *), которая определена в книге Numerical Recipes.

Пусть игрок придерживается такой тактики: никогда не изменяет своего выбора, выбрал одну из дверей и очень верит, что там приз.

int main () {
int door1prize = 0, door2prize = 0, door3prize = 0, wincounter = 0, totalcounter = 0;
for (int i = 0; i<100000; i++) {
int door_prize = random3();
if (door_prize==1) door1prize++;
if (door_prize==2) door2prize++;
if (door_prize==3) door3prize++;
totalcounter++;
int door_choosen = random3();
if (door_prize==door_choosen) wincounter++;
}
std::cout << "Из " << totalcounter << " экспериментов выигрыш получен " << wincounter << " раз, то есть в " << 100.0*wincounter/totalcounter << "% случаев\n";
return 0;
}

Здесь игра проводится 100 тыс. раз и программа выдает следующий результат:

Из 100000 экспериментов выигрыш получен 33225 раз, то есть в 33.225% случаев

Это логично, при выборе из трех вариантов шанс отгадать 1/3, то есть теоретически в 33.333% случаев.

Но давайте предположим, что наш агент-игрок является математиком и смекнул, что, когда ведущий открыл дверь без приза, то вероятность p=1/3 перераспределилась между дверьми, которые не были выбраны игроком. То есть, шанс должен увеличиться, если поменять выбор. Чтобы определить поведение ведущего, нам понадобится еще выбирать случайно из двух дверей:

int random2 () {
float x = ran(&idum); int res;
if (x<(1.0/2.0)) { res=1; }
else { res=2; }
return res;
}

Игра будет осуществляться по следующему алгоритму:

int main () {
int door1prize = 0, door2prize = 0, door3prize = 0, wincounter = 0, totalcounter = 0;
for (int i = 0; i<100000; i++) {
int door_prize = random3();
if (door_prize==1) door1prize++;
if (door_prize==2) door2prize++;
if (door_prize==3) door3prize++;
totalcounter++;
int door_choosen = random3();
int door_opened;
if (door_choosen==door_prize) {
door_opened = random2();
if (door_choosen==1) door_opened++;
if (door_choosen==2) if (door_opened==2) door_opened++;
}
else {
if ((door_choosen==1)&&(door_prize==2)) door_opened=3;
if ((door_choosen==1)&&(door_prize==3)) door_opened=2;
if ((door_choosen==2)&&(door_prize==1)) door_opened=3;
if ((door_choosen==2)&&(door_prize==3)) door_opened=1;
if ((door_choosen==3)&&(door_prize==1)) door_opened=2;
if ((door_choosen==3)&&(door_prize==2)) door_opened=1;
}
int door_choosen_new = door_choosen;
if ((door_opened==1)&&(door_choosen==2)) door_choosen_new=3;
if ((door_opened==1)&&(door_choosen==3)) door_choosen_new=2;
if ((door_opened==2)&&(door_choosen==1)) door_choosen_new=3;
if ((door_opened==2)&&(door_choosen==3)) door_choosen_new=1;
if ((door_opened==3)&&(door_choosen==1)) door_choosen_new=2;
if ((door_opened==3)&&(door_choosen==2)) door_choosen_new=1;
if (door_prize==door_choosen_new) wincounter++;
}
std::cout << "Из " << totalcounter << " экспериментов выигрыш получен " << wincounter << " раз, то есть в " << 100.0*wincounter/totalcounter << "% случаев\n";
return 0;
}

Здесь ведущий выбирает из оставшихся двух дверей ту, где нет приза, и открывает ее. А игрок всегда меняет свой выбор. В результате вывод программы получился на моем компьютере таким:

Из 100000 экспериментов выигрыш получен 66811 раз, то есть в 66.811% случаев

Видим, что шанс стал близким к теоретической вероятность 2/3.

У этой задачи есть варианты, когда дверей больше и ведущий открывает больше дверей, но суть остается одной и той же: игроку выгодно изменять решение.

Лотереи
1975 интересуются