diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9c646cd --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ + +### JupyterNotebook ### +.ipynb_checkpoints +*/.ipynb_checkpoints/* + +# To remove previous ipynb_checkpoints +# git rm -r .ipynb_checkpoints/ \ No newline at end of file diff --git a/Solving a Sudoku with AI - Lessons Problem.ipynb b/Solving a Sudoku with AI - Lessons Problem.ipynb index 7c70dd1..e4f28bc 100644 --- a/Solving a Sudoku with AI - Lessons Problem.ipynb +++ b/Solving a Sudoku with AI - Lessons Problem.ipynb @@ -40,11 +40,27 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + ". . 3 |. 2 . |6 . . \n", + "9 . . |3 . 5 |. . 1 \n", + ". . 1 |8 . 6 |4 . . \n", + "------+------+------\n", + ". . 8 |1 . 2 |9 . . \n", + "7 . . |. . . |. . 8 \n", + ". . 6 |7 . 8 |2 . . \n", + "------+------+------\n", + ". . 2 |6 . 9 |5 . . \n", + "8 . . |2 . 3 |. . 9 \n", + ". . 5 |. 1 . |3 . . \n" + ] + } + ], "source": [ "'''\n", "Exercise1: Encoding the Board\n", @@ -123,15 +139,17 @@ " # box (as a string) or '.' if the box has no value\n", " # assigned yet.\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", - " \n", + " txt = []\n", + " for c in grid:\n", + " txt.append(c) \n", + " \n", + " assert len(txt) == 81\n", + " x = zip(boxes, txt)\n", + " return dict(x)\n", + " ''''''\n", "#3. Test function.py ---------------------------- \n", "# print(grid_values('..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..'))\n", "\n", @@ -162,7 +180,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ @@ -172,11 +190,27 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "123456789 123456789 3 |123456789 2 123456789 | 6 123456789 123456789 \n", + " 9 123456789 123456789 | 3 123456789 5 |123456789 123456789 1 \n", + "123456789 123456789 1 | 8 123456789 6 | 4 123456789 123456789 \n", + "------------------------------+------------------------------+------------------------------\n", + "123456789 123456789 8 | 1 123456789 2 | 9 123456789 123456789 \n", + " 7 123456789 123456789 |123456789 123456789 123456789 |123456789 123456789 8 \n", + "123456789 123456789 6 | 7 123456789 8 | 2 123456789 123456789 \n", + "------------------------------+------------------------------+------------------------------\n", + "123456789 123456789 2 | 6 123456789 9 | 5 123456789 123456789 \n", + " 8 123456789 123456789 | 2 123456789 3 |123456789 123456789 9 \n", + "123456789 123456789 5 |123456789 1 123456789 | 3 123456789 123456789 \n" + ] + } + ], "source": [ "'''\n", "Exercise2.1: Improved grid_values()\n", @@ -265,14 +299,18 @@ " - values: Value in corresponding box, e.g. '8', or '123456789' if it is empty.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", + " \n", + " txt = []\n", + " for ch in grid:\n", + " if ch == '.':\n", + " ch = '123456789'\n", + " txt.append(ch)\n", + " \n", + " assert len(txt) == 81\n", + " return dict(zip(boxes, txt))\n", "\n", "#3. Test function.py ---------------------------- \n", "display(grid_values('..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..'))" @@ -280,11 +318,42 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The original Sudoku board is **********************************************\n", + "123456789 123456789 3 |123456789 2 123456789 | 6 123456789 123456789 \n", + " 9 123456789 123456789 | 3 123456789 5 |123456789 123456789 1 \n", + "123456789 123456789 1 | 8 123456789 6 | 4 123456789 123456789 \n", + "------------------------------+------------------------------+------------------------------\n", + "123456789 123456789 8 | 1 123456789 2 | 9 123456789 123456789 \n", + " 7 123456789 123456789 |123456789 123456789 123456789 |123456789 123456789 8 \n", + "123456789 123456789 6 | 7 123456789 8 | 2 123456789 123456789 \n", + "------------------------------+------------------------------+------------------------------\n", + "123456789 123456789 2 | 6 123456789 9 | 5 123456789 123456789 \n", + " 8 123456789 123456789 | 2 123456789 3 |123456789 123456789 9 \n", + "123456789 123456789 5 |123456789 1 123456789 | 3 123456789 123456789 \n", + "\n", + "\n", + "After implement eliminate(values) method **********************************\n", + " 45 4578 3 | 9 2 14 | 6 5789 57 \n", + " 9 24678 47 | 3 47 5 | 78 278 1 \n", + " 25 257 1 | 8 79 6 | 4 23579 2357 \n", + "---------------------+---------------------+---------------------\n", + " 345 345 8 | 1 3456 2 | 9 34567 34567 \n", + " 7 123459 49 | 59 34569 4 | 1 13456 8 \n", + " 1345 13459 6 | 7 3459 8 | 2 1345 345 \n", + "---------------------+---------------------+---------------------\n", + " 134 1347 2 | 6 8 9 | 5 1478 47 \n", + " 8 1467 47 | 2 5 3 | 17 1467 9 \n", + " 6 69 5 | 4 1 7 | 3 268 26 \n" + ] + } + ], "source": [ "'''\n", "Exercise2.2: implement eliminate()\n", @@ -350,14 +419,17 @@ " - values: Value in corresponding box, e.g. '8', or '123456789' if it is empty.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", + " txt = []\n", + " for ch in grid:\n", + " if ch == '.':\n", + " ch = '123456789'\n", + " txt.append(ch)\n", + " \n", + " assert len(txt) == 81\n", + " return dict(zip(boxes, txt))\n", "\n", "#2. function.py ----------------------------\n", "# 2.1 implement eliminate(values)\n", @@ -374,15 +446,16 @@ " Resulting Sudoku in dictionary form after eliminating values.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", - "\n", + " for key, val in values.items():\n", + " if(len(val) == 1):\n", + " for key_peer in peers[key]:\n", + " values[key_peer] = values[key_peer].replace(val, '')\n", + " \n", + " return values\n", + " \n", "#3. Test utils.py ---------------------------- \n", "values = grid_values('..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..')\n", "print(\"The original Sudoku board is **********************************************\")\n", @@ -418,7 +491,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ @@ -428,11 +501,56 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The original Sudoku board is **********************************************\n", + "123456789 123456789 3 |123456789 2 123456789 | 6 123456789 123456789 \n", + " 9 123456789 123456789 | 3 123456789 5 |123456789 123456789 1 \n", + "123456789 123456789 1 | 8 123456789 6 | 4 123456789 123456789 \n", + "------------------------------+------------------------------+------------------------------\n", + "123456789 123456789 8 | 1 123456789 2 | 9 123456789 123456789 \n", + " 7 123456789 123456789 |123456789 123456789 123456789 |123456789 123456789 8 \n", + "123456789 123456789 6 | 7 123456789 8 | 2 123456789 123456789 \n", + "------------------------------+------------------------------+------------------------------\n", + "123456789 123456789 2 | 6 123456789 9 | 5 123456789 123456789 \n", + " 8 123456789 123456789 | 2 123456789 3 |123456789 123456789 9 \n", + "123456789 123456789 5 |123456789 1 123456789 | 3 123456789 123456789 \n", + "\n", + "\n", + "After implement eliminate(values) method **********************************\n", + " 45 4578 3 | 9 2 14 | 6 5789 57 \n", + " 9 24678 47 | 3 47 5 | 78 278 1 \n", + " 25 257 1 | 8 79 6 | 4 23579 2357 \n", + "---------------------+---------------------+---------------------\n", + " 345 345 8 | 1 3456 2 | 9 34567 34567 \n", + " 7 123459 49 | 59 34569 4 | 1 13456 8 \n", + " 1345 13459 6 | 7 3459 8 | 2 1345 345 \n", + "---------------------+---------------------+---------------------\n", + " 134 1347 2 | 6 8 9 | 5 1478 47 \n", + " 8 1467 47 | 2 5 3 | 17 1467 9 \n", + " 6 69 5 | 4 1 7 | 3 268 26 \n", + "\n", + "\n", + "After implement only_choice(values) method **********************************\n", + " 45 4578 3 | 9 2 1 | 6 5789 57 \n", + " 9 6 47 | 3 47 5 | 8 278 1 \n", + " 2 257 1 | 8 79 6 | 4 23579 2357 \n", + "------------------+------------------+------------------\n", + " 345 345 8 | 1 3456 2 | 9 34567 34567 \n", + " 7 2 9 | 5 34569 4 | 1 13456 8 \n", + " 1345 13459 6 | 7 3459 8 | 2 1345 345 \n", + "------------------+------------------+------------------\n", + " 134 1347 2 | 6 8 9 | 5 1478 47 \n", + " 8 1467 47 | 2 5 3 | 17 1467 9 \n", + " 6 9 5 | 4 1 7 | 3 8 26 \n" + ] + } + ], "source": [ "'''\n", "Exercise3.1: implement only_choice()\n", @@ -496,14 +614,17 @@ " - values: Value in corresponding box, e.g. '8', or '123456789' if it is empty.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", + " txt = []\n", + " for ch in grid:\n", + " if ch == '.':\n", + " ch = '123456789'\n", + " txt.append(ch)\n", + " \n", + " assert len(txt) == 81\n", + " return dict(zip(boxes, txt))\n", "\n", "def eliminate(values):\n", " \"\"\"Eliminate values from peers of each box with a single value.\n", @@ -517,15 +638,16 @@ " Resulting Sudoku in dictionary form after eliminating values.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", - "\n", + " for key, val in values.items():\n", + " if(len(val) == 1):\n", + " for key_peer in peers[key]:\n", + " values[key_peer] = values[key_peer].replace(val, '')\n", + " \n", + " return values\n", + " \n", "#2. function.py ----------------------------\n", "# 2.1 implement only_choice(values)\n", "# from utils import *\n", @@ -539,14 +661,17 @@ " Output: Resulting Sudoku in dictionary form after filling in only choices.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", + " vals_out = values.copy()\n", + " \n", + " for unit in unitlist:\n", + " for digit in '123456789':\n", + " dplaces = [box for box in unit if digit in values[box]]\n", + " if len(dplaces) == 1:\n", + " vals_out[dplaces[0]] = digit\n", + " return vals_out\n", "\n", "#3. Test utils.py ---------------------------- \n", "values = grid_values('..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..')\n", @@ -601,7 +726,7 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ @@ -611,11 +736,42 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The original Sudoku board is **********************************************\n", + "123456789 123456789 3 |123456789 2 123456789 | 6 123456789 123456789 \n", + " 9 123456789 123456789 | 3 123456789 5 |123456789 123456789 1 \n", + "123456789 123456789 1 | 8 123456789 6 | 4 123456789 123456789 \n", + "------------------------------+------------------------------+------------------------------\n", + "123456789 123456789 8 | 1 123456789 2 | 9 123456789 123456789 \n", + " 7 123456789 123456789 |123456789 123456789 123456789 |123456789 123456789 8 \n", + "123456789 123456789 6 | 7 123456789 8 | 2 123456789 123456789 \n", + "------------------------------+------------------------------+------------------------------\n", + "123456789 123456789 2 | 6 123456789 9 | 5 123456789 123456789 \n", + " 8 123456789 123456789 | 2 123456789 3 |123456789 123456789 9 \n", + "123456789 123456789 5 |123456789 1 123456789 | 3 123456789 123456789 \n", + "\n", + "\n", + "After applying constrint propagaton (both eliminate and only_choice strategies)*****************\n", + "4 8 3 |9 2 1 |6 5 7 \n", + "9 6 7 |3 4 5 |8 2 1 \n", + "2 5 1 |8 7 6 |4 9 3 \n", + "------+------+------\n", + "5 4 8 |1 3 2 |9 7 6 \n", + "7 2 9 |5 6 4 |1 3 8 \n", + "1 3 6 |7 9 8 |2 4 5 \n", + "------+------+------\n", + "3 7 2 |6 8 9 |5 1 4 \n", + "8 1 4 |2 5 3 |7 6 9 \n", + "6 9 5 |4 1 7 |3 8 2 \n" + ] + } + ], "source": [ "'''\n", "Exercise4.1: Apply Constraint Propagation to Sudoku problem\n", @@ -685,14 +841,17 @@ " - values: Value in corresponding box, e.g. '8', or '123456789' if it is empty.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", + " txt = []\n", + " for ch in grid:\n", + " if ch == '.':\n", + " ch = '123456789'\n", + " txt.append(ch)\n", + " \n", + " assert len(txt) == 81\n", + " return dict(zip(boxes, txt))\n", "\n", "def eliminate(values):\n", " \"\"\"Eliminate values from peers of each box with a single value.\n", @@ -706,14 +865,15 @@ " Resulting Sudoku in dictionary form after eliminating values.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", + " for key, val in values.items():\n", + " if(len(val) == 1):\n", + " for key_peer in peers[key]:\n", + " values[key_peer] = values[key_peer].replace(val, '')\n", + " \n", + " return values\n", "\n", "def only_choice(values):\n", " \"\"\"Finalize all values that are the only choice for a unit.\n", @@ -725,14 +885,17 @@ " Output: Resulting Sudoku in dictionary form after filling in only choices.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", + " vals_out = values.copy()\n", + " \n", + " for unit in unitlist:\n", + " for digit in '123456789':\n", + " dplaces = [box for box in unit if digit in values[box]]\n", + " if len(dplaces) == 1:\n", + " vals_out[dplaces[0]] = digit\n", + " return vals_out\n", "\n", "#2. function.py ----------------------------\n", "# 2.1 combine the functions eliminate and only_choice to write the function reduce_puzzle\n", @@ -746,15 +909,22 @@ " Output: The resulting sudoku in dictionary form.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", - "\n", + " solved_vals = [box for box in values.keys() if len(values[box]) == 1]\n", + " stalled = False\n", + " while not stalled:\n", + " solved_vals_before = len([box for box in values.keys() if len(values[box]) == 1])\n", + " values = eliminate(values)\n", + " values = only_choice(values)\n", + " solved_vals_after = len([box for box in values.keys() if len(values[box]) == 1])\n", + " stalled = (solved_vals_before == solved_vals_after)\n", + " if len([box for box in values.keys() if len(values[box]) == 0]):\n", + " return False\n", + " \n", + " return values\n", + " \n", "#3. Test utils.py ---------------------------- \n", "values = grid_values('..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..')\n", "print(\"The original Sudoku board is **********************************************\")\n", @@ -788,11 +958,42 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The original Sudoku board is **********************************************\n", + " 4 123456789 123456789 |123456789 123456789 123456789 | 8 123456789 5 \n", + "123456789 3 123456789 |123456789 123456789 123456789 |123456789 123456789 123456789 \n", + "123456789 123456789 123456789 | 7 123456789 123456789 |123456789 123456789 123456789 \n", + "------------------------------+------------------------------+------------------------------\n", + "123456789 2 123456789 |123456789 123456789 123456789 |123456789 6 123456789 \n", + "123456789 123456789 123456789 |123456789 8 123456789 | 4 123456789 123456789 \n", + "123456789 123456789 123456789 |123456789 1 123456789 |123456789 123456789 123456789 \n", + "------------------------------+------------------------------+------------------------------\n", + "123456789 123456789 123456789 | 6 123456789 3 |123456789 7 123456789 \n", + " 5 123456789 123456789 | 2 123456789 123456789 |123456789 123456789 123456789 \n", + " 1 123456789 4 |123456789 123456789 123456789 |123456789 123456789 123456789 \n", + "\n", + "\n", + "After applying constrint propagaton (both eliminate and only_choice strategies)*****************\n", + " 4 1679 12679 | 139 2369 269 | 8 1239 5 \n", + " 26789 3 1256789 | 14589 24569 245689 | 12679 1249 124679 \n", + " 2689 15689 125689 | 7 234569 245689 | 12369 12349 123469 \n", + "------------------------+------------------------+------------------------\n", + " 3789 2 15789 | 3459 34579 4579 | 13579 6 13789 \n", + " 3679 15679 15679 | 359 8 25679 | 4 12359 12379 \n", + " 36789 4 56789 | 359 1 25679 | 23579 23589 23789 \n", + "------------------------+------------------------+------------------------\n", + " 289 89 289 | 6 459 3 | 1259 7 12489 \n", + " 5 6789 3 | 2 479 1 | 69 489 4689 \n", + " 1 6789 4 | 589 579 5789 | 23569 23589 23689 \n" + ] + } + ], "source": [ "'''\n", "Exercise5.1: Try to solve harder sudoku using the same constraint propagation\n", @@ -853,14 +1054,17 @@ " - values: Value in corresponding box, e.g. '8', or '123456789' if it is empty.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", + " txt = []\n", + " for ch in grid:\n", + " if ch == '.':\n", + " ch = '123456789'\n", + " txt.append(ch)\n", + " \n", + " assert len(txt) == 81\n", + " return dict(zip(boxes, txt))\n", "\n", "def eliminate(values):\n", " \"\"\"Eliminate values from peers of each box with a single value.\n", @@ -874,14 +1078,15 @@ " Resulting Sudoku in dictionary form after eliminating values.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", + " for key, val in values.items():\n", + " if(len(val) == 1):\n", + " for key_peer in peers[key]:\n", + " values[key_peer] = values[key_peer].replace(val, '')\n", + " \n", + " return values\n", "\n", "def only_choice(values):\n", " \"\"\"Finalize all values that are the only choice for a unit.\n", @@ -893,18 +1098,18 @@ " Output: Resulting Sudoku in dictionary form after filling in only choices.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", + " vals_out = values.copy()\n", + " \n", + " for unit in unitlist:\n", + " for digit in '123456789':\n", + " dplaces = [box for box in unit if digit in values[box]]\n", + " if len(dplaces) == 1:\n", + " vals_out[dplaces[0]] = digit\n", + " return vals_out\n", "\n", - "#2. function.py ----------------------------\n", - "# 2.1 combine the functions eliminate and only_choice to write the function reduce_puzzle\n", - "# from utils import *\n", "def reduce_puzzle(values):\n", " \"\"\"\n", " Iterate eliminate() and only_choice(). If at some point, there is a box with no available values, return False.\n", @@ -914,14 +1119,22 @@ " Output: The resulting sudoku in dictionary form.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", + " solved_vals = [box for box in values.keys() if len(values[box]) == 1]\n", + " stalled = False\n", + " while not stalled:\n", + " solved_vals_before = len([box for box in values.keys() if len(values[box]) == 1])\n", + " values = eliminate(values)\n", + " values = only_choice(values)\n", + " solved_vals_after = len([box for box in values.keys() if len(values[box]) == 1])\n", + " stalled = (solved_vals_before == solved_vals_after)\n", + " if len([box for box in values.keys() if len(values[box]) == 0]):\n", + " return False\n", + " \n", + " return values\n", + " \n", "\n", "#3. Test utils.py ---------------------------- \n", "grid_easy = '..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..'\n", @@ -975,11 +1188,22 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "%%%html\n", "" @@ -987,11 +1211,44 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": { - "collapsed": false + "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The original Sudoku board is **********************************************\n", + " 4 123456789 123456789 |123456789 123456789 123456789 | 8 123456789 5 \n", + "123456789 3 123456789 |123456789 123456789 123456789 |123456789 123456789 123456789 \n", + "123456789 123456789 123456789 | 7 123456789 123456789 |123456789 123456789 123456789 \n", + "------------------------------+------------------------------+------------------------------\n", + "123456789 2 123456789 |123456789 123456789 123456789 |123456789 6 123456789 \n", + "123456789 123456789 123456789 |123456789 8 123456789 | 4 123456789 123456789 \n", + "123456789 123456789 123456789 |123456789 1 123456789 |123456789 123456789 123456789 \n", + "------------------------------+------------------------------+------------------------------\n", + "123456789 123456789 123456789 | 6 123456789 3 |123456789 7 123456789 \n", + " 5 123456789 123456789 | 2 123456789 123456789 |123456789 123456789 123456789 \n", + " 1 123456789 4 |123456789 123456789 123456789 |123456789 123456789 123456789 \n", + "\n", + "\n", + "After applying Depth First Search Algorithm *****************\n", + "4 1 7 |3 6 9 |8 2 5 \n", + "6 3 2 |1 5 8 |9 4 7 \n", + "9 5 8 |7 2 4 |3 1 6 \n", + "------+------+------\n", + "8 2 5 |4 3 7 |1 6 9 \n", + "7 9 1 |5 8 6 |4 3 2 \n", + "3 4 6 |9 1 2 |7 5 8 \n", + "------+------+------\n", + "2 8 9 |6 4 3 |5 7 1 \n", + "5 7 3 |2 9 1 |6 8 4 \n", + "1 6 4 |8 7 5 |2 9 3 \n" + ] + } + ], "source": [ "'''\n", "Exercise6.1: Coding the Solution\n", @@ -1055,14 +1312,17 @@ " - values: Value in corresponding box, e.g. '8', or '123456789' if it is empty.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", + " txt = []\n", + " for ch in grid:\n", + " if ch == '.':\n", + " ch = '123456789'\n", + " txt.append(ch)\n", + " \n", + " assert len(txt) == 81\n", + " return dict(zip(boxes, txt))\n", "\n", "def eliminate(values):\n", " \"\"\"Eliminate values from peers of each box with a single value.\n", @@ -1076,14 +1336,15 @@ " Resulting Sudoku in dictionary form after eliminating values.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", + " for key, val in values.items():\n", + " if(len(val) == 1):\n", + " for key_peer in peers[key]:\n", + " values[key_peer] = values[key_peer].replace(val, '')\n", + " \n", + " return values\n", "\n", "def only_choice(values):\n", " \"\"\"Finalize all values that are the only choice for a unit.\n", @@ -1095,14 +1356,17 @@ " Output: Resulting Sudoku in dictionary form after filling in only choices.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", + " vals_out = values.copy()\n", + " \n", + " for unit in unitlist:\n", + " for digit in '123456789':\n", + " dplaces = [box for box in unit if digit in values[box]]\n", + " if len(dplaces) == 1:\n", + " vals_out[dplaces[0]] = digit\n", + " return vals_out\n", "\n", "def reduce_puzzle(values):\n", " \"\"\"\n", @@ -1113,14 +1377,21 @@ " Output: The resulting sudoku in dictionary form.\n", " \"\"\"\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", + " solved_vals = [box for box in values.keys() if len(values[box]) == 1]\n", + " stalled = False\n", + " while not stalled:\n", + " solved_vals_before = len([box for box in values.keys() if len(values[box]) == 1])\n", + " values = eliminate(values)\n", + " values = only_choice(values)\n", + " solved_vals_after = len([box for box in values.keys() if len(values[box]) == 1])\n", + " stalled = (solved_vals_before == solved_vals_after)\n", + " if len([box for box in values.keys() if len(values[box]) == 0]):\n", + " return False\n", + " \n", + " return values\n", " \n", "#2. function.py ----------------------------\n", "# 2.1 implement search() using Depth First Search Algorithm\n", @@ -1132,15 +1403,22 @@ " # Now use recursion to solve each one of the resulting sudokus, \n", " # and if one returns a value (not False), return that answer!\n", " \n", - " ''' Your solution here \n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", - " .........\n", + " ''' \n", + " Your solution here \n", " '''\n", - "\n", + " values = reduce_puzzle(values)\n", + " if values is False:\n", + " return False\n", + " if all(len(values[key]) == 1 for key in boxes):\n", + " return values\n", + " n,key = min((len(values[key]), key) for key in boxes if len(values[key]) > 1)\n", + " for val in values[key]:\n", + " vals_out = values.copy()\n", + " vals_out[key] = val\n", + " seeker = search(vals_out)\n", + " if seeker:\n", + " return seeker\n", + " \n", "#3. Test utils.py ---------------------------- \n", "grid_easy = '..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..'\n", "grid_hard = '4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......'\n", @@ -1167,7 +1445,7 @@ "metadata": { "anaconda-cloud": {}, "kernelspec": { - "display_name": "Python [default]", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -1181,7 +1459,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.2" + "version": "3.6.1" } }, "nbformat": 4,