Существует точный ответ (в виде матричного произведения, представленного в пункте 4 ниже). Существует достаточно эффективный алгоритм для его вычисления, основанный на следующих наблюдениях:
Случайное перемешивание из карт может быть сгенерировано путем случайного перемешивания карт и затем случайным образом перемежая оставшиеся карт в них.Н КN+kNk
Перетасовывая только тузов, а затем (применяя первое наблюдение) разбрасывая двойки, затем тройки и так далее, эту проблему можно рассматривать как цепочку из тринадцати шагов.
Нам нужно отслеживать больше, чем ценность карты, которую мы ищем. При этом, однако, нам не нужно учитывать положение знака относительно всех карт, а только его положение относительно карт равного или меньшего значения.
Представьте себе метку на первом тузе, а затем отметьте первых двух, найденных после него, и так далее. (Если на каком-либо этапе колода заканчивается без отображения карты, которую мы ищем, мы оставим все карты без отметки.) Пусть «место» каждой отметки (если она существует) будет числом карт равного или меньшего значения, которое были сданы, когда была сделана отметка (включая саму помеченную карточку). Места содержат всю необходимую информацию.
Место после метки является случайным числом. Для данной колоды последовательность этих мест образует стохастический процесс. Фактически это марковский процесс (с переменной матрицей перехода). Таким образом, точный ответ можно рассчитать по двенадцати умножениям матриц.ith
Используя эти идеи, эта машина получает значение (вычисление с плавающей запятой двойной точности) за секунды. Это приближение точного значения является точным для всех отображаемых цифр.1 / 9 19826005792658947850269453319689390235225425695.83258855290199651/9
1982600579265894785026945331968939023522542569339917784579447928182134345929899510000000000
Остальная часть этого поста содержит подробности, представляет рабочую реализацию (в R
) и завершается некоторыми комментариями по вопросу и эффективности решения.
Генерация случайных тасов колоды
На самом деле концептуально яснее и не сложнее математически рассматривать «колоду» (она же мультимножество ) из карт, из которых самого младшего достоинства, следующего младшего и т. Д. , (Заданный вопрос касается колоды, определяемой вектором .)N=k1+k2+⋯+kmk1 13 ( 4 , 4 , … , 4 )k213(4,4,…,4)
«Случайное перемешивание» из карт - это одна перестановка, взятая равномерно и случайным образом из перестановок из карт. Эти тасования попадают в группы эквивалентных конфигураций, потому что перестановка «тузов» между собой ничего не меняет, перестановка «двойки» между собой также ничего не меняет и так далее. Поэтому каждая группа перестановок, которые выглядят одинаково, когда масти карт игнорируются, содержитПерестановки. Эти группы, число которых определяется множителемN ! = N × ( N - 1 ) × ⋯ × 2 × 1 N k 1 k 2 k 1 ! × k 2 ! × ⋯ × k м !NN!=N×(N−1)×⋯×2×1Nk1k2k1!×k2!×⋯×km!
(Nk1,k2,…,km)=N!k1!k2!⋯km!,
называются «комбинации» колоды.
Есть еще один способ подсчета комбинаций. Первые карты могут образовывать только комбинация. Они оставляют «слоты» между ними и вокруг них, в которые могут быть помещены следующие карты. Мы могли бы указать это на диаграмме, где " " обозначает одну из карт а " " обозначает слот, который может содержать от до дополнительных карт:k1k1!/k1!=1k1+1k2∗k1_0k2
_∗_∗_⋯_∗_k1 stars
Когда дополнительные карты чередуются, шаблон звезд и новые карты карты на два подмножества. Число различных таких подмножеств: .k2k1+k2(k1+k2k1,k2)=(k1+k2)!k1!k2!
Повторяя эту процедуру с «тройки», мы обнаруживаем, что есть способы перемежать их среди первых карт. Поэтому общее количество различных способов упорядочить первые таким образом равноk3((k1+k2)+k3k1+k2,k3)=(k1+k2+k3)!(k1+k2)!k3!k1+k2k1+k2+k3
1×(k1+k2)!k1!k2!×(k1+k2+k3)!(k1+k2)!k3!=(k1+k2+k3)!k1!k2!k3!.
После завершения последних карт и продолжения умножения этих телескопических дробей мы находим, что количество полученных различных комбинаций равно общему количеству комбинаций, как было подсчитано ранее, . Поэтому мы не заметили никаких комбинаций. Это означает, что этот последовательный процесс перетасовки карт правильно фиксирует вероятности каждой комбинации, предполагая, что на каждом этапе каждый возможный особый способ разделения новых карт среди старых выбирается с одинаково равной вероятностью.kn(Nk1,k2,…,km)
Процесс места
Первоначально есть тузов и, очевидно, отмечен самый первый. На более поздних стадиях есть карт, место (если существует отмеченная карта) равно (некоторое значение от до ), и мы собираемся перемежать карты вокруг них. Мы можем визуализировать это с помощью диаграммы, какk1n=k1+k2+⋯+kj−1p1nk=kj
_∗_∗_⋯_∗_p−1 stars⊙_∗_⋯_∗_n−p stars
где " " обозначает отмеченный символ. Условно по этому значению места мы хотим найти вероятность того, что следующее место будет равно (какое-то значение от до ; по правилам игры следующее место должно идти после , откуда ). Если мы сможем найти, сколько существует способов перебросить новых карт в пробелах так, чтобы следующее место равнялось , то мы можем разделить на общее количество способов перемежать эти карты (равное , как мы видели), чтобы получить⊙pq1n+kpq≥p+1kq(n+kk)вероятность перехода, что место меняется с на . (Также будет вероятность перехода к тому, что место полностью исчезнет, когда ни одна из новых карт не будет следовать за отмеченной картой, но нет необходимости вычислять это явно.)pq
Давайте обновим диаграмму, чтобы отразить эту ситуацию:
_∗_∗_⋯_∗_p−1 stars⊙∗∗⋯∗s stars | _∗_⋯_∗_n−p−s stars
Вертикальная полоса « » показывает , где происходит первое новой карты после отмеченной карты: не новые карты не могут , следовательно , появляется между и (и , следовательно , нет слота не показаны на этом интервале). Мы не знаем, сколько звезд в этом интервале, поэтому я только что назвал его (который может быть нулем). Неизвестные исчезнут, как только мы найдем связь между ним и .|⊙|ssq
Предположим, что затем мы разбрасываем новых карт вокруг звезд до а затем - независимо от этого - мы чередуем оставшиеся новые карты вокруг звезд после . Естьj⊙k−j−1|
τn,k(s,p)=((p−1)+jj)((n−p−s)+(k−j)−1k−j−1)
способы сделать это. Обратите внимание, что - это самая сложная часть анализа - что место равно потому что|p+s+j+1
- Есть "старых" карт в или до знака.p
- Есть старые карты после знака , но перед .s|
- Перед маркой есть новых карт.j
- Есть новая карта, представленная самим .|
Таким образом, дает нам информацию о переходе от места к месту . Когда мы тщательно отслеживаем эту информацию для всех возможных значений и суммируем все эти (непересекающиеся) возможности, мы получаем условную вероятность места после места ,τn,k(s,p)pq=p+s+j+1sqp
Prn,k(q|p)=(∑j(p−1+jj)(n+k−qk−j−1))/(n+kk)
где сумма начинается в и заканчивается в . (Переменная длина этой суммы предполагает, что есть вряд ли это будет замкнутая формула для него как функция от и , за исключением особых случаев.)j=max(0,q−(n+1))j=min(k−1,q−(p+1)n,k,q,p
Алгоритм
Первоначально существует вероятность что место будет а вероятность будет иметь любое другое возможное значение в . Это может быть представлено вектором .1102,3,…,k1p1=(1,0,…,0)
После разбрасывания следующих карт вектор обновляется до путем умножения его (слева) на матрицу перехода . Это повторяется до тех пор, пока не будут размещены все карты . На каждом этапе сумма записей в векторе вероятности - это вероятность того, что какая-либо карта была помечена. То, что осталось сделать значение равным - это вероятность того, что после шага не останется ни одной карты.k2p1p2(Prk1,k2(q|p),1≤p≤k1,1≤q≤k2)k1+k2+⋯+kmjpj1j, Таким образом, последовательные различия в этих значениях дают нам вероятность того, что мы не смогли найти карту типа для отметки: это распределение вероятностей значения карты, которую мы искали, когда колода заканчивается в конце игры. ,j
Реализация
Следующий R
код реализует алгоритм. Это параллельно предыдущему обсуждению. Во-первых, вычисление вероятностей перехода выполняется t.matrix
(без нормализации с делением на , что облегчает отслеживание вычислений при тестировании кода):(n+kk)
t.matrix <- function(q, p, n, k) {
j <- max(0, q-(n+1)):min(k-1, q-(p+1))
return (sum(choose(p-1+j,j) * choose(n+k-q, k-1-j))
}
Это используется transition
для обновления до . Он рассчитывает матрицу переходов и выполняет умножение. Это также заботится о вычислении начального вектора если аргумент является пустым вектором:pj−1pjp1p
#
# `p` is the place distribution: p[i] is the chance the place is `i`.
#
transition <- function(p, k) {
n <- length(p)
if (n==0) {
q <- c(1, rep(0, k-1))
} else {
#
# Construct the transition matrix.
#
t.mat <- matrix(0, nrow=n, ncol=(n+k))
#dimnames(t.mat) <- list(p=1:n, q=1:(n+k))
for (i in 1:n) {
t.mat[i, ] <- c(rep(0, i), sapply((i+1):(n+k),
function(q) t.matrix(q, i, n, k)))
}
#
# Normalize and apply the transition matrix.
#
q <- as.vector(p %*% t.mat / choose(n+k, k))
}
names(q) <- 1:(n+k)
return (q)
}
Теперь мы можем легко вычислить вероятности немаркировки на каждом этапе для любой колоды:
#
# `k` is an array giving the numbers of each card in order;
# e.g., k = rep(4, 13) for a standard deck.
#
# NB: the *complements* of the p-vectors are output.
#
game <- function(k) {
p <- numeric(0)
q <- sapply(k, function(i) 1 - sum(p <<- transition(p, i)))
names(q) <- names(k)
return (q)
}
Вот они для стандартной колоды:
k <- rep(4, 13)
names(k) <- c("A", 2:9, "T", "J", "Q", "K")
(g <- game(k))
Выход
A 2 3 4 5 6 7 8 9 T J Q K
0.00000000 0.01428571 0.09232323 0.25595013 0.46786622 0.66819134 0.81821790 0.91160622 0.96146102 0.98479430 0.99452614 0.99818922 0.99944610
Согласно правилам, если король был помечен, то мы не будем искать другие карты: это означает, что значение должно быть увеличено до . При этом различия дают распределение «числа, на котором вы будете, когда закончится колода»:0.99944611
> g[13] <- 1; diff(g)
2 3 4 5 6 7 8 9 T J Q K
0.014285714 0.078037518 0.163626897 0.211916093 0.200325120 0.150026562 0.093388313 0.049854807 0.023333275 0.009731843 0.003663077 0.001810781
(Сравните это с результатом, о котором я сообщаю в отдельном ответе, описывающем моделирование по методу Монте-Карло: они кажутся одинаковыми, вплоть до ожидаемого количества случайных изменений.)
Ожидаемое значение является немедленным:
> sum(diff(g) * 2:13)
[1] 5.832589
В общем, для этого требовалось всего около десятка строк исполняемого кода. Я проверил это с помощью ручных расчетов для малых значений (до ). Таким образом, если какое-либо несоответствие становится очевидным между кодом и предшествующим анализом проблемы, доверяйте коду (потому что анализ может иметь опечатки).k3
замечания
Отношения с другими последовательностями
Когда есть одна из каждой карты, распределение представляет собой последовательность обратных целых чисел:
> 1/diff(game(rep(1,10)))
[1] 2 3 8 30 144 840 5760 45360 403200
Значение на месте это(начиная с места ). Это последовательность A001048 в онлайн-энциклопедии целочисленных последовательностей. Соответственно, мы могли бы надеяться на закрытую формулу для колод с константой («подходящих» колод), которая обобщала бы эту последовательность, которая сама по себе имеет некоторые глубокие значения. (Например, он подсчитывает размеры наибольших классов сопряженности в группах перестановок и также связан с триномиальными коэффициентами .) (К сожалению, обратные значения в обобщении для обычно не являются целыми числами.)ii!+(i−1)!i=1kik>1
Игра как случайный процесс
Наш анализ показывает, что начальные коэффициенты векторов , , являются постоянными. Например, давайте отследим вывод, как он обрабатывает каждую группу карт:ipjj≥igame
> sapply(1:13, function(i) game(rep(4,i)))
[[1]]
[1] 0
[[2]]
[1] 0.00000000 0.01428571
[[3]]
[1] 0.00000000 0.01428571 0.09232323
[[4]]
[1] 0.00000000 0.01428571 0.09232323 0.25595013
...
[[13]]
[1] 0.00000000 0.01428571 0.09232323 0.25595013 0.46786622 0.66819134 0.81821790 0.91160622 0.96146102 0.98479430 0.99452614 0.99818922 0.99944610
Например, второе значение окончательного вектора (описывающее результаты с полной колодой из 52 карт) уже появилось после обработки второй группы (и равно ). Таким образом, если вы хотите получить информацию только о разметке через значение карты , вам нужно выполнить расчет только для колоды из карт.1/(84)=1/70jthk1+k2+⋯+kj
Поскольку вероятность не пометить карту со значением быстро приближается к при увеличении , после типов карт в четырех мастях мы почти достигли предельного значения для ожидания. Действительно, предельное значение составляет приблизительно (рассчитано для колоды из карт, в которой ошибка округления двойной точности не позволяет двигаться дальше).j1j135.8333554×32
тайминг
Глядя на алгоритм, примененный к вектору , мы видим, что его время должно быть пропорционально и - используя грубую верхнюю границу - не хуже, чем пропорционально . По синхронизации все вычисления для через и через , и анализируя только те , кто принимает относительно длительного времени ( секунды или дольше), я оценить время вычисления приблизительно , поддерживая эту оценку сверху.( к , к , ... , K ) K 2 м 3 K = 1 7 п = 10 30 1 / 2 O ( K 2 н 2.9 )m(k,k,…,k)k2m3k=17n=10301/2O(k2n2.9)
Одним из применений этих асимптотик является прогнозирование времени расчета для более крупных задач. Например, учитывая, что случай занимает около секунды, мы оценили бы, что (очень интересный) случай займет около секунды. (На самом деле это занимает секунды.)1,31 к = 1 , п = 100 1,31 ( 1 / 4 ) 2 ( 100 / 30 ) 2,9 ≈ 2,7 2,87k=4,n=301.31k=1,n=1001.31(1/4)2(100/30)2.9≈2.72.87