Add files via upload
This commit is contained in:
parent
c315798ea0
commit
043406805b
@ -4,9 +4,9 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Sol Golomb’s Rectangle Puzzle\n",
|
||||
"<div align=\"right\">Peter Norvig 2014</div>\n",
|
||||
"\n",
|
||||
"<div style=\"text-align:right\">Peter Norvig</span>"
|
||||
"# Sol Golomb’s Rectangle Puzzle"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -15,15 +15,15 @@
|
||||
"source": [
|
||||
"This problem by Solomon Golomb was presented by Gary Antonik in his 14/4/14 New York Times [Numberplay column](http://wordplay.blogs.nytimes.com/2014/04/14/rectangle):\n",
|
||||
"\n",
|
||||
">*Say you’re given the following challenge: create a set of five rectangles that have sides of length 1, 2, 3, 4, 5, 6, 7, 8, 9 and 10 units. You can combine sides in a variety of ways: for example, you could create a set of rectangles with dimensions 1 x 3, 2 x 4, 5 x 7, 6 x 8 and 9 x 10.*\n",
|
||||
">Say you’re given the following challenge: create a set of five rectangles that have sides of length 1, 2, 3, 4, 5, 6, 7, 8, 9 and 10 units. You can combine sides in a variety of ways: for example, you could create a set of rectangles with dimensions 1 x 3, 2 x 4, 5 x 7, 6 x 8 and 9 x 10.\n",
|
||||
">\n",
|
||||
">1. *How many different sets of five rectangles are possible?*\n",
|
||||
">1. How many different sets of five rectangles are possible?\n",
|
||||
">\n",
|
||||
">2. *What are the maximum and minimum values for the total areas of the five rectangles?*\n",
|
||||
">2. What are the maximum and minimum values for the total areas of the five rectangles?\n",
|
||||
">\n",
|
||||
">3. *What other values for the total areas of the five rectangles are possible?*\n",
|
||||
">3. What other values for the total areas of the five rectangles are possible?\n",
|
||||
">\n",
|
||||
">4. *Which sets of rectangles may be assembled to form a square?*\n",
|
||||
">4. Which sets of rectangles may be assembled to form a square?\n",
|
||||
"\n",
|
||||
"To me, these are interesting questions because, first, I have a (slight) personal connection to Solomon Golomb (my former colleague at USC) and to Nelson Blachman (the father of my colleague Nancy Blachman), who presented the problem to Antonik, and second, I find it interesting that the problems span the range from mathematical to computational. Let's answer them."
|
||||
]
|
||||
@ -72,9 +72,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def rectangle_sets(sides):\n",
|
||||
@ -91,9 +89,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
@ -120,9 +116,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
@ -155,9 +149,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
@ -198,15 +190,13 @@
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"I think I know this one, but I'm not sure. I know that a rectangle with a fixed perimeter has maximum area when it is a square. My guess is that the maximum *total* area occurs when each rectangle is *almost* square: a 9 × 10 rectangle; 7 × 8; and so on. So that would give us a maximum area of:"
|
||||
"I think I know this one, but I'm not completely sure. I know that a rectangle with a fixed perimeter has maximum area when it is a square. My guess is that the maximum total area occurs when each rectangle is *almost* square: a 9 × 10 rectangle; 7 × 8; and so on. So that would give us a maximum area of:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
@ -233,9 +223,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
@ -262,9 +250,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def total_area(rectangles): return sum(w * h for (w, h) in rectangles)"
|
||||
@ -273,9 +259,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
@ -295,9 +279,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
@ -338,9 +320,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
@ -365,9 +345,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
@ -388,7 +366,7 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The answer is: \"All the integers between the min (110) and max (190), except 176, 185, 188, and 189.\""
|
||||
"The answer is: \"All the integers between 110 and 190 inclusive, except 176, 185, 188, and 189.\""
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -402,15 +380,13 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The only way I can think about this is to write a program; I don't see any way to work it out by hand. I do know that the total area will have to be a perfect square, so:"
|
||||
"The only way I can think about this is to write a program; I don't see any way to work it out by hand. I do know that the total area will have to be a perfect square, and since the total area is between 110 and 191, that means either 121, 144, or 169:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
@ -458,11 +434,30 @@
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def is_perfect_square(n): return is_integer(n ** 0.5)\n",
|
||||
"def is_integer(n): return (int(n) == n)\n",
|
||||
"perfect_squares = {i ** 2 for i in range(100)}\n",
|
||||
"\n",
|
||||
"sorted((total_area(s), s) \n",
|
||||
" for s in all_sets if is_perfect_square(total_area(s)))"
|
||||
" for s in all_sets if total_area(s) in perfect_squares)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"35"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"len(_)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -479,10 +474,8 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"empty = (0, 0)\n",
|
||||
@ -495,10 +488,8 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
@ -510,7 +501,7 @@
|
||||
" [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]]"
|
||||
]
|
||||
},
|
||||
"execution_count": 14,
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@ -528,10 +519,8 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def place_rectangle_at(rect, grid, pos):\n",
|
||||
@ -550,10 +539,8 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
@ -565,7 +552,7 @@
|
||||
" [(0, 0), (0, 0), (3, 4), (3, 4), (3, 4)]]"
|
||||
]
|
||||
},
|
||||
"execution_count": 16,
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@ -577,10 +564,8 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
@ -592,7 +577,7 @@
|
||||
" [(2, 5), (2, 5), (3, 4), (3, 4), (3, 4)]]"
|
||||
]
|
||||
},
|
||||
"execution_count": 17,
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@ -607,10 +592,8 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"execution_count": 19,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
@ -622,7 +605,7 @@
|
||||
" [(2, 5), (2, 5), (3, 4), (3, 4), (3, 4)]]"
|
||||
]
|
||||
},
|
||||
"execution_count": 18,
|
||||
"execution_count": 19,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@ -634,10 +617,8 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"execution_count": 20,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
@ -656,8 +637,6 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Packing Strategy\n",
|
||||
"\n",
|
||||
"Now we need a strategy for packing a set of rectangles onto a grid. I know that many variants of [bin packing problems](http://en.wikipedia.org/wiki/Bin_packing_problem) are NP-hard, but we only have 5 rectangles, so it should be easy: just exhaustively try each rectangle in each possible position, and in both possible orientations (horizontal and vertical). But placing rectangles is commutative, so we can do this two ways:\n",
|
||||
"\n",
|
||||
"> Way 1: Considering the *rectangles* in a fixed order, try every possible *position* for each *rectangle*.\n",
|
||||
@ -668,34 +647,37 @@
|
||||
"\n",
|
||||
"In Way 1, we could pre-sort the rectangles (say, biggest first). Then we try to put the biggest rectangle in all possible positions on the grid, and for each position that fits, try putting the second biggest rectangle in all remaining positions, and so on. As a rough estimate, assume there are on average about 10 ways to place a rectangle. Then this way will look at about 10<sup>5</sup> = 100,000 combinations.\n",
|
||||
"\n",
|
||||
"In Way 2, we consider the positions in some fixed order; say top-to-bottom, left-to right. Take the first empty position (say, the upper left corner). Try putting each of the rectangles there, and for each one that fits, try all possible rectangles in the next empty position, and so on. There are only 5! permutations of rectangles, and each rectangle can go either horizontally or vertically, so we would have to consider 5! × 2<sup>5</sup> = 3840 combinations. Since 3840 < 100,000, I'll go with Way 2. Here is a more precise description:\n",
|
||||
"In Way 2, we consider the positions in some fixed order; say top-to-bottom, left-to right. Take the first empty position (say, the upper left corner). Try putting each of the rectangles there, and for each one that fits, try all possible rectangles in the next empty position, and so on. There are only 5! permutations of rectangles, and each rectangle can go either horizontaly or vertically, so we would have to consider 5! × 2<sup>5</sup> = 3840 combinations. Since 3840 < 100,000, I'll go with Way 2. Here is a more precise description:\n",
|
||||
"\n",
|
||||
"> Way 2: To `pack` a set of rectangles onto a grid, find the first empty cell on the grid. Try in turn all possible placements of any rectangle (in either orientation) at that position. For each one that fits, try to `pack` the remaining rectangles, and return the resulting grid if one of these packings succeeds. "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def pack(rectangles, grid):\n",
|
||||
" \"\"\"Find a way to pack all rectangles onto grid and return the packed grid,\n",
|
||||
" or return None if not possible.\"\"\"\n",
|
||||
" if not rectangles or grid is None:\n",
|
||||
" if not rectangles:\n",
|
||||
" return grid \n",
|
||||
" pos = first_empty_cell(grid)\n",
|
||||
" if pos is None:\n",
|
||||
" return None\n",
|
||||
" for rect in rectangles:\n",
|
||||
" for (w, h) in [rect, reversed(rect)]:\n",
|
||||
" grid2 = place_rectangle_at((w, h), grid, pos)\n",
|
||||
" solution = pack(rectangles - {rect}, grid2)\n",
|
||||
" if grid and pos:\n",
|
||||
" for (rectangles2, grid2) in rectangle_placements(rectangles, grid, pos):\n",
|
||||
" solution = pack(rectangles2, grid2)\n",
|
||||
" if solution:\n",
|
||||
" return solution\n",
|
||||
"\n",
|
||||
"def rectangle_placements(rectangles, grid, pos):\n",
|
||||
" \"Yield all (rect, grid) pairs that result from placing a rectangle at pos on grid.\"\n",
|
||||
" for (w, h) in rectangles:\n",
|
||||
" for rect in [(w, h), (h, w)]:\n",
|
||||
" grid2 = place_rectangle_at(rect, grid, pos)\n",
|
||||
" if grid2: \n",
|
||||
" yield rectangles - {(w, h)}, grid2 \n",
|
||||
" \n",
|
||||
"def first_empty_cell(grid):\n",
|
||||
" \"The uppermost, leftmost empty cell.\"\n",
|
||||
" for (y, row) in enumerate(grid):\n",
|
||||
@ -713,10 +695,8 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
@ -728,7 +708,7 @@
|
||||
" [(2, 5), (2, 5), (3, 4), (3, 4), (3, 4)]]"
|
||||
]
|
||||
},
|
||||
"execution_count": 21,
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@ -750,15 +730,13 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"It would be nicer to have a graphical display of colored rectangles. I will define the function `show` which displays a grid as colored rectangles, by calling upon `html_table`, which formats any grid into HTML text."
|
||||
"It would be nicer to have a graphical display of colored rectangles. I will define the function `show` which displays a grid as colored rectangles, by calling upon `html_table`, which formats any grid into HTML text. (*Note:* I used the deprecated `bgcolor` attribute of HTML, rather than CSS styles, because Github is conservative in the javascript and even CSS that it allows, and wouldn't display colored styles.)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"execution_count": 23,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from IPython.display import HTML, display, clear_output\n",
|
||||
@ -769,36 +747,35 @@
|
||||
" display(html_table(grid, colored_cell))\n",
|
||||
" \n",
|
||||
"def html_table(grid, cell_function='<td>{}'.format):\n",
|
||||
" \"Return an HTML <table>, where each cell's contents comes from calling cell_function(grid[y][x])\"\n",
|
||||
" \"\"\"Return an HTML <table>, where each cell's contents comes from calling \n",
|
||||
" cell_function(grid[y][x])\"\"\"\n",
|
||||
" return HTML('<table>{}</table>'\n",
|
||||
" .format(cat('\\n<tr>' + cat(map(cell_function, row)) \n",
|
||||
" for row in grid)))\n",
|
||||
"\n",
|
||||
"def colored_cell(rect): \n",
|
||||
" x, y = sorted(rect)\n",
|
||||
" return '<td style=\"background-color:{}\">{}{}'.format(colors[x], x%10, y%10)\n",
|
||||
" return '<td bgcolor={}>{}{}'.format(colors[x], x%10, y%10)\n",
|
||||
"\n",
|
||||
"colors = 'lightgrey yellow plum chartreuse cyan coral red olive slateblue lightgrey wheat'.split()\n",
|
||||
"colors = 'lightgrey yellow plum lime cyan coral red olive slateblue wheat'.split()\n",
|
||||
"\n",
|
||||
"cat = ''.join"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"execution_count": 24,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<table>\n",
|
||||
"<tr><td style=\"background-color:plum\">25<td style=\"background-color:plum\">25<td style=\"background-color:yellow\">13<td style=\"background-color:yellow\">13<td style=\"background-color:yellow\">13\n",
|
||||
"<tr><td style=\"background-color:plum\">25<td style=\"background-color:plum\">25<td style=\"background-color:chartreuse\">34<td style=\"background-color:chartreuse\">34<td style=\"background-color:chartreuse\">34\n",
|
||||
"<tr><td style=\"background-color:plum\">25<td style=\"background-color:plum\">25<td style=\"background-color:chartreuse\">34<td style=\"background-color:chartreuse\">34<td style=\"background-color:chartreuse\">34\n",
|
||||
"<tr><td style=\"background-color:plum\">25<td style=\"background-color:plum\">25<td style=\"background-color:chartreuse\">34<td style=\"background-color:chartreuse\">34<td style=\"background-color:chartreuse\">34\n",
|
||||
"<tr><td style=\"background-color:plum\">25<td style=\"background-color:plum\">25<td style=\"background-color:chartreuse\">34<td style=\"background-color:chartreuse\">34<td style=\"background-color:chartreuse\">34</table>"
|
||||
"<tr><td bgcolor=plum>25<td bgcolor=plum>25<td bgcolor=yellow>13<td bgcolor=yellow>13<td bgcolor=yellow>13\n",
|
||||
"<tr><td bgcolor=plum>25<td bgcolor=plum>25<td bgcolor=lime>34<td bgcolor=lime>34<td bgcolor=lime>34\n",
|
||||
"<tr><td bgcolor=plum>25<td bgcolor=plum>25<td bgcolor=lime>34<td bgcolor=lime>34<td bgcolor=lime>34\n",
|
||||
"<tr><td bgcolor=plum>25<td bgcolor=plum>25<td bgcolor=lime>34<td bgcolor=lime>34<td bgcolor=lime>34\n",
|
||||
"<tr><td bgcolor=plum>25<td bgcolor=plum>25<td bgcolor=lime>34<td bgcolor=lime>34<td bgcolor=lime>34</table>"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
@ -822,28 +799,26 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"execution_count": 25,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<table>\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89<td style=\"background-color:slateblue\">89\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:yellow\">12<td style=\"background-color:yellow\">12<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46\n",
|
||||
"<tr><td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46\n",
|
||||
"<tr><td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46\n",
|
||||
"<tr><td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:chartreuse\">37<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46<td style=\"background-color:cyan\">46</table>"
|
||||
"<tr><td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50\n",
|
||||
"<tr><td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50\n",
|
||||
"<tr><td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50\n",
|
||||
"<tr><td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50\n",
|
||||
"<tr><td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50\n",
|
||||
"<tr><td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50\n",
|
||||
"<tr><td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50\n",
|
||||
"<tr><td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50\n",
|
||||
"<tr><td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=slateblue>89<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50\n",
|
||||
"<tr><td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=yellow>12<td bgcolor=yellow>12<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50\n",
|
||||
"<tr><td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=lime>37<td bgcolor=lime>37<td bgcolor=lime>37<td bgcolor=lime>37<td bgcolor=lime>37<td bgcolor=lime>37<td bgcolor=lime>37\n",
|
||||
"<tr><td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=lime>37<td bgcolor=lime>37<td bgcolor=lime>37<td bgcolor=lime>37<td bgcolor=lime>37<td bgcolor=lime>37<td bgcolor=lime>37\n",
|
||||
"<tr><td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=cyan>46<td bgcolor=lime>37<td bgcolor=lime>37<td bgcolor=lime>37<td bgcolor=lime>37<td bgcolor=lime>37<td bgcolor=lime>37<td bgcolor=lime>37</table>"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
@ -856,19 +831,19 @@
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<table>\n",
|
||||
"<tr><td style=\"background-color:cyan\">45<td style=\"background-color:cyan\">45<td style=\"background-color:cyan\">45<td style=\"background-color:cyan\">45<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79\n",
|
||||
"<tr><td style=\"background-color:cyan\">45<td style=\"background-color:cyan\">45<td style=\"background-color:cyan\">45<td style=\"background-color:cyan\">45<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79\n",
|
||||
"<tr><td style=\"background-color:cyan\">45<td style=\"background-color:cyan\">45<td style=\"background-color:cyan\">45<td style=\"background-color:cyan\">45<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79\n",
|
||||
"<tr><td style=\"background-color:cyan\">45<td style=\"background-color:cyan\">45<td style=\"background-color:cyan\">45<td style=\"background-color:cyan\">45<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79\n",
|
||||
"<tr><td style=\"background-color:cyan\">45<td style=\"background-color:cyan\">45<td style=\"background-color:cyan\">45<td style=\"background-color:cyan\">45<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79\n",
|
||||
"<tr><td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:yellow\">12<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79\n",
|
||||
"<tr><td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:yellow\">12<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79<td style=\"background-color:olive\">79\n",
|
||||
"<tr><td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60\n",
|
||||
"<tr><td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60\n",
|
||||
"<tr><td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60\n",
|
||||
"<tr><td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60\n",
|
||||
"<tr><td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60\n",
|
||||
"<tr><td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:chartreuse\">38<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60<td style=\"background-color:red\">60</table>"
|
||||
"<tr><td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60\n",
|
||||
"<tr><td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60\n",
|
||||
"<tr><td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60\n",
|
||||
"<tr><td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60\n",
|
||||
"<tr><td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60\n",
|
||||
"<tr><td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60<td bgcolor=red>60\n",
|
||||
"<tr><td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=yellow>12<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79\n",
|
||||
"<tr><td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=lime>38<td bgcolor=yellow>12<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79\n",
|
||||
"<tr><td bgcolor=cyan>45<td bgcolor=cyan>45<td bgcolor=cyan>45<td bgcolor=cyan>45<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79\n",
|
||||
"<tr><td bgcolor=cyan>45<td bgcolor=cyan>45<td bgcolor=cyan>45<td bgcolor=cyan>45<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79\n",
|
||||
"<tr><td bgcolor=cyan>45<td bgcolor=cyan>45<td bgcolor=cyan>45<td bgcolor=cyan>45<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79\n",
|
||||
"<tr><td bgcolor=cyan>45<td bgcolor=cyan>45<td bgcolor=cyan>45<td bgcolor=cyan>45<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79\n",
|
||||
"<tr><td bgcolor=cyan>45<td bgcolor=cyan>45<td bgcolor=cyan>45<td bgcolor=cyan>45<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79<td bgcolor=olive>79</table>"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
@ -881,17 +856,17 @@
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<table>\n",
|
||||
"<tr><td style=\"background-color:plum\">20<td style=\"background-color:plum\">20<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39\n",
|
||||
"<tr><td style=\"background-color:plum\">20<td style=\"background-color:plum\">20<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39\n",
|
||||
"<tr><td style=\"background-color:plum\">20<td style=\"background-color:plum\">20<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39<td style=\"background-color:chartreuse\">39\n",
|
||||
"<tr><td style=\"background-color:plum\">20<td style=\"background-color:plum\">20<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58\n",
|
||||
"<tr><td style=\"background-color:plum\">20<td style=\"background-color:plum\">20<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58\n",
|
||||
"<tr><td style=\"background-color:plum\">20<td style=\"background-color:plum\">20<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58\n",
|
||||
"<tr><td style=\"background-color:plum\">20<td style=\"background-color:plum\">20<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58\n",
|
||||
"<tr><td style=\"background-color:plum\">20<td style=\"background-color:plum\">20<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58\n",
|
||||
"<tr><td style=\"background-color:plum\">20<td style=\"background-color:plum\">20<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58\n",
|
||||
"<tr><td style=\"background-color:plum\">20<td style=\"background-color:plum\">20<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58\n",
|
||||
"<tr><td style=\"background-color:yellow\">16<td style=\"background-color:yellow\">16<td style=\"background-color:yellow\">16<td style=\"background-color:yellow\">16<td style=\"background-color:yellow\">16<td style=\"background-color:yellow\">16<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58<td style=\"background-color:coral\">58</table>"
|
||||
"<tr><td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58\n",
|
||||
"<tr><td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58\n",
|
||||
"<tr><td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58\n",
|
||||
"<tr><td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58\n",
|
||||
"<tr><td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58<td bgcolor=coral>58\n",
|
||||
"<tr><td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=yellow>16\n",
|
||||
"<tr><td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=yellow>16\n",
|
||||
"<tr><td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=yellow>16\n",
|
||||
"<tr><td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=lime>39<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=yellow>16\n",
|
||||
"<tr><td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=yellow>16\n",
|
||||
"<tr><td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=plum>20<td bgcolor=yellow>16</table>"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
@ -904,17 +879,17 @@
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<table>\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:chartreuse\">36<td style=\"background-color:chartreuse\">36<td style=\"background-color:chartreuse\">36<td style=\"background-color:chartreuse\">36<td style=\"background-color:chartreuse\">36<td style=\"background-color:chartreuse\">36\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:chartreuse\">36<td style=\"background-color:chartreuse\">36<td style=\"background-color:chartreuse\">36<td style=\"background-color:chartreuse\">36<td style=\"background-color:chartreuse\">36<td style=\"background-color:chartreuse\">36\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:chartreuse\">36<td style=\"background-color:chartreuse\">36<td style=\"background-color:chartreuse\">36<td style=\"background-color:chartreuse\">36<td style=\"background-color:chartreuse\">36<td style=\"background-color:chartreuse\">36\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:plum\">28<td style=\"background-color:plum\">28\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:plum\">28<td style=\"background-color:plum\">28\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:plum\">28<td style=\"background-color:plum\">28\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:plum\">28<td style=\"background-color:plum\">28\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:plum\">28<td style=\"background-color:plum\">28\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:plum\">28<td style=\"background-color:plum\">28\n",
|
||||
"<tr><td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:coral\">50<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:cyan\">47<td style=\"background-color:plum\">28<td style=\"background-color:plum\">28\n",
|
||||
"<tr><td style=\"background-color:yellow\">19<td style=\"background-color:yellow\">19<td style=\"background-color:yellow\">19<td style=\"background-color:yellow\">19<td style=\"background-color:yellow\">19<td style=\"background-color:yellow\">19<td style=\"background-color:yellow\">19<td style=\"background-color:yellow\">19<td style=\"background-color:yellow\">19<td style=\"background-color:plum\">28<td style=\"background-color:plum\">28</table>"
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=plum>28<td bgcolor=plum>28\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=plum>28<td bgcolor=plum>28\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=plum>28<td bgcolor=plum>28\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=plum>28<td bgcolor=plum>28\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=plum>28<td bgcolor=plum>28\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=plum>28<td bgcolor=plum>28\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=plum>28<td bgcolor=plum>28\n",
|
||||
"<tr><td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=plum>28<td bgcolor=plum>28</table>"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
@ -928,7 +903,7 @@
|
||||
"def pack_square(rectangles):\n",
|
||||
" \"Pack rectangles into a square of appropriate size, if possible.\"\n",
|
||||
" A = total_area(rectangles)\n",
|
||||
" if is_perfect_square(A):\n",
|
||||
" if A in perfect_squares:\n",
|
||||
" return pack(rectangles, Square(int(A ** 0.5)))\n",
|
||||
"\n",
|
||||
"for s in all_sets:\n",
|
||||
@ -946,317 +921,76 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Now For Something Completely Different: Cryptarithmetic"
|
||||
"# Animated Colored Rectangles"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"On April 28, Gary Antonik had another [Numberplay column](http://wordplay.blogs.nytimes.com/2014/04/28/num/) that quotes my friend Bill Gosper. (Gosper often presents more advanced puzzles in the [math-fun](http://mailman.xmission.com/cgi-bin/mailman/listinfo/math-fun) mailing list.) This puzzle was:\n",
|
||||
"\n",
|
||||
">For the expression N U M + B E R = P L A Y,\n",
|
||||
"\n",
|
||||
"> Which distinct numerals (each different) can be substituted for letters to make a valid expression?\n",
|
||||
"\n",
|
||||
"> How many solutions are there?"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"I tackled this type of problem (known as a [cryptarithmetic](http://mathworld.wolfram.com/Cryptarithmetic.html) or [alphametic](http://mathworld.wolfram.com/Alphametic.html) problem) in my Udacity class [CS 212](https://www.udacity.com/wiki/cs212/unit-2#cryptarithmetic). My approach was simple: try all permutations of digits replacing letters (that should be quick and easy—there can be at most 10 factorial or 3.6 million permutations), then for each one, use Python's `eval` function to see if the resulting string is a true expression. The basic idea is simple, but there are complications to worry about:\n",
|
||||
"\n",
|
||||
"1. Math uses `=` and Python uses `==` for equality; we'll allow either one.\n",
|
||||
"2. The more detailed rules for these problems say that a number with a leading zero (like `012`) is illegal (but `0` itself is ok).\n",
|
||||
"3. By default, Python thinks that 3/2 is 1, because integer division rounds down. But we can import \"proper\" division from the future.\n",
|
||||
"4. If we try to eval an expression like 1/0, Python raises an error; we'll have to handle it."
|
||||
"It is gratifying to see the final results, and have the computation be so fast, but I'd like to get a better understanding of the algorithm. I can visualize the process by *animating* the search that `pack` does: on every recursive call to `pack`, I can show the grid, and then pause briefly. I do that by redefining `pack`; the only change is the line starting `if pause:`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 29,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"execution_count": 26,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from __future__ import division\n",
|
||||
"import itertools\n",
|
||||
"import re\n",
|
||||
"import time\n",
|
||||
"\n",
|
||||
"def solve_all(formula):\n",
|
||||
" \"\"\"Given a formula like 'NUM + BER = PLAY', fill in digits to solve it.\n",
|
||||
" Input formula is a string; generate each digit-filled-in string.\"\"\"\n",
|
||||
" formula = formula.replace(' = ', ' == ')\n",
|
||||
" for exp in replace_letters(formula):\n",
|
||||
" if valid(exp):\n",
|
||||
" yield exp\n",
|
||||
"\n",
|
||||
"def replace_letters(formula):\n",
|
||||
" \"Generate all possible replacements of letters with digits in formula.\"\n",
|
||||
" letters = ''.join(set(re.findall('[A-Z]', formula)))\n",
|
||||
" for digits in itertools.permutations('1234567890', len(letters)):\n",
|
||||
" trans = str.maketrans(letters, ''.join(digits))\n",
|
||||
" yield formula.translate(trans)\n",
|
||||
"\n",
|
||||
"def valid(exp):\n",
|
||||
" \"Expression is valid iff it has no numbers with leading zero, and evals true.\"\n",
|
||||
" try:\n",
|
||||
" return not leading_zero(exp) and eval(exp)\n",
|
||||
" except ArithmeticError:\n",
|
||||
" return False\n",
|
||||
" \n",
|
||||
"leading_zero = re.compile(r'\\b0[0-9]').search"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 30,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'352 + 746 == 1098'"
|
||||
]
|
||||
},
|
||||
"execution_count": 30,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"next(solve_all('NUM + BER = PLAY'))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 31,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"CPU times: user 41.4 s, sys: 452 ms, total: 41.9 s\n",
|
||||
"Wall time: 44.2 s\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"96"
|
||||
]
|
||||
},
|
||||
"execution_count": 31,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%time len(list(solve_all('NUM + BER = PLAY')))"
|
||||
"def pack(rectangles, grid, pause=None):\n",
|
||||
" \"\"\"Find a way to pack all rectangles onto grid and return the packed grid,\n",
|
||||
" or return None if not possible.\"\"\"\n",
|
||||
" if pause: (clear_output(), show(grid), time.sleep(pause))\n",
|
||||
" if not rectangles:\n",
|
||||
" return grid \n",
|
||||
" pos = first_empty_cell(grid)\n",
|
||||
" if grid and pos:\n",
|
||||
" for (rectangles2, grid2) in rectangle_placements(rectangles, grid, pos):\n",
|
||||
" solution = pack(rectangles2, grid2, pause)\n",
|
||||
" if solution:\n",
|
||||
" return solution"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"So there are 96 solutions, but it is a bit slow to find them all. For each of the permutations of digits, we substitute the digits for letters, and then call `eval(exp)` on the resulting string. The majority of time is spent inside `eval`. But the expression is basically the same each time; we could save a lot of work if we eval the expression just once, yielding a Python function, and then call that function once for each permutation of digits. In other words, we want to take an expression such as\n",
|
||||
"\n",
|
||||
" \"NUM + BER == PLAY\"\n",
|
||||
" \n",
|
||||
"and transform it into the Python function\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" lambda A,B,E,M,L,N,P,R,U,Y: (100*N+10*U+M) + (100*B+10*E+R) == (1000*P+100*L+10*A+Y)\n",
|
||||
" \n",
|
||||
"Actually that's not quite right. The rules are that the first letter of each multi-letter word (the \"N\" in \"NEW\"; the \"B\" in \"BER\"; and the \"P\" in \"PLAY\") cannot be a zero. So the function should be:\n",
|
||||
"\n",
|
||||
" lambda A,B,E,M,L,N,P,R,U,Y: N and B and P and (100*N+10*U+M) + (100*B+10*E+R) == (1000*P+100*L+10*A+Y)\n",
|
||||
"\n",
|
||||
"In my Udacity class I show a solution to this problem; you can [go there](https://www.udacity.com/wiki/cs212/unit-2#rethinking-eval) or see it here. Here is the code to compile a formula (or expression) into a Python function: "
|
||||
"If you are running this in a live IPython notebook (not in nbviewer), you can see for yourself by re-running this cell:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 32,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def compile_formula(formula, verbose=False):\n",
|
||||
" \"\"\"Compile formula into a function. Also return letters found, as a str,\n",
|
||||
" in same order as parms of function. For example, 'YOU == ME**2' returns\n",
|
||||
" (lambda Y,M,E,U,O: Y and M and ((100*Y+10*O+U) == (10*M+E)**2)), 'YMEUO'\"\"\"\n",
|
||||
" formula = formula.replace(' = ', ' == ')\n",
|
||||
" letters = ''.join(set(re.findall('[A-Z]', formula)))\n",
|
||||
" firstletters = set(re.findall(r'\\b([A-Z])[A-Z]', formula))\n",
|
||||
" body = re.sub('[A-Z]+', compile_word, formula)\n",
|
||||
" if firstletters:\n",
|
||||
" body = '{} and ({})'.format(' and '.join(firstletters), body)\n",
|
||||
" fn = 'lambda {}: {}'.format(','.join(letters), body)\n",
|
||||
" if verbose: print(fn)\n",
|
||||
" return eval(fn), letters\n",
|
||||
"\n",
|
||||
"def compile_word(matchobj):\n",
|
||||
" \"Compile the word 'YOU' as '(100*Y + 10*O + U)'.\"\n",
|
||||
" word = matchobj.group()\n",
|
||||
" terms = reversed([mult(10**i, L) for (i, L) in enumerate(reversed(word))])\n",
|
||||
" return '(' + '+'.join(terms) + ')'\n",
|
||||
"\n",
|
||||
"def mult(factor, var): return var if factor == 1 else str(factor) + '*' + var"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 33,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"lambda O,Y,E,U,M: M and Y and ((100*Y+10*O+U) == (10*M+E)**2)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(<function __main__.<lambda>>, 'OYEUM')"
|
||||
]
|
||||
},
|
||||
"execution_count": 33,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"compile_formula(\"YOU == ME**2\", verbose=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 34,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"lambda M,L,P,R,Y,A,E,N,U,B: P and B and N and ((100*N+10*U+M) + (100*B+10*E+R) == (1000*P+100*L+10*A+Y))\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(<function __main__.<lambda>>, 'MLPRYAENUB')"
|
||||
]
|
||||
},
|
||||
"execution_count": 34,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"compile_formula(\"NUM + BER == PLAY\", verbose=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 35,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def faster_solve_all(formula):\n",
|
||||
" \"\"\"Given a formula like 'ODD + ODD == EVEN', fill in digits to solve it.\n",
|
||||
" Input formula is a string; output is a digit-filled-in string or None.\n",
|
||||
" Capital letters are variables. This version precompiles the formula; only one eval per formula.\"\"\"\n",
|
||||
" fn, letters = compile_formula(formula)\n",
|
||||
" for digits in itertools.permutations((1,2,3,4,5,6,7,8,9,0), len(letters)):\n",
|
||||
" try:\n",
|
||||
" if fn(*digits):\n",
|
||||
" yield replace_all(formula, letters, digits)\n",
|
||||
" except ZeroDivisionError: \n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
"def replace_all(text, olds, news):\n",
|
||||
" \"Replace each occurrence of each old in text with the corresponding new.\"\n",
|
||||
" # E.g. replace_all('A + B', ['A', 'B'], [1, 2]) == '1 + 2'\n",
|
||||
" for (old, new) in zip(olds, news):\n",
|
||||
" text = text.replace(str(old), str(new))\n",
|
||||
" return text"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 36,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'352 + 746 = 1098'"
|
||||
]
|
||||
},
|
||||
"execution_count": 36,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"next(faster_solve_all('NUM + BER = PLAY'))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 37,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"CPU times: user 2.57 s, sys: 31.5 ms, total: 2.6 s\n",
|
||||
"Wall time: 2.7 s\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"96"
|
||||
]
|
||||
},
|
||||
"execution_count": 37,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%time len(list(faster_solve_all('NUM + BER = PLAY')))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"execution_count": 27,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<table>\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36<td bgcolor=lime>36\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=plum>28<td bgcolor=plum>28\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=plum>28<td bgcolor=plum>28\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=plum>28<td bgcolor=plum>28\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=plum>28<td bgcolor=plum>28\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=plum>28<td bgcolor=plum>28\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=plum>28<td bgcolor=plum>28\n",
|
||||
"<tr><td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=coral>50<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=cyan>47<td bgcolor=plum>28<td bgcolor=plum>28\n",
|
||||
"<tr><td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=yellow>19<td bgcolor=plum>28<td bgcolor=plum>28</table>"
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.HTML object>"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"We get the same answer, but 15 times faster."
|
||||
"pack({(5, 10), (3, 6), (4, 7), (2, 8), (1, 9)}, Square(11), 1);"
|
||||
]
|
||||
}
|
||||
],
|
||||
@ -1276,7 +1010,7 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.0"
|
||||
"version": "3.7.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
Loading…
Reference in New Issue
Block a user