다음을 해결하는 데 문제가 있습니다.
에이스를 얻을 때까지 교체하지 않고 표준 52 카드 데크에서 카드를 가져옵니다. 당신은 2를 얻을 때까지 남은 것에서 뽑습니다. 계속해서 3을 계속합니다.
시키는 것이 자연 스러웠다
따라서 문제는 본질적으로 갑판이 다 떨어질 때 올 확률을 알아내는 것입니다 .
나는 그것을 볼 수 있습니다
그러나 더 이상 얻을 수 없었습니다 ...
2AAA2
다음을 해결하는 데 문제가 있습니다.
에이스를 얻을 때까지 교체하지 않고 표준 52 카드 데크에서 카드를 가져옵니다. 당신은 2를 얻을 때까지 남은 것에서 뽑습니다. 계속해서 3을 계속합니다.
시키는 것이 자연 스러웠다
따라서 문제는 본질적으로 갑판이 다 떨어질 때 올 확률을 알아내는 것입니다 .
나는 그것을 볼 수 있습니다
그러나 더 이상 얻을 수 없었습니다 ...
2AAA2
답변:
@ gung의 아이디어에 따라 예상 값이 5.84라고 생각합니까? 그리고 의견에 대한 나의 해석에서, 나는 "A"가 거의 불가능한 값이라고 가정합니다 (갑판의 마지막 4 장의 카드가 모두 에이스가 아닌 한). 다음은 몬테 카를로 시뮬레이션의 반복 결과입니다.
results
2 3 4 5 6 7 8 9 J K Q T
1406 7740 16309 21241 19998 15127 9393 4906 976 190 380 2334
여기에 R 코드가 있습니다.
# monte carlo card-drawing functions from here
# http://streaming.stat.iastate.edu/workshops/r-intro/lectures/5-Rprogramming.pdf
# create a straightforward deck of cards
create_deck <-
function( ){
suit <- c( "H" , "C" , "D" , "S" )
rank <- c( "A" , 2:9 , "T" , "J" , "Q" , "K" )
deck <- NULL
for ( r in rank ) deck <- c( deck , paste( r , suit ) )
deck
}
# construct a function to shuffle everything
shuffle <- function( deck ){ sample( deck , length( deck ) ) }
# draw one card at a time
draw_cards <-
function( deck , start , n = 1 ){
cards <- NULL
for ( i in start:( start + n - 1 ) ){
if ( i <= length( deck ) ){
cards <- c( cards , deck[ i ] )
}
}
return( cards )
}
# create an empty vector for your results
results <- NULL
# run your simulation this many times..
for ( i in seq( 100000 ) ){
# create a new deck
sdeck <- shuffle( create_deck() )
d <- sdeck[ grep('A|2' , sdeck ) ]
e <- identical( grep( "2" , d ) , 1:4 )
# loop through ranks in this order
rank <- c( "A" , 2:9 , "T" , "J" , "Q" , "K" )
# start at this position
card.position <- 0
# start with a blank current.draw
current.draw <- ""
# start with a blank current rank
this.rank <- NULL
# start with the first rank
rank.position <- 1
# keep drawing until you find the rank you wanted
while( card.position < 52 ){
# increase the position by one every time
card.position <- card.position + 1
# store the current draw for testing next time
current.draw <- draw_cards( sdeck , card.position )
# if you draw the current rank, move to the next.
if ( grepl( rank[ rank.position ] , current.draw ) ) rank.position <- rank.position + 1
# if you have gone through every rank and are still not out of cards,
# should it still be a king? this assumes yes.
if ( rank.position == length( rank ) ) break
}
# store the rank for this iteration.
this.rank <- rank[ rank.position ]
# at the end of the iteration, store the result
results <- c( results , this.rank )
}
# print the final results
table( results )
# make A, T, J, Q, K numerics
results[ results == 'A' ] <- 1
results[ results == 'T' ] <- 10
results[ results == 'J' ] <- 11
results[ results == 'Q' ] <- 12
results[ results == 'K' ] <- 13
results <- as.numeric( results )
# and here's your expected value after 100,000 simulations.
mean( results )
A
불가능합니까? AAAA
예를 들어 48 장의 카드 순서를 고려하십시오 .
1/prod( 48:1 / 52:5 )
results
시뮬레이션을 위해서는 정확 하고 빠른 것이 중요합니다 . 이 두 가지 목표는 프로그래밍 환경의 핵심 기능을 목표로하는 코드 작성과 가능한 짧고 간단한 코드 작성을 제안합니다. 단순함은 명확함과 선명함이 정확성을 높이기 때문입니다. 다음은 두 가지를 모두 달성하려는 시도입니다 R
.
#
# Simulate one play with a deck of `n` distinct cards in `k` suits.
#
sim <- function(n=13, k=4) {
deck <- sample(rep(1:n, k)) # Shuffle the deck
deck <- c(deck, 1:n) # Add sentinels to terminate the loop
k <- 0 # Count the cards searched for
for (j in 1:n) {
k <- k+1 # Count this card
deck <- deck[-(1:match(j, deck))] # Deal cards until `j` is found
if (length(deck) < n) break # Stop when sentinels are reached
}
return(k) # Return the number of cards searched
}
다음 과 같이 난수 시드를 설정 한 후 함수를 사용하여 이를 재현 가능한 방식으로 적용 할 수 있습니다 replicate
.
> set.seed(17); system.time(d <- replicate(10^5, sim(13, 4)))
user system elapsed
5.46 0.00 5.46
속도는 느리지 만 기다릴 필요없이 상당히 길고 정확한 시뮬레이션을 반복적으로 수행 할 수있을 정도로 빠릅니다. 결과를 나타낼 수있는 몇 가지 방법이 있습니다. 그 평균으로 시작합시다.
> n <- length(d)
> mean(d)
[1] 5.83488
> sd(d) / sqrt(n)
[1] 0.005978956
후자는 표준 오차입니다. 시뮬레이션 된 평균이 실제 값의 2 개 또는 3 개의 SE 내에있을 것으로 예상합니다. 이로 인해 실제 기대 값은 에서 사이5.853 입니다.
우리는 또한 주파수 (과의 표를 참조 할 수 있습니다 자신의 표준 오차를). 다음 코드는 도표를 약간 미리 보여줍니다.
u <- table(d)
u.se <- sqrt(u/n * (1-u/n)) / sqrt(n)
cards <- c("A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K")
dimnames(u) <- list(sapply(dimnames(u), function(x) cards[as.integer(x)]))
print(rbind(frequency=u/n, SE=u.se), digits=2)
출력은 다음과 같습니다.
2 3 4 5 6 7 8 9 T J Q K
frequency 0.01453 0.07795 0.1637 0.2104 0.1995 0.1509 0.09534 0.04995 0.02249 0.01009 0.00345 0.00173
SE 0.00038 0.00085 0.0012 0.0013 0.0013 0.0011 0.00093 0.00069 0.00047 0.00032 0.00019 0.00013
시뮬레이션이 올바른지 어떻게 알 수 있습니까? 한 가지 방법은 작은 문제에 대해 철저하게 테스트하는 것입니다. 이 때문에이 코드 교체, 문제의 작은 일반화를 공격하기 위해 작성되었습니다 와 별개의 카드 와 와 정장 . 그러나 테스트를 위해 코드에 데크를 미리 정해진 순서대로 공급할 수 있어야합니다. 동일한 알고리즘에 약간 다른 인터페이스를 작성해 봅시다 :4n
k
draw <- function(deck) {
n <- length(sentinels <- sort(unique(deck)))
deck <- c(deck, sentinels)
k <- 0
for (j in sentinels) {
k <- k+1
deck <- deck[-(1:match(j, deck))]
if (length(deck) < n) break
}
return(k)
}
(사용할 수 있습니다 draw
대신에 sim
모든 곳에서, 그러나의 시작 부분에 수행 된 추가 작업 draw
느린 배 차종을 sim
.)
주어진 데크의 모든 셔플 에 적용하여 사용할 수 있습니다 . 여기서의 목적은 일회성 테스트 일 뿐이므로 셔플 생성의 효율성은 중요하지 않습니다. 다음은 빠른 무차별 방식입니다.
n <- 4 # Distinct cards
k <- 2 # Number of suits
d <- expand.grid(lapply(1:(n*k), function(i) 1:n))
e <- apply(d, 1, function(x) var(tabulate(x))==0)
g <- apply(d, 1, function(x) length(unique(x))==n)
d <- d[e & g,]
이제 d
행에 모든 셔플이 포함 된 데이터 프레임이 있습니다. draw
각 행에 적용 하고 결과를 세십시오.
d$result <- apply(as.matrix(d), 1, draw)
(counts <- table(d$result))
결과는 (정식 테스트에서 잠시 사용할 것입니다)
2 3 4
420 784 1316
(의 값 그런데, 이해하기 쉬운 : 우리는 여전히 카드에 일하게 될 것이라고 경우 모든의 보수는 모든 에이스를 선행하는 경우에만이 일어나는의 기회를 (두 벌과)입니다. 의. 아웃 구별 셔플을 이 특성을 갖는다.)2 1 / ( 2 + 225202520/6=420
카이 제곱 테스트로 출력을 테스트 할 수 있습니다. 이를 위해 소송 에서 개의 개별 카드의 경우 번을 적용 합니다.sim
>set.seed(17)
>d.sim <- replicate(10^4, sim(n, k))
>print((rbind(table(d.sim) / length(d.sim), counts / dim(d)[1])), digits=3)
2 3 4
[1,] 0.168 0.312 0.520
[2,] 0.167 0.311 0.522
> chisq.test(table(d.sim), p=counts / dim(d)[1])
Chi-squared test for given probabilities
data: table(d.sim)
X-squared = 0.2129, df = 2, p-value = 0.899
가 너무 높기 때문에 우리 는 말과 철저한 열거로 계산 된 값 사이에 큰 차이가 없습니다 . 과 의 다른 (작은) 값에 대해이 연습을 반복 하면 비슷한 결과가 나오므로 과 적용될 때 신뢰할만한 충분한 이유가 됩니다 .sim
sim
마지막으로 2- 표본 카이 제곱 테스트 는 sim
출력을 다른 답변에보고 된 출력과 비교합니다 .
>y <- c(1660,8414,16973,21495,20021,14549,8957,4546,2087,828,313,109)
>chisq.test(cbind(u, y))
data: cbind(u, y)
X-squared = 142.2489, df = 11, p-value < 2.2e-16
막대한 카이 제곱 통계량은 본질적으로 0 인 p- 값을 생성합니다 . 의심 할 여지없이 sim
다른 답변에 동의하지 않습니다. 불일치에 대한 두 가지 가능한 해결책이 있습니다.이 답변 중 하나 (또는 둘 다!)가 틀리거나 질문에 대한 다른 해석을 구현합니다. 예를 들어, 나는 마지막 카드를 관찰 한 후 "덱이 바닥 난 후"를 의미 하고, 가능하다면 절차를 종료하기 전에 "사용할 번호"를 업데이트 한 것으로 해석했습니다 . 아마도 그 마지막 단계는 취해지지 않았습니다. 아마도 그러한 미묘한 해석 차이는 의견 차이를 설명 할 것이며,이 시점에서 우리는 질문을 명확하게하기 위해 질문을 수정할 수 있습니다.
정확한 답이 있습니다 (아래 4 항에 제시된 매트릭스 제품 형태). 이를 계산하기 위해 합리적으로 효율적인 알고리즘이 존재합니다.
셔플의 임의의 카드 랜덤 셔플 링에 의해 생성 될 수있는 카드하고 임의로 산재 나머지 그 안에 카드.
에이스 만 섞은 다음 (첫 번째 관찰을 적용하여) 두 개, 세 개 등을 산재시킴으로써이 문제는 13 단계의 체인으로 볼 수 있습니다.
우리는 우리가 찾고있는 카드의 가치보다 더 많은 것을 추적해야합니다. 그러나 이렇게 할 때 모든 카드에 대한 마크의 위치를 설명 할 필요는 없지만 값이 같거나 작은 카드에 대한 위치 만 고려하면됩니다.
첫 에이스에 표시를 한 다음 그 뒤에 나오는 첫 번째 두 개의 마크를 표시하는 것을 상상해보십시오. (어떤 단계에서든 현재 찾고있는 카드를 표시하지 않고 덱이 떨어지면 모든 카드를 표시하지 않은 상태로 둡니다.) 각 마크의 "장소"(존재하는 경우)는 값이 같거나 낮은 카드 수입니다. 마크가 만들어 졌을 때 (표시된 카드 자체 포함) 처리되었습니다. 장소는 모든 필수 정보를 포함합니다.
표시 뒤의 위치 는 임의의 숫자입니다. 특정 데크의 경우 이러한 장소의 순서는 확률 적 프로세스를 형성합니다. 실제로 Markov 프로세스 (가변 전이 행렬 포함)입니다. 따라서 12 개의 행렬 곱셈을 통해 정확한 답을 계산할 수 있습니다.
이 아이디어를 사용하여이 기계는 초 안에 (배정 밀도 부동 소수점으로 계산) 의 값을 얻습니다 . 정확한 값 은 표시된 모든 자릿수에 정확합니다.
이 게시물의 나머지 부분에서는 세부 정보를 제공하고 실제 구현을 제공하며 R
질문과 솔루션의 효율성에 대한 의견으로 마무리합니다.
그것은 (일명 개념적 실제로 명확하고 더 이상은 "데크"를 고려하는 것이 수학적으로 복잡 MULTISET )의 가있는 카드 가장 낮은 교단의 등 다음으로 낮은, 그리고 . (질문과 같은 질문은 벡터 의해 결정된 데크에 관한 것 입니다.)
카드 의 "무작위 셔플"은 에서 균일하고 무작위로 가져온 하나의 순열입니다 카드의 순열 . 이러한 셔플은 "aces"를 변경하면 아무것도 변경되지 않고 "twos"를 변경해도 아무것도 변경되지 않기 때문에 동등한 구성의 그룹으로 분류 됩니다. 따라서 카드의 양복이 무시 될 때 동일하게 보이는 각 순열 그룹에는순열. 다항식 계수에 의해 주어진 수의 그룹N ! = N × ( N - 1 ) × ⋯ × 2 × 1 N k 1 k 2
갑판의 "조합"이라고합니다.
조합을 계산하는 다른 방법이 있습니다. 첫 번째 카드는 조합. 다음 카드를 놓을 수 있도록 그들 사이와 주변에 "슬롯"을 남겨 둡니다 . " "는 카드 중 하나를 지정 하고 " "는 과 사이의 추가 카드를 넣을 수있는 슬롯을 지정 하는 다이어그램 으로이를 수 있습니다 .
때 추가 카드가 산재되어, 별과 새로운 카드 파티션의 패턴 두 부분 집합으로 카드. 고유 한 하위 집합의 수는 입니다.
"threes" 로이 절차를 반복하면 는 첫 번째 카드 사이에 하는 방법 입니다. 따라서 이런 식으로 첫 번째 카드 를 배열하는 총 고유 한 방법의 수는
마지막 카드를 완성 하고이 텔레 스코핑 비율을 계속해서 곱한 후 , 얻은 고유 조합 수가 이전에 계산 된 총 조합 수인 . 따라서 우리는 조합을 간과하지 않았습니다. 이는 카드를 순서대로 섞는이 순차적 프로세스가 각 단계에서 기존 카드 중 새 카드를 산재하는 각각의 고유 한 방법이 균일하게 동일한 확률로 가정된다는 가정하에 각 조합의 확률을 정확하게 포착 한다는 것을 의미 합니다 .
처음에는 개의 에이스가 있으며 분명히 첫 번째가 표시됩니다. 후기 단계에는 카드가 있으며 장소 (표시된 카드가있는 경우)는 (일부 값은 에서 임 )와 같 으며 는 산재하려고합니다. 주위에 카드. 우리는 이것을 다음과 같은 다이어그램으로 시각화 할 수 있습니다
여기서 " "는 현재 표시된 기호를 나타냅니다. 조건부 장소의이 값에 , 우리는 다음 장소는 동일 확률 찾고자 (일부 값 을 통해 , 게임의 규칙에 의해, 다음 장소 후에 와야 , 어디서 ). 우리가 산재하기 위해 얼마나 많은 방법을 찾아 낼 수있는 경우에 그래서 다음 장소에 해당하는 빈칸에 새로운 카드를 , 우리는이 카드를 산재하는 방법의 총 개수로 나눌 수 있습니다 (동일 우리가 본 것처럼장소가 에서 바뀌는 전이 확률 . (표시된 카드를 따르는 새 카드도 없을 때 장소가 완전히 사라질 가능성이 있지만이를 명시 적으로 계산할 필요는 없습니다.)
이 상황을 반영하도록 다이어그램을 업데이트하겠습니다.
"세로줄 제 새로운 카드가 표시된 카드 후에 발생 쇼" 더 새로운 카드 그러므로 사이 나타나지 않을 수 및 (따라서 어떤 슬롯이 그 간격에 도시되지 않음). 우리는이 구간에 얼마나 많은 별이 있는지 모릅니다. 그래서 방금 (0 일 수도 있습니다) 라고 불렀습니다 . 알 수없는 는 우리가 그것과 사이의 관계를 찾으면 사라질 것 입니다.
그런 다음, 우리 는 이전의 별 주위에 새 카드를 산재하고 그 와 독립적으로 뒤의 별 주위에 남아있는 새 카드를 산재 한다고 가정합니다 . 있다
이것을하는 방법. 공지 사항,하지만 -이 분석의 가장 까다로운 부분은 -의 장소 것을 동일 인해를
따라서 는 장소 에서 장소 로의 전환에 대한 정보를 제공합니다 . 우리는 모든 가능한 값에 대해 신중하게이 정보를 추적 할 때 , 그리고 합계 모든 (이산) 가능성을 통해 우리는 위의 조건부 확률을 구하는 위 아래의 ,
여기서 합계는 에서 시작하고 에서 끝납니다 이 합계의 가변 길이는 특별한 경우를 제외하고 및 의 함수로 공식에 포함되지는 않습니다 .)
초기 확률이 존재 곳이 될 것이라고 확률 이 임의의 다른 가능한 값을 가질 것 . 이것은 벡터 로 나타낼 수 있습니다 .
다음 카드를 산재한 후 벡터 은 왼쪽에있는 전이 행렬 을 곱하여 로 업데이트됩니다. . 모든 카드가 배치 될 때까지이 과정이 반복 됩니다. 각 단계 에서 확률 벡터 의 항목 합계는 일부 카드가 표시되었을 가능성입니다 . 따라서 값을 유지하기 위해 남은 것은 단계 후에 카드가 표시 되지 않을 가능성입니다. 따라서 이러한 값의 연속적인 차이는 표시 할 유형의 카드를 찾을 수없는 확률을 제공 합니다. 즉, 게임이 끝날 때 덱이 다 떨어질 때 찾고 있던 카드 값의 확률 분포입니다. .
다음 R
코드는 알고리즘을 구현합니다. 앞에서 설명한 내용과 비슷합니다. 먼저, 전환 확률 계산은t.matrix
않고 정규화하지 않고 코드를 테스트 할 때 계산을 더 쉽게 추적 할 수 있습니다.
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
로 업데이트 하는 데 사용됩니다 . 전이 행렬을 계산하고 곱셈을 수행합니다. 또한 인수 가 빈 벡터 인 경우 초기 벡터 을 계산합니다 .p
#
# `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
규칙에 따르면 왕이 표시되면 더 이상 카드를 찾지 않을 것입니다. 이는 의 값 을 로 늘려야 한다는 의미 입니다. 그렇게 할 때, 차이점은 "갑판이 다 떨어졌을 때의 숫자"의 분포를 나타냅니다.
> 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
(Monte-Carlo 시뮬레이션을 설명하는 별도의 답변으로 출력 한 보고서와 비교해보십시오. 예상되는 임의의 변동량까지 동일한 것으로 보입니다.)
예상 값은 즉각적입니다.
> sum(diff(g) * 2:13)
[1] 5.832589
모두들, 이것은 12 줄 정도의 실행 코드 만 필요했습니다. 나는 작은 값 (최대 ) 에 대한 손 계산과 비교하여 확인했습니다 . 따라서 코드와 문제의 이전 분석간에 불일치가 발생 하면 분석에 인쇄상의 오류가있을 수 있으므로 코드를 신뢰하십시오 .
다른 서열과의 관계
각 카드 중 하나가있을 때 분포는 정수의 역수 순서입니다.
> 1/diff(game(rep(1,10)))
[1] 2 3 8 30 144 840 5760 45360 403200
장소 의 가치 는( 에서 시작 ). 이다 순서 A001048 정수 시퀀스의 온라인 백과 사전이다. 따라서 우리는 이 시퀀스를 일반화 할 상수 ( "적합한"데크)를 가진 데크에 대해 닫힌 공식을 원할 수 있습니다. (예를 들어, 순열 그룹에서 가장 큰 결합 클래스의 크기를 계산하고 삼항 계수 와도 관련이 있습니다 .) (안타깝게도 에 대한 일반화의 역수는 일반적으로 정수가 아닙니다.)
확률 적 프로세스로서의 게임
우리의 분석은 벡터 , 의 초기 계수 가 일정 하다는 것을 분명히합니다 . 예를 들어, 각 카드 그룹을 처리 할 때 출력을 추적 해 보겠습니다 .game
> 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 장의 카드로 결과를 설명 함)은 두 번째 그룹이 처리 된 후 이미 나타 났으며 과 같습니다 . 따라서 카드 값을 통해 마크 업에 대한 정보 만 원하는 경우 카드 의 데크에 계산을 수행하면됩니다 .
가치의 카드를 표시하지 가능성 때문에 신속하게 가까운지고 로 증가, 이후 사 정장 카드의 종류 우리는 거의 기대에 대한 한계 값에 도달했습니다. 실제로, 제한 값은 약 ( 카드 의 데크에 대해 계산 됨 ,이 시점에서 배정도 반올림 오류로 인해 더 이상 진행되지 않음).
타이밍
-vector 적용된 알고리즘을 살펴보면 타이밍이 비례해야 하고 조잡한 상한을 사용하여 비례하는 것보다 나쁘지 않아야합니다. . ~ 및 ~ 대한 모든 계산의 타이밍을 정하고 상대적으로 오랜 시간 ( 초 이상)이 걸리는 계산 만 분석함으로써 계산 시간은 대략 ,이 상한 평가를 지원합니다.( K , K는 , ... , k는 ) k는 2 m 3 (K) = 1 (7) N = 10 30 1 / 2 O ( K 2 N 2.9 )
이러한 무증상의 한 가지 용도는 더 큰 문제에 대한 계산 시간을 계획하는 것입니다. 예를 들어, 의 경우 약 초가 걸리고 , (매우 흥미로운) 경우 경우 약 초 (실제로 초가 걸립니다 .)1.31 K = 1 , N = 100 1.31 ( 1 / 4 ) (2) ( 100 / 30 ) 2.9 ≈ 2.7 2.87
Perl에서 간단한 Monte Carlo를 해킹하여 약 발견 .
#!/usr/bin/perl
use strict;
my @deck = (1..13) x 4;
my $N = 100000; # Monte Carlo iterations.
my $mean = 0;
for (my $i = 1; $i <= $N; $i++) {
my @d = @deck;
fisher_yates_shuffle(\@d);
my $last = 0;
foreach my $c (@d) {
if ($c == $last + 1) { $last = $c }
}
$mean += ($last + 1) / $N;
}
print $mean, "\n";
sub fisher_yates_shuffle {
my $array = shift;
my $i = @$array;
while (--$i) {
my $j = int rand($i + 1);
@$array[$i, $j] = @$array[$j, $i];
}
}