Add files via upload

This commit is contained in:
Peter Norvig 2020-04-13 21:08:16 -07:00 committed by GitHub
parent 669a926364
commit 558b50f049
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -31,7 +31,7 @@
},
{
"cell_type": "code",
"execution_count": 20,
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
@ -50,7 +50,7 @@
},
{
"cell_type": "code",
"execution_count": 21,
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
@ -60,7 +60,7 @@
},
{
"cell_type": "code",
"execution_count": 22,
"execution_count": 3,
"metadata": {},
"outputs": [
{
@ -69,7 +69,7 @@
"'May'"
]
},
"execution_count": 22,
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
@ -80,7 +80,7 @@
},
{
"cell_type": "code",
"execution_count": 23,
"execution_count": 4,
"metadata": {},
"outputs": [
{
@ -89,7 +89,7 @@
"'15'"
]
},
"execution_count": 23,
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
@ -104,30 +104,30 @@
"source": [
"## 2. Cheryl then tells Albert and Bernard separately the month and the day of the birthday respectively.\n",
"\n",
"Now we have to think carefully about what we're doing. The puzzle is tricky because we're dealing with two types of uncertainty:\n",
"Now we have to think really carefully about what we're doing. The puzzle is tricky because we're dealing with two types of uncertainty:\n",
"\n",
"1. Albert and Bernard are uncertain about the birthdate. *(Cheryl knows something they don't know.)*\n",
"2. We, the puzzle solvers don't know what Albert and Bernard were told. *(They know something we don't know.)*\n",
"\n",
"If Cheryl tells Albert \"May\", then he believes the birthday could be either May 15, May 16, or May 19. We'll call `{'May 15', 'May 16', 'May 19'}` his **belief set**. We will say that a person **knows** the birthdate when they get down to a belief set with only one possibility. The type 2 uncertainty is that we don't know that Albert was told \"May\", so we have uncertainty about his belief set. But we do know some statements about his belief set, and our task is to use those statements to solve the puzzle. \n",
"If Cheryl tells Albert \"May\", then he believes the birthdate could be either May 15, May 16, or May 19. We'll call `{'May 15', 'May 16', 'May 19'}` his **belief set** about the birthdate. We will say that a person **knows** the birthdate when they get down to a belief set with exactly one possibility. The type 2 uncertainty is that we don't know that Albert was told \"May\", so we have uncertainty about his belief set. But we do know some statements about his belief set, and our task is to use those statements to solve the puzzle. \n",
"\n",
"The way we will deal with our uncertainty as puzzle solvers is by considering each of the ten dates one at a time and reasoning as follows: \n",
"- If this date were Cheryl's true birthdate, then we would know what Albert and Bernard were told: we would eliminate the type 2 uncertainty, and we could figure out their belief sets. \n",
"- From that we could figure out if the statements are true (given this date). \n",
"- If the puzzle is correct and we don't make mistakes, then there will be only one date that makes all the statements true.\n",
"- If the puzzle is correct and we don't make mistakes, then there will be only one date that makes all the statements true; that's Cheryl's birthday.\n",
"\n",
"We can define the idea of Cheryl having **told** someone a component of her birthdate, and the idea of **knowing** a birthdate as follows:"
]
},
{
"cell_type": "code",
"execution_count": 24,
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"BeliefSet = set\n",
"\n",
"def told(part: str, dates=dates) -> BeliefSet:\n",
"def told(part: str) -> BeliefSet:\n",
" \"\"\"Cheryl told a part of her birthdate to someone; return a belief set of possible dates.\"\"\"\n",
" return {date for date in dates if part in date}\n",
"\n",
@ -140,6 +140,8 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"(Note: one thing I dislike about my code is that `told` uses the global `dates`. Later we will see that `cheryls_birthday` does the same. For that to be an acceptable design choice, we need to think of `dates` as a constant, not a variable.)\n",
"\n",
"Let's see what happens as we consider the date `'May 15'`:\n",
"\n",
"Cheryl tells Albert `'May'` and Bernard `'15'`, giving them these belief sets: "
@ -147,7 +149,7 @@
},
{
"cell_type": "code",
"execution_count": 25,
"execution_count": 6,
"metadata": {},
"outputs": [
{
@ -156,7 +158,7 @@
"{'May 15', 'May 16', 'May 19'}"
]
},
"execution_count": 25,
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
@ -167,7 +169,7 @@
},
{
"cell_type": "code",
"execution_count": 26,
"execution_count": 7,
"metadata": {},
"outputs": [
{
@ -176,7 +178,7 @@
"{'August 15', 'May 15'}"
]
},
"execution_count": 26,
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
@ -189,12 +191,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We can then check whether statements 3 through 5 are true in this scenario. The first part of statement 3 is Albert saying \"I don't know when Cheryl's birthday is.\" We can verify that that part of the statement is true (given that Albert was told \"May\"):"
"We can then check whether statements 3 through 5 are true, given this date. The first part of statement 3 is \"I (Albert) don't know when Cheryl's birthday is.\" We can verify that that part of the statement is true (given that Albert was told \"May\"):"
]
},
{
"cell_type": "code",
"execution_count": 27,
"execution_count": 8,
"metadata": {},
"outputs": [
{
@ -203,7 +205,7 @@
"True"
]
},
"execution_count": 27,
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
@ -225,25 +227,25 @@
"source": [
"# Overall Strategy\n",
"\n",
"Here is the main function, `cheryls_birthday`, which takes a set of possible dates as input, and returns the subset of dates that satisfy statements 3 through 5. We will define a **statement** as a boolean function that takes a single date as input and returns true if the statement would be true in the condition that the given date is Cheryl's actual birthday. So a statement only has to consider one date at a time. But the code within a statement may have to consider the belief sets of Albert and Bernard to determine if the statement is true.\n",
"Here is the main function, `cheryls_birthday`, which computes the subset of dates in the global variable `dates` that satisfy statements 3 through 5. We will define a **statement** as a boolean function that takes a single date as input and returns true if the statement would be true in the condition that the given date is Cheryl's actual birthday. So a statement only has to consider one date at a time. But the code within a statement may have to consider the belief sets of Albert and Bernard, to determine if the statement is true.\n",
"\n",
"The function `satisfy` takes a collection of items (here a set of dates) and returns the subset that satisfies all the predicates:"
]
},
{
"cell_type": "code",
"execution_count": 28,
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def cheryls_birthday(dates=dates) -> BeliefSet:\n",
" \"\"\"Return a subset of the dates for which all three statements are true.\"\"\"\n",
"def cheryls_birthday() -> BeliefSet:\n",
" \"\"\"Return a subset of the global `dates` for which all three statements are true.\"\"\"\n",
" return satisfy(dates, statement3, statement4, statement5)\n",
"\n",
"def satisfy(items, *predicates) -> BeliefSet:\n",
" \"\"\"Return the subset of items that satisfy all the predicates.\"\"\"\n",
" return {item for item in items\n",
" if all(pred(item) for pred in predicates)}"
" if all(predicate(item) for predicate in predicates)}"
]
},
{
@ -259,23 +261,23 @@
"source": [
"The function `statement3` takes as input a single 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 it in a form that uses the concepts we have defined:\n",
"\n",
"> **Albert**: After Cheryl **told** me the **month** of her birthdate, my belief set was such that I didn't **know** her birthday. But I can see that for **all** the possible dates, if Bernard was **told** the **day** of that date, he would **not know** Cheryl's birthday.\n",
"> **Albert**: After Cheryl **told** me the **month** of her birthdate, my **belief set** was such that I didn't **know** her birthday. I do know that Bernard does not know. How do I know that? I can see that for **all** the possible dates in my **belief set**, 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": 29,
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"def statement3(date) -> bool:\n",
" \"\"\"Albert: I don't know when Cheryl's birthday is, but I know that Bernard does not know too.\"\"\"\n",
" albert_dates = told(month(date))\n",
" return (not know(albert_dates) \n",
" albert_beliefs = told(month(date))\n",
" return (not know(albert_beliefs) \n",
" and all(not know(told(day(d))) \n",
" for d in albert_dates))"
" for d in albert_beliefs))"
]
},
{
@ -287,7 +289,7 @@
},
{
"cell_type": "code",
"execution_count": 30,
"execution_count": 11,
"metadata": {},
"outputs": [
{
@ -296,7 +298,7 @@
"{'August 14', 'August 15', 'August 17', 'July 14', 'July 16'}"
]
},
"execution_count": 30,
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
@ -305,35 +307,6 @@
"satisfy(dates, statement3)"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'May 15': {'August 15', 'May 15'},\n",
" 'May 16': {'July 16', 'May 16'},\n",
" 'May 19': {'May 19'},\n",
" 'June 17': {'August 17', 'June 17'},\n",
" 'June 18': {'June 18'},\n",
" 'July 14': {'August 14', 'July 14'},\n",
" 'July 16': {'July 16', 'May 16'},\n",
" 'August 14': {'August 14', 'July 14'},\n",
" 'August 15': {'August 15', 'May 15'},\n",
" 'August 17': {'August 17', 'June 17'}}"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"{d: told(day(d)) for d in dates}"
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -342,7 +315,7 @@
"\n",
"Again, a paraphrase:\n",
"\n",
"> **Bernard:** At first Cheryl **told** me the **day**, and I didn't **know**. Then, out of those possible dates, I considered just the dates that **satisfy** Albert's **statement 3**, and now I **know**."
"> **Bernard:** At first Cheryl **told** me the **day**, and I didn't **know**. After I heard Albert's **statement 3**, I updated my **belief set**, and now I **know**."
]
},
{
@ -353,9 +326,9 @@
"source": [
"def statement4(date) -> bool:\n",
" \"Bernard: At first I don't know when Cheryl's birthday is, but I know now.\"\n",
" at_first_dates = told(day(date))\n",
" after3_dates = satisfy(at_first_dates, statement3)\n",
" return not know(at_first_dates) and know(after3_dates)"
" at_first_beliefs = told(day(date))\n",
" after3_beliefs = satisfy(at_first_beliefs, statement3)\n",
" return not know(at_first_beliefs) and know(after3_beliefs)"
]
},
{
@ -391,15 +364,13 @@
"source": [
"Wait a minute—I thought that Bernard **knew**?! Why are there three possible dates? \n",
"\n",
"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. If Bernard was told `'15'` then he would know `'August 15'`; if he was told `'17'` he would know `'August 17'`, and if he was told `'16'` he would know `'July 16'`. *We* don't know because we don't know which of these is the case. We'll need more information (coming in statement 5) before we know.\n",
"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. If Bernard was told `'15'` then he would know `'August 15'`; if he was told `'17'` he would know `'August 17'`, and if he was told `'16'` he would know `'July 16'`. *We* don't know because we don't know which of these is the case. We'll need more information (coming in statement 5) before *we* know.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"## 5. Albert: Then I also know when Cheryl's birthday is.\n",
"\n",
@ -414,9 +385,8 @@
"source": [
"def statement5(date) -> bool:\n",
" \"Albert: Then I also know when Cheryl's birthday is.\" \n",
" albert_dates = told(month(date))\n",
" after4_dates = satisfy(albert_dates, statement4)\n",
" return know(after4_dates)"
" after4_beliefs = satisfy(told(month(date)), statement4)\n",
" return know(after4_beliefs)"
]
},
{
@ -487,16 +457,16 @@
"> 1. Steve tells Alice the hour of his bus departure and he tells Annie at which minute it leaves. He also tells them both that the bus leaves between 06:00 and 10:00.\n",
"> 2. Alice and Annie consult the timetable and find the following services between those two time: 06:32 06:43 06:50 07:17 07:46 08:19 08:32 09:17 09:19 09:50.\n",
"> 3. Alice then says “I dont know when Steves bus leaves but I am sure that neither does Annie”\n",
"> 4. Annie Replies “I didnt know his bus, but now i do”\n",
"> 4. Annie Replies “I didnt know his bus, but now I do”\n",
"> 5. Alice responds “Now I do as well!”\n",
"> 6. When is Steves bus?\n",
"\n",
"Upon closer inspection, not only is it a similar format, it is **exactly** the same puzzle, except that months are changed to hours and days to minutes. If we write the times in the same format as dates, we can solve the problem without writing a single line of new code:"
"Upon closer inspection, not only is it a similar format, it is **exactly** the same puzzle, except that months are changed to hours and days to minutes. If we rewrite the times in the same format as `dates`, we can solve the problem without writing a single line of new code:"
]
},
{
"cell_type": "code",
"execution_count": 35,
"execution_count": 17,
"metadata": {},
"outputs": [
{
@ -505,13 +475,14 @@
"{'08 32'}"
]
},
"execution_count": 35,
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dates[:] = '06 32, 06 43, 06 50, 07 17, 07 46, 08 19, 08 32, 09 17, 09 19, 09 50'.split(', ')\n",
"dates = '06:32, 06:43, 06:50, 07:17, 07:46, 08:19, 08:32, 09:17, 09:19, 09:50'.replace(':', ' ').split(', ')\n",
"\n",
"cheryls_birthday()"
]
},