Picking 2 Socks At Random
Amazon used to ask this problem as part of their interview:
A drawer contains 12 identical black socks and 12 identical white socks. If you pick 2 socks at random, what is the probability of getting a matching pair?
Think about it for a few minutes before scrolling down to read this further.
Ready?
My immediate reaction was “11/23”. But the question is supposed to be hard, which is why I assumed my answer was completely wrong. Well, maybe it wasn’t? There is only one way to verify.
It takes less than a second to do this experiment a million times in a row. So let’s do that.
Apparently, the most common wrong answer is 50%.
Let’s start. Here is our drawer filled with socks.
const drawer = [
'⚪️', '⚪️', '⚪️', '⚪️', '⚪️', '⚪️',
'⚪️', '⚪️', '⚪️', '⚪️', '⚪️', '⚪️',
'⚫️', '⚫️', '⚫️', '⚫️', '⚫️', '⚫️',
'⚫️', '⚫️', '⚫️', '⚫️', '⚫️', '⚫️',
]
We have exactly 12 white and 12 black socks in our array. Now, we need to randomly draw two socks from here.
const getRandomInt = max => Math.floor(Math.random() * max)
This function will return a random integer less than the max
value it takes in. Note that max
is non-inclusive so we can pass in the array length. In JavaScript, array indexing starts at 0, so for an array with 24 elements, the indexes range from 0 to 23.
We can use our function to draw two socks.
const firstDrawIndex = getRandomInt(24)
const [firstSock] = drawer.splice(firstDrawIndex, 1)
const secondDrawIndex = getRandomInt(23)
const [secondSock] = drawer.splice(secondDrawIndex, 1)
return firstSock === secondSock
splice
will remove the sock from the array and return the resulting item that was just removed from the array. It will return an array with a single item, so we just need to pick the first element.
We have a pair now. Let’s just check if these two socks are the same color.
firstSock === secondSock
Whenever they are equal, we have a matching pair. Whenever they’re not, we have a non-matching pair.
Let’s move the logic we have so far into a function drawPair
and run it a million times.
And let’s keep counting the result while doing that.
let matchingCount = 0
let nonMatchingCount = 0
for (let i = 0; i < 1000000; i++) {
drawPair() ? matchingCount++ : nonMatchingCount++
}
const probability = Number(
matchingCount / (matchingCount + nonMatchingCount) * 100)
+ '%'
Have fun:
Matching count:
Nonmatching count:
Probability:
We should be getting results around %47.8, which is 11/23. Here is the actual number in a higher precision:
(11/23) * 100 = 47.82608695652174%
Or maybe it’s the perfect answer. Things either happen or they don’t. ↩