Add files via upload

This commit is contained in:
Peter Norvig 2018-04-13 15:05:11 -07:00 committed by GitHub
parent e78bd1f692
commit 8c2e90f6ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -13,7 +13,7 @@
"source": [ "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", "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", "\n",
"><i>Say youre 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 youre 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", ">\n",
">1. How many different sets of five rectangles are possible?\n", ">1. How many different sets of five rectangles are possible?\n",
">\n", ">\n",
@ -21,7 +21,7 @@
">\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", ">\n",
">4. Which sets of rectangles may be assembled to form a square?</i>\n", ">4. Which sets of rectangles may be assembled to form a square?\n",
"\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." "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."
] ]
@ -645,7 +645,7 @@
"\n", "\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", "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", "\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! &times; 2<sup>5</sup> = 3840 combinations. Since 3840 &lt; 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! &times; 2<sup>5</sup> = 3840 combinations. Since 3840 &lt; 100,000, I'll go with Way 2. Here is a more precise description:\n",
"\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. " "> 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. "
] ]
@ -669,7 +669,7 @@
" return solution\n", " return solution\n",
"\n", "\n",
"def rectangle_placements(rectangles, grid, pos):\n", "def rectangle_placements(rectangles, grid, pos):\n",
" \"Yield all (rectangles2, grid2) pairs that are the result of placing any rectangle at pos on grid.\"\n", " \"Yield all (rect, grid) pairs that result from placing a rectangle at pos on grid.\"\n",
" for (w, h) in rectangles:\n", " for (w, h) in rectangles:\n",
" for rect in [(w, h), (h, w)]:\n", " for rect in [(w, h), (h, w)]:\n",
" grid2 = place_rectangle_at(rect, grid, pos)\n", " grid2 = place_rectangle_at(rect, grid, pos)\n",
@ -728,7 +728,7 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "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:* Github is conservative in the javascript and even CSS that it allows, so if you don't see colors in the grids below, look at this file on [nbviewer](https://nbviewer.jupyter.org/github/norvig/pytudes/blob/master/ipynb/Golomb-Puzzle.ipynb); same file, but the rendering will definitely show the colors.)"
] ]
}, },
{ {
@ -745,7 +745,8 @@
" display(html_table(grid, colored_cell))\n", " display(html_table(grid, colored_cell))\n",
" \n", " \n",
"def html_table(grid, cell_function='<td>{}'.format):\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", " return HTML('<table>{}</table>'\n",
" .format(cat('\\n<tr>' + cat(map(cell_function, row)) \n", " .format(cat('\\n<tr>' + cat(map(cell_function, row)) \n",
" for row in grid)))\n", " for row in grid)))\n",
@ -754,7 +755,8 @@
" x, y = sorted(rect)\n", " x, y = sorted(rect)\n",
" return '<td style=\"background-color:{}\">{}{}'.format(colors[x], x%10, y%10)\n", " return '<td style=\"background-color:{}\">{}{}'.format(colors[x], x%10, y%10)\n",
"\n", "\n",
"colors = 'lightgrey yellow plum chartreuse cyan coral red olive slateblue lightgrey wheat'.split()\n", "colors = ('lightgrey yellow plum chartreuse cyan coral red olive slateblue lightgrey wheat'\n",
" .split())\n",
"\n", "\n",
"cat = ''.join" "cat = ''.join"
] ]
@ -931,17 +933,15 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 26, "execution_count": 26,
"metadata": { "metadata": {},
"collapsed": true
},
"outputs": [], "outputs": [],
"source": [ "source": [
"import time\n", "import time\n",
"\n", "\n",
"def pack(rectangles, grid, animation=False): \n", "def pack(rectangles, grid, animation=False): \n",
" \"\"\"Find a way to pack all rectangles onto grid and return the packed grid,\n", " \"\"\"Find a way to pack all rectangles onto grid and return the packed grid,\n",
" or return None if not possible. \n", " or return None if not possible. Pause `animation` seconds between \n",
" Pause `animation` seconds between displaying each rectangle placement if `animation` is not false.\"\"\"\n", " displaying each rectangle placement if `animation` is not false.\"\"\"\n",
" if animation: \n", " if animation: \n",
" clear_output()\n", " clear_output()\n",
" show(grid)\n", " show(grid)\n",
@ -1073,7 +1073,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"'857 + 349 == 1206'" "'325 + 764 == 1089'"
] ]
}, },
"execution_count": 29, "execution_count": 29,
@ -1094,8 +1094,8 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"CPU times: user 29 s, sys: 42.2 ms, total: 29.1 s\n", "CPU times: user 30 s, sys: 56.5 ms, total: 30 s\n",
"Wall time: 29.1 s\n" "Wall time: 30.1 s\n"
] ]
}, },
{ {
@ -1136,9 +1136,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 31, "execution_count": 31,
"metadata": { "metadata": {},
"collapsed": true
},
"outputs": [], "outputs": [],
"source": [ "source": [
"def compile_formula(formula, verbose=False):\n", "def compile_formula(formula, verbose=False):\n",
@ -1173,13 +1171,13 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"lambda Y,M,E,O,U: Y and M and ((100*Y+10*O+U) == (10*M+E)**2)\n" "lambda M,U,E,O,Y: M and Y and ((100*Y+10*O+U) == (10*M+E)**2)\n"
] ]
}, },
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"(<function __main__.<lambda>>, 'YMEOU')" "(<function __main__.<lambda>>, 'MUEOY')"
] ]
}, },
"execution_count": 32, "execution_count": 32,
@ -1200,13 +1198,13 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"lambda L,A,Y,P,M,E,R,U,B,N: P and B and N and ((100*N+10*U+M) + (100*B+10*E+R) == (1000*P+100*L+10*A+Y))\n" "lambda U,A,R,E,L,Y,N,B,M,P: B and N and P and ((100*N+10*U+M) + (100*B+10*E+R) == (1000*P+100*L+10*A+Y))\n"
] ]
}, },
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"(<function __main__.<lambda>>, 'LAYPMERUBN')" "(<function __main__.<lambda>>, 'UARELYNBMP')"
] ]
}, },
"execution_count": 33, "execution_count": 33,
@ -1221,15 +1219,14 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 34, "execution_count": 34,
"metadata": { "metadata": {},
"collapsed": true
},
"outputs": [], "outputs": [],
"source": [ "source": [
"def faster_solve_all(formula):\n", "def faster_solve_all(formula):\n",
" \"\"\"Given a formula like 'ODD + ODD == EVEN', fill in digits to solve it.\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", " 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", " Capital letters are variables. This version precompiles the formula; \n",
" only one eval per formula.\"\"\"\n",
" fn, letters = compile_formula(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", " for digits in itertools.permutations((1,2,3,4,5,6,7,8,9,0), len(letters)):\n",
" try:\n", " try:\n",
@ -1239,7 +1236,7 @@
" pass\n", " pass\n",
" \n", " \n",
"def replace_all(text, olds, news):\n", "def replace_all(text, olds, news):\n",
" \"Replace each occurrence of each old in text with the corresponding new.\"\n", " \"Replace each occurence of each old in text with the corresponding new.\"\n",
" # E.g. replace_all('A + B', ['A', 'B'], [1, 2]) == '1 + 2'\n", " # E.g. replace_all('A + B', ['A', 'B'], [1, 2]) == '1 + 2'\n",
" for (old, new) in zip(olds, news):\n", " for (old, new) in zip(olds, news):\n",
" text = text.replace(str(old), str(new))\n", " text = text.replace(str(old), str(new))\n",
@ -1254,7 +1251,7 @@
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"'857 + 349 = 1206'" "'325 + 764 = 1089'"
] ]
}, },
"execution_count": 35, "execution_count": 35,
@ -1275,8 +1272,8 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"CPU times: user 1.75 s, sys: 3.29 ms, total: 1.76 s\n", "CPU times: user 1.77 s, sys: 4.05 ms, total: 1.77 s\n",
"Wall time: 1.76 s\n" "Wall time: 1.77 s\n"
] ]
}, },
{ {