LINUX.ORG.RU
решено ФорумTalks

3 сундука по 2 монеты

 , ,


0

2

По мотивам 3 сундука по 2 монеты написал вот ЕТО: http://paste.omsklug.com/3583/

Получил вот ето:

G: 49996682     S: 50003318
Rate: 0.499967

Извините, если уже было, тот тред почти не читал. Также не допер, в дев или сайенс, так что сюда.

UPD: Поправил, для большей привлекательности

★★★

Последнее исправление: BruteForce (всего исправлений: 2)

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

Sadler ★★★
()
Последнее исправление: Sadler (всего исправлений: 1)

Что же эти стандартизаторы с языком сделали. Я не в теме, наверное, сейчас именно так и принято писать на плюсах?

Tweaker ★★★★☆
()
Ответ на: комментарий от Tweaker

Что же эти стандартизаторы с языком сделали. Я не в теме, наверное, сейчас именно так и принято писать на плюсах?

Поэтому в мотивах я постил модели на PHP.

h578b1bde ★☆
()
Ответ на: комментарий от Tweaker

Нет, я не зню как принято, с крестами сильно не знаком.

BruteForce ★★★
() автор топика
        for (auto i = count; i > 0; --i) {

                auto c = cdistribution(generator);

                if(c == 2) {

                        i++; continue;

                }

                auto m = distribution(generator);

                if ((chests[c][m] == d(Metal::Gold)) == chests[c][!m])

                        gold_counter++;

        }


То есть ты пропускаешь только если на первом шаге выбран 3-й сундук? А если на первом шаге из второго будет выбрано серебро?

Вот мое: http://pastebin.com/UK98ZGK1

Сам алгоритм:

TCounter answer[2]={0,0}; // Ответ: количество вытащенных монет каждого типа

const TCoin c_gold=0; // Золотая монета
const TCoin c_silver=1; // Серебряная монета

// Сундуки и монеты в них
const TCoin chest_coin[]={c_gold,c_gold , c_gold,c_silver, c_silver,c_silver};

// Единичный тест
TCoin test()
{
	uint chest_coin_choice; // Сундук и монета

	chest_coin_choice=rand()%6; // Выбирам сундук и монету
	if (chest_coin[chest_coin_choice] != c_gold ) // Если монета не золотая, прерываем тест
		throw EFirstNonGold();
	
	if (chest_coin_choice%2 == 1) // Если из сундука была выбрана вторая монета...
		chest_coin_choice--; // ... то следущей будет первая из того же сундука
	else
		chest_coin_choice++; // ... иначе следующей будет вторая из того же сундука
	
	return chest_coin[chest_coin_choice]; // Возвращаем следующую вытащенную монету 
}

Результат:
Вытащено золотых монет: 3432
Вытащено серебряных монет: 1671

P. S. Спасибо: приятно посмотреть на С++ код использующий С++ на полную :)

Kroz ★★★★★
()
Ответ на: комментарий от Tweaker

Что же эти стандартизаторы с языком сделали. Я не в теме, наверное, сейчас именно так и принято писать на плюсах?

Ну, товарищ немного намутил с типами (непонятно зачем было делать array<int_fast8_t, 2> а потом Chest{d(Metal::Gold), d(Metal::Gold)}) да и массивы я бы делал статическими. А в остальном - всё правильно. А что не так?

Kroz ★★★★★
()
Ответ на: комментарий от Kroz

То есть ты пропускаешь только если на первом шаге выбран 3-й сундук?

Читаем условие:

вслепую вытаскиваем от туда монетку. Она оказывается золотой.

Значит в противном случае нам ничего не надо делать, мы не рассматриваем такие случаи. Поэтому пропускаем ход и возвращаем каунтер на место.

А если на первом шаге из второго будет выбрано серебро?

По условию вытаскивание золотой монеты — уже свершившееся. Мы не можем этого изменить и принимаем как факт. МОжно ыбло даже не писать код для третьего сундука (более того, его там и не было изначально).

приятно посмотреть на С++ код

Многие с тобой не согласятся, cast Stahl

Сам алгоритм:

	if (chest_coin_choice%2 == 1) // Если из сундука была выбрана вторая монета...
		chest_coin_choice--; // ... то следущей будет первая из того же сундука
	else
		chest_coin_choice++; // ... иначе следующей будет вторая из того же сундука
	

Можно заменить на

		chest_coin_choice++; // ... иначе следующей будет вторая из 
	
По поводу результата работы программы — ничиего не могу сказать, я не очень разбираюсь и найти ошибку не могу. Попробуй переписать как в условии. Ну, как вариант, найди ошибку у меня.

П. С. Кидать исключения на каждый чих — не комильфо, ето тут уже обсуждали.

BruteForce ★★★
() автор топика
Ответ на: комментарий от SystemD-hater

Ты уж определись

Копипастил откуда-то, в глаза не бросилось.

BruteForce ★★★
() автор топика
Ответ на: комментарий от Kroz

Вот бывает синтаксический сахар, а то что в этих исходниках - это синтаксическое говно.

Но выглядит впечатляюще, конечно.

Tweaker ★★★★☆
()
Последнее исправление: Tweaker (всего исправлений: 1)
Ответ на: комментарий от Kroz

array<int_fast8_t, 2>

Мой незамученый опытом мозг полагает, что это ускорит что-то, мол операции с bool медленнее, чем с int64_t. Вносите царя.

BruteForce ★★★
() автор топика
Ответ на: комментарий от Tweaker

синтаксическое говно.

Да, есть такое. Оправдаюсь тем, что книжках все время пишут, что надо пользовать наиболее современные штуки из языка, старые — плохо.

Предлагаю вам переписать код.

BruteForce ★★★
() автор топика
Ответ на: комментарий от BruteForce

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

Tweaker ★★★★☆
()
Ответ на: комментарий от Tweaker

наворачивают и наворачивают

Да, это правда бесит. Есть 100500 вариантов написать одно и тоже, все берут и пользуются этим, а затем не понимают кто и что написал и как оно работает. Либо пусть выпиливают обратную совместимость, есди считат, что «так нельзя писать на крестах», либо пусть закапывают(

BruteForce ★★★
() автор топика
Ответ на: комментарий от SystemD-hater

Что такое «полная» вероятность в контексте той задачи?

Это вероятность выпадения двух золотых безотносительно вытащенной первой. Выше даже привели два варианта сырцов, под обе трактовки.

Sadler ★★★
()
Ответ на: комментарий от Sadler

Это вероятность выпадения двух золотых безотносительно вытащенной первой. Выше даже привели два варианта сырцов, под обе трактовки.

Безусловная, очевидно, равна 1/3. Это я к тому, что не один из сырцов не реализует полную трактовку.

SystemD-hater
()
Ответ на: комментарий от BruteForce

Ну, как вариант, найди ошибку у меня.
> А если на первом шаге из второго будет выбрано серебро?
По условию вытаскивание золотой монеты — уже свершившееся.

Хмм. По-моему мы говорим о разных вероятностях.
Я рассчитывал полную вероятность всего эксперимента, из двух шагов. Ты рассчитываешь вероятность только на втором шаге. Тут и разница.


приятно посмотреть на С++ код

Многие с тобой не согласятся, cast Stahl

Я говорил про использование возможностей C++, а не про оформление. ИМХО оформление у тебя нормальное, хоть можно было и лучше.

Сам алгоритм:
if (chest_coin_choice%2 == 1) // Если из сундука была выбрана вторая монета...
chest_coin_choice--; // ... то следущей будет первая из того же сундука
else
chest_coin_choice++; // ... иначе следующей будет вторая из того же сундука

Можно заменить на
chest_coin_choice++; // ... иначе следующей будет вторая из

Нет, нельзя. Если chest_coin_choice=1 aka вторая монета из первого сундука, то chest_coin_choice++ даст первую монету из второго сундука, а нам нужна первая монета из того же первого сундука.

Kroz ★★★★★
()
Ответ на: комментарий от BruteForce

> array<int_fast8_t, 2>
Мой незамученый опытом мозг полагает, что это ускорит что-то, мол операции с bool медленнее, чем с int64_t.

1) Сначала заставь работать, потом оптимизируй.
2) В данной задаче оптимизация не нужна.
3) Если есть отдельный int_fast8_t вместе с int8_t, но наверняка есть и минусы такого подхода. Иначе почему бы не делать такую оптимизацию на уровне компилятора автоматически.

Kroz ★★★★★
()
Ответ на: комментарий от BruteForce

По кому?

По Байесу. Вот так: есть 3 сундука, назовём их ЗЗ, ЗС, СС и так же обзовём события выбора соответствующего сундука. И есть событие «вытащена золотая монета», назовём его З.

Вероятности выбора сундуков P(XX) = 1/3 для всех сундуков. Условные вероятности наугад вынуть золотую монету из соотв. сундука: P(З | ЗЗ) = 1, P(З | ЗС) = 1/2, P(З | CC) = 0.

Теперь. Известно, что была вытащена золотая монета. Вопрос о том, какова вероятность, что вторая монета в сундуке тоже золотая, можно переформулировать как условную вероятность что был выбран сундук ЗЗ: P(ЗЗ | З). По Байесу получается 2/3.

Вроде как мой код её и описывает, результат 1/2.

Раз не 2/3, то код описывает что-то другое, а не вышеприведённое рассуждение.

Я не подробно не смотрел, но обратил внимание на это:

Значит в противном случае нам ничего не надо делать, мы не рассматриваем такие случаи. Поэтому пропускаем ход и возвращаем каунтер на место.

if(c == 2) {
    i++; continue;
}

У меня подозрение, что здесь меняется распределение вероятности между сундуками. Генератор выбирает сундук с вероятностью 1/3, а ты выкидываешь один из вариантов выбора, что эффективно соответствует выбору двух сундуков: ЗЗ и ЗС с вероятностями 1/2.

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

После чего нужно выбрать сундук и, НЕ ПРОВЕРЯЯ номер сундука, выбрать монету. Если она золотая, инкрементируется счётчик G. После чего проверяется номер сундука и, если это сундук с двумя золотыми, то инкрементируется GG. Обрати внимание, что проверять номер сундука нужно ТОЛЬКО ЕСЛИ была выбрана золотая монета. Тогда это будет удовлетворять условию задачи.

Искомой вероятностью будет G/GG.

SystemD-hater
()

Бред. Программа ошибочно учитывает половину случаев со вторым сундуком, когда выпала серебряная монета.

German_1984 ★★
()
                if ((chests[c][m] == d(Metal::Gold)) == chests[c][!m])

Бррр. Я над этим даже думать не хочу, тут ошибка на уровне ДНК.

Miguel ★★★★★
()
Ответ на: комментарий от Kroz

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

BruteForce ★★★
() автор топика
Ответ на: комментарий от German_1984

Программа ошибочно учитывает половину случаев со вторым сундуком, когда выпала серебряная монета.

Учитывает? Где выпадает серебряная монета, назови, пожалуйста, строчку.

BruteForce ★★★
() автор топика
Ответ на: комментарий от Kroz

int_fast8_t can be anything. It's likely to be a typedef of int if the «native» size is considered to be «fast».

http://stackoverflow.com/questions/5254051/the-difference-of-int8-t-int-least...

почему бы не делать

Потому что ето с++, компилятор не знает, можно ли тебе вместо твоих 8 бит сунуть 64, если ето булет быстрее, или нет. Нао ему объяснять, мол надо только 8, но ты сунь самый быстрый тип.

UPD: А иногда нужно именно 8 бит.

BruteForce ★★★
() автор топика
Последнее исправление: BruteForce (всего исправлений: 1)
Ответ на: комментарий от Kroz

Хмм. По-моему мы говорим о разных вероятностях.

Видимо да, я разби разбирал то, что написано в условии, думал что по тому поводу весь сыр-бор.

BruteForce ★★★
() автор топика
Ответ на: комментарий от SystemD-hater

У меня подозрение, что здесь меняется распределение вероятности между сундуками. Генератор выбирает сундук с вероятностью 1/3, а ты выкидываешь один из вариантов выбора, что эффективно соответствует выбору двух сундуков: ЗЗ и ЗС с вероятностями 1/2.

Тут писал 3 сундука по 2 монеты (комментарий)

По условию вытаскивание золотой монеты — уже свершившееся. Мы не можем этого изменить и принимаем как факт. МОжно ыбло даже не писать код для третьего сундука (более того, его там и не было изначально).

BruteForce ★★★
() автор топика
Ответ на: комментарий от BruteForce

Сперва перепиши код так, чтобы он буквально соответствовал условию задачи, после этого можно будет поспорить. Если останется о чём.

SystemD-hater
()
Ответ на: комментарий от BruteForce

По условию вытаскивание золотой монеты — уже свершившееся.

Вытаскивание монеты до выбора сундука? Кул стори.

SystemD-hater
()
Ответ на: комментарий от BruteForce

кажется ближе к условию.

Но как? Когда ты выкидываешь сундук с серебряными монетами, ты как бы заглядываешь в сундук до вытаскивания монеты и не вытаскиваешь, если это сундук с двумя серебряными. Как минимум здесь явное несоответствие условию задачи.

SystemD-hater
()
Ответ на: комментарий от SystemD-hater

Да, понял, благодарю за разъяснения.

BruteForce ★★★
() автор топика
Ответ на: комментарий от SystemD-hater

У меня подозрение, что здесь меняется распределение вероятности между сундуками

Именно так. По хорошему ему нужно дописать чуть ниже

		if (c == 1 && m == 1) {
			i++; continue;
		}
и тогда всё сойдётся. Вместо этого он просто проверяет какой из двух сундуков, содержащих золото, ему попался.

kim-roader ★★
()
Ответ на: комментарий от BruteForce

Похоже на правильный ответ, и нет этих извращений.

Miguel ★★★★★
()
Ответ на: комментарий от h578b1bde

Мигель прав потому что. А все постоянные члены клуба 50/50 не удосужились даже азы теорвера подучить и лепят тупейшую отсебятину.

nezamudich ★★
()

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

nezamudich ★★
()
Ответ на: комментарий от Kroz

Сколько лапши на ровном месте... Вот почему нельзя две строчки написать? Например, так:

octave:1> choices = histc(6 * rand(10000, 1), 0 : 6);
octave:2> sum(choices(1 : 2)) / sum(choices(1 : 3))
ans =  0.66765

Пронумеруем монеты от 1 до 6 так, что первые три — золотые, оставшиеся три — серебряные. Причём 1ая и 2ая монеты — первый сундук, 3ья и 4ая — второй, 5ая и 6ая — третий.

Первым движением выделили одну монету из шести. Если золотая, то этот случай учитываем, поэтому в знаменателе sum(choices(1 : 3)). Вторая золотая будет только тогда, когда вытащили из первого сундука с двумя золотыми монетами, поэтому в числителе sum(choices(1 : 2)).

nezamudich ★★
()
Ответ на: комментарий от templarrr

Вот правильно говоришь. Задача сформулирована так же, как и все остальные комбинаторые задачи по теорверу. Ясным, чётким и недвусмысленным языком.

Но почему-то даже некоторые нормальные люди из клуба 67/33 считают, что проблема в кривой формулировке. Подозреваю, что они так говорят, чтобы сторговаться с неадекватами и замять тему.

nezamudich ★★
()
Ответ на: комментарий от nezamudich

А все постоянные члены клуба 50/50 не удосужились даже азы теорвера подучить и лепят тупейшую отсебятину.

Это ещё полбеды, ведь все сектанты 2/3 даже не смогли прочитать условие.

h578b1bde ★☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.