Как рассчитать конкретный индекс комбинации карт

64
7

Есть 22100 комбинаций из 3 карт из колоды 52 карт (52 * 51 * 50/3! = 22100).

Вот список всех этих комбинаций:

    static const ins cards_count = 52;
int boardId = 0;

for (int b1 = 0; b1 < card_count; b1++)
{
for (int b2 = b1 + 1; b2 < card_count; b2++)
{
for (int b3 = b2 + 1; b3 < card_count; b3++)
{
cout << boardId << endl;
boardId++;
}
}
}

Можно ли написать указатель fucntion, который преобразует b1, b2, b3 в boardId (без использования карты)? Если это сложно, возможно, вы можете посоветовать некоторую хэш-функцию, которая отображает b1, b2, b3 в хэш-размер int.

спросил(а) 2021-01-25T17:59:34+03:00 6 месяцев назад
1
Решение
90

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

Идея состоит в том, чтобы вычислить, сколько комбинаций приходит до (или после) того, для которого вам нужен индекс.

Разумеется, 3 из 52 сочетаний, которые вы указываете, являются правильными. Теперь позвольте перечислить, сколько из них приходилось перед b1, b2, b3:

    Прежде всего, все комбинации с первой карточкой меньше, чем b1. У вас есть опции b1 для первой карты (начиная с 0), и для каждой из этих опций b1_ вас есть 52-b1_ выбрать 2 комбинации. Таким образом, это число представляет собой сумму по b1_ от 0 до b1-1 по указанному биномиальному коэффициенту. Имея небольшое количество математических знаний, вы можете получить закрытую формулу для этого, фактически не вычисляя сумму. Во-вторых, есть все комбинации с первой картой, имеющей индекс b1 а вторая карта имеет индекс ниже b2. Это снова сумма, но более простая. У вас есть один выбор для первой карты (b1) и b2-b1 (может быть отключен на единицу, проверьте, чтобы до ее реализации) варианты для второй карты. Для каждой из этих опций (сумма по b2_) у вас есть b2_ 52-b2 для третьей карты. Это сумма по последовательным числам, и получение замкнутой формулы для этого просто (подсказка: сумма первых n чисел, начиная с 1, равна n*(n+1)/2, сумма последовательных чисел не начинается при одном - разница между двумя суммами, начиная с 1). Наконец, вас интересует количество комбинаций с первыми двумя картами, которые являются b1 и b2 а третье меньше, чем b3. Это просто, так как эта сумма точно равна b3.

Единственное, что вам нужно сделать сейчас - это добавить результат от каждого элемента, и у вас есть свой индекс. Я советую вам взять лист бумаги, сделать математику, как было предложено, и перейти к простой, простой в оценке формуле, которую вы можете реализовать.

ответил(а) 2021-01-25T17:59:34+03:00 6 месяцев назад
45

Если вам интересно только назначить и получить уникальный идентификатор набора из 3 разных карт из стандартной колоды, нет необходимости вычислять количество комбинаций для разных наборов.

Пусть карты в колоде назначены с 1 по 52.

Вы можете сделать это программно, как:

int getSetId (int card1, int card2, int card3){
if (card1 == card2 || card2 == card3 || card1 == card3)
//throw an exception
return (card1 * card2 * card3);
}

Это даст вам уникальный идентификатор для всех комбинаций.

Изменить 1:

Если будет дублированный идентификатор из-за множителей, образующих один и тот же продукт, вместо использования от 1 до 52 вы можете использовать первые 52 простых числа.

ответил(а) 2021-01-25T17:59:34+03:00 6 месяцев назад
46

Я просто проигнорировал бы тот факт, что карты в наборе должны быть уникальными и отсортированными. Тогда ваш индекс просто card1 + 52 * card2 + 52 * 52 * card3. С хорошо сформированными наборами не каждый индекс доступен, а распределение искажается в сторону меньших чисел. Попробуйте hash = index % prime * 52 * 52 * 52 + index чтобы выровнять распределение. Попробуйте низкий премьер. Добавленная часть индекса гарантирует, что хэш останется уникальным.

ответил(а) 2021-01-25T17:59:34+03:00 6 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема