Delete Cheryl's Birthday.ipynb

This commit is contained in:
Peter Norvig 2017-03-24 19:15:31 -07:00 committed by GitHub
parent 7e99a8ad11
commit 11db599107

View File

@ -1,487 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When is Cheryl's Birthday?\n",
"===\n",
"\n",
"[This puzzle](https://www.google.com/webhp?#q=cheryl%27s%20birthday) has been making the rounds:\n",
"\n",
"1. Albert and Bernard just became friends with Cheryl, and they want to know when her birthday is. Cheryl gave them a list of 10 possible dates:\n",
"<pre>\n",
" May 15 May 16 May 19\n",
" June 17 June 18\n",
" July 14 July 16\n",
" August 14 August 15 August 17\n",
"</pre>\n",
" \n",
"2. Cheryl then tells Albert and Bernard separately the month and the day of the birthday resepctively.\n",
" \n",
"3. Albert: I don't know when Cheryl's birthday is, but I know that Bernard does not know too.\n",
" \n",
"4. Bernard: At first I don't know when Cheryl's birthday is, but I know now.\n",
" \n",
"5. Albert: Then I also know when Cheryl's birthday is.\n",
" \n",
"6. So when is Cheryl's birthday?\n",
"\n",
"\n",
"\n",
"1. Cheryl gave them a list of 10 possible dates:\n",
"---\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"DATES = ['May 15', 'May 16', 'May 19',\n",
" 'June 17', 'June 18',\n",
" 'July 14', 'July 16',\n",
" 'August 14', 'August 15', 'August 17']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We'll define accessor functions for the month and day of a date:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def Month(date): return date.split()[0]\n",
"\n",
"def Day(date): return date.split()[1]"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"'May'"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Month('May 15')"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"'15'"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Day('May 15')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"2. Cheryl then tells Albert and Bernard separately the month and the day of the birthday respectively.\n",
"---\n",
"\n",
"We can define the idea of **telling**, and while we're at it, the idea of **knowing** a birthdate:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def tell(part, possible_dates=DATES):\n",
" \"Cheryl tells a part of her birthdate to someone; return a new list of possible dates that match the part.\"\n",
" return [date for date in possible_dates if part in date]\n",
"\n",
"def know(possible_dates):\n",
" \"A person knows the birthdate if they have exactly one possible date.\"\n",
" return len(possible_dates) == 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that we use a *list of dates* to represent someone's knowledge of the possible birthdates, and that someone *knows* the birthdate when they get down to only one possibility. For example: If Cheryl tells Albert that her birthday is in May, he would know there is a list of three possible birthdates:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"['May 15', 'May 16', 'May 19']"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tell('May')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And if she tells Bernard that her birthday is on the 15th, he would know there are two possibilities:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"['May 15', 'August 15']"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tell('15')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"With two possibilities, Bernard does not know the birthdate:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"know(tell('15'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Overall Strategy\n",
"---\n",
"\n",
"When Cheryl tells Albert `'May'` then *he* knows there are three possibilities, but *we* (the puzzle solvers) don't, because we don't know what Cheryl said. So what can we do? We will consider *all* of the possible dates, one at a time. For example, first consider `'May 15'`. Cheryl tells Albert `'May'` and Bernard `'15'`, giving them the lists of possible birthdates shown above. We can then check whether statements 3 through 5 are true in this scenario. If they are, then `'May 15'` is a solution to the puzzle. Repeat the process for each of the other possible dates. If all goes well, there should be exactly one solution. \n",
"\n",
"Here is the main function, `cheryls_birthday`:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def cheryls_birthday(possible_dates=DATES):\n",
" \"Return a list of the possible dates for which all three statements are true.\"\n",
" return filter(all3, possible_dates)\n",
"\n",
"def all3(date): return statement3(date) and statement4(date) and statement5(date)\n",
"\n",
"## TO DO: define statement3, statement4, statement5"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" (*Python note:* `filter(predicate, items)` returns a list of all items for which `predicate(item)` is true.)\n",
" \n",
" 3. Albert: I don't know when Cheryl's birthday is, but I know that Bernard does not know too.\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The function `statement3` takes as input a possible birthdate and returns true if Albert's statement is true for that birthdate. How do we go from Albert's English statement to a Python function? Let's paraphrase in a form that is closer to Python code:\n",
"\n",
"> **Albert**: After Cheryl told me the month of her birthdate, I didn't know her birthday. I also don't know what day Cheryl told Bernard, but for *any* of the possible dates, if Bernard was told the day of that date, he would not know Cheryl's birthday.\n",
"\n",
"That I can translate directly into code:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def statement3(date):\n",
" \"Albert: I don't know when Cheryl's birthday is, but I know that Bernard does not know too.\"\n",
" possible_dates = tell(Month(date))\n",
" return (not know(possible_dates) \n",
" and all(not know(tell(Day(d)))\n",
" for d in possible_dates))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We haven't solved the puzzle yet, but let's take a peek and see which dates satisfy statement 3:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"['July 14', 'July 16', 'August 14', 'August 15', 'August 17']"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"filter(statement3, DATES)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"4. Bernard: At first I don't know when Cheryl's birthday is, but I know now.\n",
"---\n",
"\n",
"Again, a paraphrase:\n",
"\n",
"> **Bernard:** At first Cheryl told me the day, and I didn't know. Then I considered just the dates for which Albert's statement 3 is true, and now I know."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def statement4(date):\n",
" \"Bernard: At first I don't know when Cheryl's birthday is, but I know now.\"\n",
" at_first = tell(Day(date))\n",
" return (not know(at_first) \n",
" and know(filter(statement3, at_first)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's see which dates satisfy both statement 3 and statement 4:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"['July 16', 'August 15', 'August 17']"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"filter(statement4, filter(statement3, DATES))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Wait a minute&mdash;I thought that Bernard **knew**?! Why are there three possible dates? Bernard does indeed know; it is just that we, the puzzle solvers, don't know. That's because Bernard knows something we don't know: the day. We won't know until after statement 5.\n",
"\n",
"5. Albert: Then I also know when Cheryl's birthday is.\n",
"---\n",
"\n",
"Albert is saying that after hearing the month and Bernard's statement 4, he now knows Cheryl's birthday:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def statement5(date):\n",
" \"Albert: Then I also know when Cheryl's birthday is.\"\n",
" return know(filter(statement4, tell(Month(date))))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"6. So when is Cheryl's birthday?\n",
"---\n",
"\n",
"Let's see:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"['July 16']"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cheryls_birthday()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Success!** We have deduced that Cheryl's birthday is **July 16**. It is now `True` that we know Cheryl's birthday:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"know(cheryls_birthday())"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.1"
}
},
"nbformat": 4,
"nbformat_minor": 0
}