BlackJack is a classic Casino card game. A detailed explanation is given here. When the game starts you (the player) have two cards in front of you and the dealer has one, all visible. You now have to decide to either take another card or not. Your clearly should do whatever gives you the better chance of winning. Say you have a King and a 3, for a total of 13, and the dealer shows an 8. Write a simulation that finds the probabilities of either taking another card or staying, and then winning the game. To simplify you will only take one more card, if any.
Use the following dealer rules: dealer takes another card if his total is at most 15 (“stay on 16”). An Ace counts as 11 if that puts the dealer to 16-21, otherwise it counts as 1.
Here is the answer:
take.one.card.or.stay <- function(player=13, dealer=8, B=1e4) {
cards <- c(2:10, 10, 10, 10, 11)
player.win <- c(0, 0)
dealer.start <- dealer
names(player.win) <- c("Stay", "Take Card")
for(i in 1:B) {
# Player goes first:
player.next.card <- sample(cards, 1, replace=TRUE)
if(player.next.card==11 & player+player.next.card>21)
player.next.card <- 1
player.takes.card <- player+player.next.card
# Now the dealer goes:
dealer <- dealer.start
repeat {
dealer.next.card <- sample(cards, 1, replace=TRUE)
if(dealer.next.card==11 & dealer+dealer.next.card>21)
dealer.next.card <- 1 # Ace has to be counted as 1
dealer <- dealer + dealer.next.card
if(dealer>15) break
}
# Let's see what we have:
# First we didn't pick another card,
# then we win if dealer is less than us or over 21:
if(dealer>21 | dealer<player)
player.win[1] <- player.win[1]+1
# Second we did pick another card,
# then we win if we didn't go over 21 and dealer is less than us or over 21:
if(player.takes.card<=21) {
if(dealer>21 | dealer<player.takes.card)
player.win[2] <- player.win[2]+1
}
}
player.win/B
}
take.one.card.or.stay(player=13, dealer=8, B=1e4)
## Stay Take Card
## 0.1705 0.2956
so the probability of winning when taking a card is about 30% but when staying it is only 17%, so you should take a card!
Use your routine to find the answer when you have a 10 and the dealer shows a 7.
take.one.card.or.stay(player=10, dealer=7, B=1e4)
## Stay Take Card
## 0.1839 0.5489
Say the floor in your house is made of square tiles of one foot by one foot. You have a stick that is 0.5 feet long. If you drop the stick on the floor, what is the probability that it will land entirely within one tile? For example, in the following picture the red stick is entirely inside a tile but the blue one is not.
The hard part of this problem is to turn it into math, and that is actually quite often the case. So what do we have here? In principle we have a three-dimensional problem, with the stick flying and bouncing around. However, we only care about what happens once the stick has stopped moving. At that point the floor is essentially two-dimensional, and so we can start by overlaying the floor with a Cartesian coordinate system. Moreover we can do this in such a way that one end of the stick is always in the unit square [0,1]x[0,1] because we can put the origin anywhere we want.
Now in principle the stick is three-dimensional, it has length, width and height. But for a regular stick the width and the height are eesentially irrelevant because they are much much smaller than the length. So certainly as a first approximation we can treat the stick as a one-dimensional object. This means it is perfectly decribed by the (x,y) coordinates of the ends of the stick. Then all we need to check is whether those ends are both in the same square. One is for sure, so the question becomes whether other one is as well.
How do we drop te stick on the floor? As we said, one end is always in the unit square, so x=runif(2). The other end of the stick has to be a randomly chosen point on a circle of diameter 1/2, centered at x. We can generate that by simply generating a point in the square [-1,1]2, find its length, stretch it so is has length 1/2 and add it to x:
drop.stick <- function(B=1e5) {
x=matrix(runif(2*B), ncol=2) #coordinates of one end of stick, in [0,1]x[0,1]
y=matrix(runif(2*B, -1, 1), ncol=2) #random point in [-1,1]x[-1,1]
distance.to.0=apply(y, 1, function(y) sqrt(sum(y^2)))
y=x+y/distance.to.0/2 #coordinates of other end of stick
y=y[y[ ,1]>0 & y[ ,1]<1 & y[ ,2]>0 &y[ ,2]<1, ] #drop points not in [0,1]x[0,1]
nrow(y)/B
}
drop.stick()
## [1] 0.43689
Here is another solution: this time focus on the midpoint of the stick, let’s call it Z, and again choose it randomly in [0,1]x[0,1]. Now we choose and angle in \((0, \pi)\), the angle at which the stick lies to the horizontal. Now the endpoints are plu and minus 1/4 along that line, and again we check if the endpoints are in the same square. This is the case if the first digit of the coordinates is the same. So
drop.stick.alt <- function(B=1e5) {
z=matrix(runif(2*B), ncol=2) #coordinates of midpoints in [0,1]x[0,1]
phi=runif(B, 0, pi) #angles
x1=round(z[, 1] + sin(phi)/4)
x2=round(z[, 2] + cos(phi)/4)
y1=round(z[, 1] + sin(phi+pi)/4)
y2=round(z[, 2] + cos(phi+pi)/4)
sum(x1==y1 & x2==y2)/B
}
drop.stick.alt()
## [1] 0.44198
This is actually a famous problem called Buffon-Laplace needle problem and the actual answer can be shown to be \(1-\frac7{4\pi}=0.443\). For a calculation of this result see https://www.maa.org/sites/default/files/0746834220026.di020760.02p0021g.pdf.