Counting Coins in the Dark

May 25, 2017

index_1.gif

My friend Dario says this is a Google interview question.

Problem statement

You're in a dark room with n coins. You're told that there are m heads (and therefore n-m tails). You're allowed to flip coins over if you want. The goal is to partition the n coins into 2 piles (not nec. w/ the same number of coins) such that each pile has the same number of heads.

Example

With n=10 coins, m=6 of which are heads, you might simply split the pile into two equal halves and hope that you get m/2=3 heads in each pile.

index_2.gif

index_3.gif

index_4.gif

index_5.gif

You can see the partitions don’t have an equal number of heads. You weren’t feeling lucky.

So this scheme doesn’t have the property that for all sets of coinflips, it partitions the set into two subsets which have the same number of heads.

Can we devise a better scheme?

Solution

There are 3 cases to consider:
Case 1. If m==0, there are no heads, so we partition the coins into “the empty set” and “all the coins”, which each has 0 heads, and you’re done.
Case 2. If m>n/2, flip all the coins. Now you have a situation with n coins and 0<m≤n/2 heads,  which is Case 3.
Case 3. If 0<m≤n/2, do this:

Partition the coins into an m-length list index_6.gif and an (n-m)-length list index_7.gif. Let k denote the number of heads in list index_8.gif, so the number of tails in index_9.gif is (m-k). Since there are m heads total, if index_10.gif has k heads then index_11.gif has m-k heads. Therefore, by flipping all index_12.gif’s coins, index_13.gif’s m-k tails become m-k heads, matching index_14.gif’s m-k heads. So they have the same number of heads, so we are done.

Example

index_15.gif

index_16.gif

index_17.gif

index_18.gif

index_19.gif

index_20.gif

index_21.gif

index_22.gif

index_23.gif

index_24.gif

index_25.gif

Proof by 1 example.

Numerical check of n=1,...,100

First let’s extend the definition of the Not[] function to work on the symbols H and T (heads & tails):

index_26.gif

index_27.gif

index_28.gif

index_29.gif

index_30.gif

index_31.gif

index_32.gif

Here is a function that runs this algorithm:

index_33.gif

It partitions the list into an m-length list and a (n-m)-length list, and flips the coins in the m-length list:

index_34.gif

index_35.gif

If m==0, no heads. A boring partition will work:

index_36.gif

index_37.gif

If m>n/2, flip everything and run f[] again:

index_38.gif

index_39.gif

Here is a function that checks if each set in the partition has the same number of heads:

index_40.gif

Same number of Heads is OK:

index_41.gif

index_42.gif

Different number of Heads is not OK:

index_43.gif

index_44.gif

Here are all the possible sets of 4 coin flips (order doesn’t matter):

index_45.gif

index_46.gif

Run f[] on all the flips and see if the resulting partition has equal numbers of heads:

index_47.gif

flips partition OK?
{T,T,T,T} {{},{T,T,T,T}} True
{H,T,T,T} {{T},{T,T,T}} True
{H,H,T,T} {{T,T},{T,T}} True
{H,H,H,T} {{H},{T,T,H}} True
{H,H,H,H} {{},{T,T,T,T}} True

Here is a function that test whether f[] returns an OK partition for every possible set of n coinflips:

index_48.gif

We already saw that our algorithm works for n=4 coins:

index_49.gif

index_50.gif

Does it work for n coins, for n=1,...,100?

index_51.gif

index_52.gif

Nice!

Created with the Wolfram Language