Monday, November 16, 2015

A Game Of Pills, Shoestring Fries, and Land Clumps

Today I Learned:
1) The answer to the following riddle:

A Very Important Man goes to the doctor one day. He discovers he has a deadly terminal illness that will kill him soon. Luckily, the doctor has a medicine that will keep him alive as long as he eats *exactly* one pill of type A and one pill of type B every day. The doctor gives him a bunch of A and a smaller supply of B, and tells him to pick up more B when it's about to run out.

The man then does something remarkably stupid and goes out to his isolated cabin in the woods for a week, with exactly 7 B pills remaining. He tells his friend to bring him more B pills at the end of 7 weeks, so that he won't die on the 8th day, but he otherwise has no way of contacting the outside world or getting more B pills. On the first day, the man drops two B pills and an A pill on the ground, and he loses track of which one is which. The two types of pills look identical and cannot be distinguished by experiment (except by trying a pair of pills and seeing if he dies or not...). Again, the man has a large supply of A pills, 5 B pills that he knows are B pills, and 3 pills of which exactly two are B pills. How can he survive the week with 100% probability?

As usual with these riddles, it may appear at first that this is an unsolvable problem. It is not. The answer is not ridiculously complex. See if you can figure it out. (Please don't spoil the answer in the comments!)

Kudos to Clare Hayes for telling me the riddle; kudos to Robert Johnson for solving it.

2) Shoestring fries are surprisingly close to actual shoe strings in diameter.

3) In a typical Magic: The Gathering* deck with 23 lands, if you shuffle well, on average, the largest clump of lands you'll see is about 4, according to Monte Carlo simulations. Here's some code that you can try, as long as you have numpy and matplotlib (or Seaborn, if you have it and comment in the appropriate lines). This is also a nice little coding challenge -- if you want a 10-20 minute code practice run, try writing one yourself! (Bonus points if you write it in Haskell)

import numpy as np
from matplotlib import pyplot as plt
#import seaborn as sns
n_trials = 10000
max_clump_sizes = -1*np.ones(n_trials)

# Run a bunch of trials
for i in range(n_trials):
    n_lands = 23
    n_nonlands = 37

    # Lands will be represented as ones, non-lands as zero. Luckily,
    # Numpy has a function for shuffling.
    cards = np.concatenate([np.ones(n_lands), np.zeros(n_nonlands)])
    np.random.shuffle(cards)

    # To find clumps, split the array at every zero element. Yeah, this
    # probably isn't efficient, but I'm trusting in Numpy to do the
    # right thing. Besides, this is a Facebook post, I'm trying to keep the
    # code short.
    clumps     = np.split(cards, np.where(cards == 0)[0])
    max_clump  = max(map(len, clumps))
    max_clump_sizes[i] = max_clump - 1 # Split leaves a 0 in each stack.

plt.cla()

# To visualize with seaborn
#sns.distplot(max_clump_sizes, kde=False)

# To visualize with matplotlib
plt.hist(max_clump_sizes, bins=max(max_clump_sizes)-1)

plt.xlim([0, max(max_clump_sizes)])
plt.show()

print("Average maximum land clump size: " + str(np.mean(max_clump_sizes)))

(Note: the whitespace formatting on this blog is kind of weird -- you may have to re-write the tabbing on the for loop to get this to work)

*for the uninitiated, in Magic: The Gathering, players build a deck of 60 cards, which they bring to games to play with. Land cards are a special type of card that produce resources which are used to play other (non-land) cards. As such, they are critical to gameplay, and it's very important how many lands vs non-lands a player draws during the course of a game. Thus, distributions of land clumpiness are of interest to a Magic player.

No comments:

Post a Comment