mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-04-30 16:01:14 -04:00
refactor(curriculum): restructure sudoku solver python project (#54303)
Co-authored-by: zairahira <33151350+zairahira@users.noreply.github.com> Co-authored-by: Sem Bauke <semboot699@gmail.com>
This commit is contained in:
@@ -11,320 +11,316 @@
|
||||
"superBlock": "scientific-computing-with-python",
|
||||
"challengeOrder": [
|
||||
{
|
||||
"id": "656873ffdc638f7e290f60de",
|
||||
"id": "66068fb0bfddba2b7977eb60",
|
||||
"title": "Step 1"
|
||||
},
|
||||
{
|
||||
"id": "656874efd5102b81815c8ef7",
|
||||
"id": "66069167b3307b2f4067b22b",
|
||||
"title": "Step 2"
|
||||
},
|
||||
{
|
||||
"id": "65688efcc78c9495e73acfc9",
|
||||
"id": "6606927d010be4300a4e5330",
|
||||
"title": "Step 3"
|
||||
},
|
||||
{
|
||||
"id": "65688f22703200963a85dfb7",
|
||||
"id": "6606933d6813a8308c962dd1",
|
||||
"title": "Step 4"
|
||||
},
|
||||
{
|
||||
"id": "65688f737b0ef396bf0c22d6",
|
||||
"id": "660699119472f332798860ad",
|
||||
"title": "Step 5"
|
||||
},
|
||||
{
|
||||
"id": "65688f93a1b6e9970f710f62",
|
||||
"id": "660699aabc59c532f2d556e5",
|
||||
"title": "Step 6"
|
||||
},
|
||||
{
|
||||
"id": "65688fc27e8dda9760c45d7d",
|
||||
"id": "66069b0b36053733a2f012fe",
|
||||
"title": "Step 7"
|
||||
},
|
||||
{
|
||||
"id": "65689020cfd5279803976b25",
|
||||
"id": "66069b992c1c5e3451f3deb0",
|
||||
"title": "Step 8"
|
||||
},
|
||||
{
|
||||
"id": "6568904b83a2f29878578146",
|
||||
"id": "66069d65162e61357c793e0c",
|
||||
"title": "Step 9"
|
||||
},
|
||||
{
|
||||
"id": "6568917528820d99236ad811",
|
||||
"id": "66069e5759b800364707988e",
|
||||
"title": "Step 10"
|
||||
},
|
||||
{
|
||||
"id": "656896ffecbf07a2d3402a93",
|
||||
"id": "66069f86f58f85371d47123e",
|
||||
"title": "Step 11"
|
||||
},
|
||||
{
|
||||
"id": "6568991b4d4874a4d5271337",
|
||||
"id": "6606a219f9efbf38ad496f67",
|
||||
"title": "Step 12"
|
||||
},
|
||||
{
|
||||
"id": "6568994faf481da5d37bfa40",
|
||||
"id": "6606a2f8a6a36f39518e0439",
|
||||
"title": "Step 13"
|
||||
},
|
||||
{
|
||||
"id": "6568997f94c673a68b035b60",
|
||||
"id": "6606a3ccb1eea93a23c066bf",
|
||||
"title": "Step 14"
|
||||
},
|
||||
{
|
||||
"id": "656899c0478950a7e5db2cc0",
|
||||
"id": "6606a4641ec48b3a9fe8c2fc",
|
||||
"title": "Step 15"
|
||||
},
|
||||
{
|
||||
"id": "656899f4214ee6a881bc8649",
|
||||
"id": "6606b0d602d1e33e81bcef0d",
|
||||
"title": "Step 16"
|
||||
},
|
||||
{
|
||||
"id": "65689a748de8fbaa00c5617e",
|
||||
"id": "6606b224a69a293f98f8db8f",
|
||||
"title": "Step 17"
|
||||
},
|
||||
{
|
||||
"id": "65689aa3d3f2b6aad204a59e",
|
||||
"id": "6606b63c0fd55e4314d2ec85",
|
||||
"title": "Step 18"
|
||||
},
|
||||
{
|
||||
"id": "65689ad61dfa81ab9ffafc86",
|
||||
"id": "6606b6b7760d0643c3b4eb29",
|
||||
"title": "Step 19"
|
||||
},
|
||||
{
|
||||
"id": "65689b055e6f49ac6f82d3cf",
|
||||
"id": "6606b8d31356fe4563f0e99c",
|
||||
"title": "Step 20"
|
||||
},
|
||||
{
|
||||
"id": "6568a242a3e1efc22b07274d",
|
||||
"id": "6606b961ebcf04460f8af76e",
|
||||
"title": "Step 21"
|
||||
},
|
||||
{
|
||||
"id": "6568bb1ffe8462c427c0d386",
|
||||
"id": "6606baaf1828ff46ebcc008c",
|
||||
"title": "Step 22"
|
||||
},
|
||||
{
|
||||
"id": "6568bb656c67e9c54cced2d7",
|
||||
"id": "6606bbd52233b247cf0a56e4",
|
||||
"title": "Step 23"
|
||||
},
|
||||
{
|
||||
"id": "6568bba429481cc693fc2570",
|
||||
"id": "6606bc4e5535c0484990ccd5",
|
||||
"title": "Step 24"
|
||||
},
|
||||
{
|
||||
"id": "6568bbc8c3bda1c773e23cf1",
|
||||
"id": "6606bd3d02e86548d3ce1a0a",
|
||||
"title": "Step 25"
|
||||
},
|
||||
{
|
||||
"id": "6568bc19f3418dc8a8821187",
|
||||
"id": "6606beade9200b49aaeecd94",
|
||||
"title": "Step 26"
|
||||
},
|
||||
{
|
||||
"id": "6568bc85c5beadca3e0f6eb1",
|
||||
"id": "6606bf4561f8794a0d345919",
|
||||
"title": "Step 27"
|
||||
},
|
||||
{
|
||||
"id": "6568bd3741e379ccc220af1b",
|
||||
"id": "6606c05b5624a54ab85808fa",
|
||||
"title": "Step 28"
|
||||
},
|
||||
{
|
||||
"id": "6568bd85482755cdd26443ae",
|
||||
"id": "6606c0dd3293064b30d17a72",
|
||||
"title": "Step 29"
|
||||
},
|
||||
{
|
||||
"id": "6568bdb69e05a9cee01068a8",
|
||||
"id": "6606c14182435d4bab0de2ee",
|
||||
"title": "Step 30"
|
||||
},
|
||||
{
|
||||
"id": "6568beebba98a3d1f26f6bf8",
|
||||
"id": "6606c2d203a8124c83b2234b",
|
||||
"title": "Step 31"
|
||||
},
|
||||
{
|
||||
"id": "6568bf22bb5de0d2e8260cf3",
|
||||
"id": "6606c3fd5634684d48a7887b",
|
||||
"title": "Step 32"
|
||||
},
|
||||
{
|
||||
"id": "6568bf5e5b2f4bd3eb7ef995",
|
||||
"id": "6606cb019db4f74f224856f4",
|
||||
"title": "Step 33"
|
||||
},
|
||||
{
|
||||
"id": "6568bf853bf06dd4ed25d4ca",
|
||||
"id": "6606cc088fd3574fa9010a4f",
|
||||
"title": "Step 34"
|
||||
},
|
||||
{
|
||||
"id": "6568bfb601a54ed5b367b44f",
|
||||
"id": "6606cc473675e85017b0c53d",
|
||||
"title": "Step 35"
|
||||
},
|
||||
{
|
||||
"id": "6568bfd65322add674039bde",
|
||||
"id": "6606cc754a8834509cd0afb6",
|
||||
"title": "Step 36"
|
||||
},
|
||||
{
|
||||
"id": "6568c0013b3b62d7617518c7",
|
||||
"id": "6606cd69f56e27516583b0cc",
|
||||
"title": "Step 37"
|
||||
},
|
||||
{
|
||||
"id": "6568c024933423d85d5ed93c",
|
||||
"id": "6606cf1b2b9f65529c161098",
|
||||
"title": "Step 38"
|
||||
},
|
||||
{
|
||||
"id": "6568c073d5f37fd99ab2ab0c",
|
||||
"id": "6606d03ff198245383e61d90",
|
||||
"title": "Step 39"
|
||||
},
|
||||
{
|
||||
"id": "6568c0a5edddc3daa65d20b2",
|
||||
"id": "6606d32096165654b8e73f21",
|
||||
"title": "Step 40"
|
||||
},
|
||||
{
|
||||
"id": "6569d83fe4dcc614c2ff971d",
|
||||
"id": "6606d378de78d55523f08298",
|
||||
"title": "Step 41"
|
||||
},
|
||||
{
|
||||
"id": "6569d8a4b8d85515cbb1ce72",
|
||||
"id": "6606d589750ad655fa0df168",
|
||||
"title": "Step 42"
|
||||
},
|
||||
{
|
||||
"id": "6569d946293d4f185e32e2da",
|
||||
"id": "6606d6138c49e456920fa818",
|
||||
"title": "Step 43"
|
||||
},
|
||||
{
|
||||
"id": "6569d98303af38193149b66e",
|
||||
"id": "6606d7bb9e4c6b574235159a",
|
||||
"title": "Step 44"
|
||||
},
|
||||
{
|
||||
"id": "6569d9dfd53db11b176d2963",
|
||||
"id": "6606d8795bd533582425a363",
|
||||
"title": "Step 45"
|
||||
},
|
||||
{
|
||||
"id": "6569da02e7e2641be14ff922",
|
||||
"id": "6606d8c323d6205890fbbd54",
|
||||
"title": "Step 46"
|
||||
},
|
||||
{
|
||||
"id": "6569de93a5340b202667deda",
|
||||
"id": "6606d9d92fcf78598b3b5184",
|
||||
"title": "Step 47"
|
||||
},
|
||||
{
|
||||
"id": "6569def38470282151f873ce",
|
||||
"id": "6606db6a23a1455a402f91ae",
|
||||
"title": "Step 48"
|
||||
},
|
||||
{
|
||||
"id": "6569df1d6fb83d22623b38c5",
|
||||
"id": "6606dcf5a31e4e5b43737417",
|
||||
"title": "Step 49"
|
||||
},
|
||||
{
|
||||
"id": "6569df6916294723e01f0035",
|
||||
"id": "6606dd63109f9f5c2195e30c",
|
||||
"title": "Step 50"
|
||||
},
|
||||
{
|
||||
"id": "6569df9e20f74a251d482c5d",
|
||||
"id": "6606de006a82e05c9a65cebe",
|
||||
"title": "Step 51"
|
||||
},
|
||||
{
|
||||
"id": "6569dffeee007f26d2b56d46",
|
||||
"id": "6606e2f27f19ca5f398c6aed",
|
||||
"title": "Step 52"
|
||||
},
|
||||
{
|
||||
"id": "6569e2a01a97b231862ba2ff",
|
||||
"id": "6606e3e6231702600bd5860c",
|
||||
"title": "Step 53"
|
||||
},
|
||||
{
|
||||
"id": "6569e2e1944fe7329ab21c7f",
|
||||
"id": "660a737f0f72b51de361051c",
|
||||
"title": "Step 54"
|
||||
},
|
||||
{
|
||||
"id": "6569e309feb5d333867a034a",
|
||||
"id": "660a7a1cac69b7217cbae22d",
|
||||
"title": "Step 55"
|
||||
},
|
||||
{
|
||||
"id": "6569e33a708a3834f6d4879b",
|
||||
"id": "660a7cb75dce3d22ab562c0d",
|
||||
"title": "Step 56"
|
||||
},
|
||||
{
|
||||
"id": "6569e37ec28e853628f18a86",
|
||||
"id": "660a7ea6e3a21a243d6aa288",
|
||||
"title": "Step 57"
|
||||
},
|
||||
{
|
||||
"id": "6569e3a134fea0371fa008de",
|
||||
"id": "660a7f28d5ce6a24ef856a50",
|
||||
"title": "Step 58"
|
||||
},
|
||||
{
|
||||
"id": "6569e3d1418b373839a0aa7b",
|
||||
"id": "660a8b6cd8de406ae82ce910",
|
||||
"title": "Step 59"
|
||||
},
|
||||
{
|
||||
"id": "6569e41657a9923953aa7d3c",
|
||||
"id": "660a8c3b21100c6b83e57cb0",
|
||||
"title": "Step 60"
|
||||
},
|
||||
{
|
||||
"id": "6569e481e67f123ad25c5d20",
|
||||
"id": "660a8d7c5f33c16c67e58b37",
|
||||
"title": "Step 61"
|
||||
},
|
||||
{
|
||||
"id": "6569f6b48716b5402504e216",
|
||||
"id": "660a8ef6b7571f6dddc3553b",
|
||||
"title": "Step 62"
|
||||
},
|
||||
{
|
||||
"id": "6569f6ebe558bd4136da96cc",
|
||||
"id": "660a92e93854486efa68fe6f",
|
||||
"title": "Step 63"
|
||||
},
|
||||
{
|
||||
"id": "6569f70a66ccdc42097ca051",
|
||||
"id": "660a937220bf966fd844f1ee",
|
||||
"title": "Step 64"
|
||||
},
|
||||
{
|
||||
"id": "6569f770fd7dc443d6293095",
|
||||
"id": "660a940b3379fb708a83593a",
|
||||
"title": "Step 65"
|
||||
},
|
||||
{
|
||||
"id": "6569f7c7f6954944d207775f",
|
||||
"id": "660a94f55c3c9b71a37e1c8b",
|
||||
"title": "Step 66"
|
||||
},
|
||||
{
|
||||
"id": "6569f7f2fa74c045e95676ac",
|
||||
"id": "660a957f44c096728ba9c41f",
|
||||
"title": "Step 67"
|
||||
},
|
||||
{
|
||||
"id": "6569fa5b9d507748bf4ec722",
|
||||
"id": "660a95c3da857673124ed698",
|
||||
"title": "Step 68"
|
||||
},
|
||||
{
|
||||
"id": "6569fa85d8f9ed49c8dfb37d",
|
||||
"id": "660a968ca0838773c9bbfc85",
|
||||
"title": "Step 69"
|
||||
},
|
||||
{
|
||||
"id": "6569fabbfe1c094ad838ec4c",
|
||||
"id": "660a9819ad113774d65a1e7c",
|
||||
"title": "Step 70"
|
||||
},
|
||||
{
|
||||
"id": "6569fbbfee025a4e850b6eaf",
|
||||
"id": "660ac1d158923e805d3c3099",
|
||||
"title": "Step 71"
|
||||
},
|
||||
{
|
||||
"id": "6569fc21837cab5029d82e26",
|
||||
"id": "660ac2873b090d80d6aa6ce2",
|
||||
"title": "Step 72"
|
||||
},
|
||||
{
|
||||
"id": "6569fc63a404c8519d918095",
|
||||
"id": "660ac35d55a15d81afdedd76",
|
||||
"title": "Step 73"
|
||||
},
|
||||
{
|
||||
"id": "6569fca3cd7a9f52f322a298",
|
||||
"id": "660ac44c7eec868220318297",
|
||||
"title": "Step 74"
|
||||
},
|
||||
{
|
||||
"id": "6569fd01dab2ea547d98f093",
|
||||
"id": "660ac4f4f784b9829e89632a",
|
||||
"title": "Step 75"
|
||||
},
|
||||
{
|
||||
"id": "6569fd352879475599d0ec66",
|
||||
"id": "660ac56326c2eb831583c0de",
|
||||
"title": "Step 76"
|
||||
},
|
||||
{
|
||||
"id": "6569fd6d3cb95856c9ed2190",
|
||||
"id": "660ac59d7ea60083900b83df",
|
||||
"title": "Step 77"
|
||||
},
|
||||
{
|
||||
"id": "6569fdc59fe1b658bc9e23a4",
|
||||
"id": "660ac60e22aa218400acb4b6",
|
||||
"title": "Step 78"
|
||||
},
|
||||
{
|
||||
"id": "6569fe0fe5b5425a1bb1f534",
|
||||
"title": "Step 79"
|
||||
}
|
||||
],
|
||||
"helpCategory": "Python"
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
---
|
||||
id: 656874efd5102b81815c8ef7
|
||||
title: Step 2
|
||||
challengeType: 20
|
||||
dashedName: step-2
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
A new instance of a class is created by using the function notation: `ClassName()`. The instantiation creates an empty object. Classes can have methods, which are like local functions for each instance. Methods are declared as follows:
|
||||
|
||||
```python
|
||||
class ClassName:
|
||||
def method_name():
|
||||
pass
|
||||
```
|
||||
|
||||
The `__init__` method is a special method that allows you to instantiate an object to a customized state. When a class implements an `__init__` method, `__init__` is automatically called upon instantiation.
|
||||
|
||||
Create an `__init__` method inside your `Board` class.
|
||||
|
||||
# --hints--
|
||||
|
||||
Your method should be named `__init__`. Don't add any parameters.
|
||||
|
||||
```js
|
||||
assert.match(code, / +def\s+__init__\s*\(\s*\)\:/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Board:
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,33 +0,0 @@
|
||||
---
|
||||
id: 65688efcc78c9495e73acfc9
|
||||
title: Step 3
|
||||
challengeType: 20
|
||||
dashedName: step-3
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Add two parameters to the `__init__` method, order matters:
|
||||
|
||||
- `self`: This is a reference to the instance of the class. It is a convention to name this parameter self.
|
||||
- `board`: The board parameter is expected to be passed when creating an instance of the `Board` class.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should add the parameter `self` and `board` to the method.
|
||||
|
||||
```js
|
||||
assert.match(code, /def\s+__init__\s*\(\s*self\s*,\s*board\s*\):/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Board:
|
||||
def __init__():
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,32 +0,0 @@
|
||||
---
|
||||
id: 65688f22703200963a85dfb7
|
||||
title: Step 4
|
||||
challengeType: 20
|
||||
dashedName: step-4
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the `__init__` method, assign the value of the `board` parameter (which is passed when creating an instance of the `Board` class) to an instance variable named `board` using `self.board`.
|
||||
|
||||
`self.board` refers to the board attribute of the instance of the class. It's a variable that belongs to the object created from the `Board` class.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `self.board = board` within the `__init__` method.
|
||||
|
||||
```js
|
||||
assert.match(code, /self\.board\s*=\s*board/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,60 +0,0 @@
|
||||
---
|
||||
id: 65688f737b0ef396bf0c22d6
|
||||
title: Step 5
|
||||
challengeType: 20
|
||||
dashedName: step-5
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now you will move to the actual construction of the board, which is a 9x9 grid.
|
||||
|
||||
The input puzzle would look like this:
|
||||
|
||||
```py
|
||||
puzzle = [
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
```
|
||||
|
||||
The resulting grid would look like this:
|
||||
|
||||
<img class="img-responsive" alt="a board of sudoku" src="https://cdn.freecodecamp.org/curriculum/python/sample-board.png" style="background-color: white; height:300px; width:300px; padding: 10px;">
|
||||
|
||||
|
||||
Define a method `__str__` within the `Board` class. Also, add the `self` parameter. This method is automatically called when you use the `str()` function on an instance of the class or when you use `print()` with the object.
|
||||
|
||||
# --hints--
|
||||
|
||||
Your method should be named `__str__`.
|
||||
|
||||
```js
|
||||
assert.match(code, /def\s+__str__\s*\(/);
|
||||
```
|
||||
|
||||
You should add the parameter `self` to the method.
|
||||
|
||||
```js
|
||||
assert.match(code, /def\s+__str__\s*\(\s*self\s*\)\s*:/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,35 +0,0 @@
|
||||
---
|
||||
id: 65688f93a1b6e9970f710f62
|
||||
title: Step 6
|
||||
challengeType: 20
|
||||
dashedName: step-6
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
To create the top border of the board, create an `upper_lines` variable and assign it the value of `f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'`.
|
||||
|
||||
This string represents the top border of the sudoku board in a visually appealing ASCII art style. It uses special Unicode characters to draw the borders and intersections.
|
||||
|
||||
# --hints--
|
||||
|
||||
Assign the value of `f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'` to a variable named `upper_lines`.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /upper_lines\s*=\s*f("|')\\n╔═══\{\s*(?=[^\1])("|')╤═══\2\s*\*\s*2\s*\}\{\s*\2╦═══\2\s*\}\{\s*\2╤═══\2\s*\*\s*2\s*\}\{\s*\2╦═══\2\s*\}\{\s*\2╤═══\2\s*\*\s*2\s*\}╗\\n\1/m) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
--fcc-editable-region--
|
||||
def __str__(self):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,34 +0,0 @@
|
||||
---
|
||||
id: 65688fc27e8dda9760c45d7d
|
||||
title: Step 7
|
||||
challengeType: 20
|
||||
dashedName: step-7
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
To create middle borders of the sudoku board, create a `middle_lines` variable and assign it the value of `f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should assign the value of `f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'` to a variable named `middle_lines`.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /middle_lines\s*=\s*f("|')╟───\{\s*(?=[^\1])("|')┼───\2\s*\*\s*2\s*\}\{\s*\2╫───\2\s*\}\{\s*\2┼───\2\s*\*\s*2\s*\}\{\s*\2╫───\2\s*\}\{\s*\2┼───\2\s*\*\s*2\s*\}╢\\n\1/m) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
--fcc-editable-region--
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,35 +0,0 @@
|
||||
---
|
||||
id: 65689020cfd5279803976b25
|
||||
title: Step 8
|
||||
challengeType: 20
|
||||
dashedName: step-8
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
To create the bottom border of the sudoku board, create a `lower_lines` variable and assign it the value of `f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should add `lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'` to the code.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /lower_lines\s*=\s*f("|')╚═══\{\s*(?=[^\1])("|')╧═══\2\s*\*\s*2\s*\}\{\s*\2╩═══\2\s*\}\{\s*\2╧═══\2\s*\*\s*2\s*\}\{\s*\2╩═══\2\s*\}\{\s*\2╧═══\2\s*\*\s*2\s*\}╝\\n\1/m) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
--fcc-editable-region--
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,42 +0,0 @@
|
||||
---
|
||||
id: 6568904b83a2f29878578146
|
||||
title: Step 9
|
||||
challengeType: 20
|
||||
dashedName: step-9
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Initialize a `board_string` variable with the content of `upper_lines`. This will be the starting point for building the entire visual representation of the sudoku board.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `board_string = upper_lines` within the `__str__` method.
|
||||
|
||||
```js
|
||||
({ test: () =>
|
||||
{
|
||||
const str = __helpers.python.getDef(code.replace(/\r/g, ''), "__str__");
|
||||
const {function_body} = str;
|
||||
assert(function_body.match(/board_string\s*=\s*upper_lines/));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
--fcc-editable-region--
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,53 +0,0 @@
|
||||
---
|
||||
id: 6568917528820d99236ad811
|
||||
title: Step 10
|
||||
challengeType: 20
|
||||
dashedName: step-10
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now, you need to go over each row in the sudoku board.
|
||||
|
||||
Enumeration is a convenient way to keep track of both the element and its position on a list.
|
||||
The `enumerate()` function is a built-in function in Python that takes an iterable (such as a list, tuple, or string) and returns an iterator that produces tuples containing indices and corresponding values from the iterable.
|
||||
|
||||
Initiate a `for` loop to iterate over each row (`line`) in the sudoku board (`self.board`).
|
||||
|
||||
Use enumeration to get both the index (`index`) and the content (`line`) of each row.
|
||||
|
||||
The general syntax would be like this:
|
||||
|
||||
```js
|
||||
for x, y in enumerate(parameter):
|
||||
```
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `for index, line in enumerate(self.board):` within the `__str__` method.
|
||||
|
||||
```js
|
||||
assert.match(
|
||||
code,
|
||||
/for\s+(\w+)\s*,\s*(?!\1)(\w+)\s+in\s+enumerate\s*\(\s*self\.board\s*\)\s*:/m
|
||||
);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,57 +0,0 @@
|
||||
---
|
||||
id: 656896ffecbf07a2d3402a93
|
||||
title: Step 11
|
||||
challengeType: 20
|
||||
dashedName: step-11
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the loop, initialize an empty list `row_list` to store the elements of a single row in the sudoku board.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have a `row_list` variable.
|
||||
|
||||
```js
|
||||
({ test: () =>
|
||||
{
|
||||
const str = __helpers.python.getDef(code.replace(/\r/g, ''), "__str__");
|
||||
const {function_body} = str;
|
||||
assert(function_body.match(/row_list\s*=/));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`row_list` should be an empty list.
|
||||
|
||||
```js
|
||||
({ test: () =>
|
||||
{
|
||||
const str = __helpers.python.getDef(code.replace(/\r/g, ''), "__str__");
|
||||
const {function_body} = str;
|
||||
assert(function_body.match(/row_list\s*=\s*\[\s*\]/));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
|
||||
--fcc-editable-region--
|
||||
for index, line in enumerate(self.board):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,48 +0,0 @@
|
||||
---
|
||||
id: 6568991b4d4874a4d5271337
|
||||
title: Step 12
|
||||
challengeType: 20
|
||||
dashedName: step-12
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Next, you are going to split each row in three segments, in order to represent the 3x3 squares properly.
|
||||
|
||||
Create a nested `for` loop to iterate over each segment of the row. Use `square_no` and `part` as the iterating variable and the `enumerate()` function. For now, leave the `enumerate()` call empty.
|
||||
|
||||
# --hints--
|
||||
|
||||
The inner loop should have `square_no` as the counter and `part` as the element from iterable.
|
||||
|
||||
```js
|
||||
assert.match(code, /for\s+square_no\s*,\s*part/)
|
||||
```
|
||||
|
||||
You should have `for square_no, part in enumerate()` within the existing `for` loop.
|
||||
|
||||
```js
|
||||
assert.match(code, /for\s+square_no\s*,\s*part\s+in\s+enumerate\s*\(\s*\)\:/)
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
|
||||
--fcc-editable-region--
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,42 +0,0 @@
|
||||
---
|
||||
id: 6568994faf481da5d37bfa40
|
||||
title: Step 13
|
||||
challengeType: 20
|
||||
dashedName: step-13
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now, you need to create the three line segments to pass to the `enumerate` function.
|
||||
|
||||
Use list slicing to create the three lists of equal length representing the `line` segment of each 3x3 square and pass them to the `enumerate()` call. Add `start = 1` to start the enumeration from `1` instead of `0`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `enumerate([line[:3], line[3:6], line[6:]], start=1)` within the inner `for` loop.
|
||||
|
||||
```js
|
||||
assert.match(code, /\[\s*line\s*\[\s*:3\s*\]\s*,\s*line\s*\[\s*3\s*:\s*6\s*\]\s*,\s*line\s*\[\s*6\s*:\s*\]\s*\]\s*,\s*start\s*=\s*1/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
|
||||
--fcc-editable-region--
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate():
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,60 +0,0 @@
|
||||
---
|
||||
id: 6568997f94c673a68b035b60
|
||||
title: Step 14
|
||||
challengeType: 20
|
||||
dashedName: step-14
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now, you would join the elements of the segment (`part`) with the pipe character (`|`).
|
||||
|
||||
For that, first, use a `for` loop `for item in part` to access all elements.
|
||||
|
||||
Then, use the `join()` method on the `|` character to join the elements of the segment (`part`).
|
||||
|
||||
After that, convert each element to a string using `str(item)`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should use the `join()` method on the `|` character to join the elements of the segment (`part`).
|
||||
add test for "" as well
|
||||
|
||||
```js
|
||||
assert.match(code, /('|")\|\1\.join\s*\(/)
|
||||
```
|
||||
|
||||
You should call `str()` on each element in `part` using a generator expression.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /\(\s*str\s*\(\s*(\w+)\s*\)\s+for\s+\1\s+in\s+part\s*\)/) })
|
||||
```
|
||||
|
||||
You should have `'|'.join(str(item) for item in part)` within the inner `for` loop.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /("|')\|\1\.join\s*\(\s*str\s*\(\s*(\w+)\s*\)\s+for\s+\2\s+in\s+part\s*\)/m) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
--fcc-editable-region--
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,41 +0,0 @@
|
||||
---
|
||||
id: 656899c0478950a7e5db2cc0
|
||||
title: Step 15
|
||||
challengeType: 20
|
||||
dashedName: step-15
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Assign the joined string to the variable `row_square`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should assign the value of `'|'.join(str(item) for item in part)` to a variable named `row_square`.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /row_square\s*=\s*("|')\|\1\.join\s*\(\s*str\s*\(\s*(\w+)\s*\)\s+for\s+\2\s+in\s+part\s*\)/m) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
--fcc-editable-region--
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
'|'.join(str(item) for item in part)
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,42 +0,0 @@
|
||||
---
|
||||
id: 656899f4214ee6a881bc8649
|
||||
title: Step 16
|
||||
challengeType: 20
|
||||
dashedName: step-16
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Extend the `row_list` with the elements of the `row_square` string.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `row_list.extend(row_square)` within the innermost `for` loop.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /row_list\.extend\s*\(\s*row_square\s*\)/m) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
|
||||
--fcc-editable-region--
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,44 +0,0 @@
|
||||
---
|
||||
id: 65689a748de8fbaa00c5617e
|
||||
title: Step 17
|
||||
challengeType: 20
|
||||
dashedName: step-17
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Within the innermost loop, create an `if` statement to check if the current segment (`square_no`) is not the last one (i.e., not equal to `3`)
|
||||
|
||||
# --hints--
|
||||
|
||||
You should check if the current segment (`square_no`) is not equal to `3`.
|
||||
|
||||
```js
|
||||
assert.match(code, /if\s+square_no\s*!=\s*3/m)
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
|
||||
--fcc-editable-region--
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,45 +0,0 @@
|
||||
---
|
||||
id: 65689aa3d3f2b6aad204a59e
|
||||
title: Step 18
|
||||
challengeType: 20
|
||||
dashedName: step-18
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the `if` block, append a `║` character at the end of `row_list`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `row_list.append('║')` within the `if` statement.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /row_list\.append\s*\(\s*("|')║\1\s*\)/m) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
|
||||
--fcc-editable-region--
|
||||
if square_no != 3:
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,48 +0,0 @@
|
||||
---
|
||||
id: 65689ad61dfa81ab9ffafc86
|
||||
title: Step 19
|
||||
challengeType: 20
|
||||
dashedName: step-19
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Next, you will create a string representation of the row with spaces between each element.
|
||||
|
||||
For that, outside the innermost `for` loop body, create a string `row`. Assign the following formatted string `f'║ {" ".join(row_list)} ║\n'` to it to join the elements of `row_list` with a space in between.
|
||||
|
||||
# --hints--
|
||||
|
||||
Assign the formatted string `f'║ {" ".join(row_list)} ║\n'` to a variable named `row`.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /row\s*\=\s*f("|')║\s\{(?!\1)("|')\s\2\.join\s*\(\s*row_list\s*\)\s*\}\s║\\n\1/m) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
--fcc-editable-region--
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,60 +0,0 @@
|
||||
---
|
||||
id: 65689b055e6f49ac6f82d3cf
|
||||
title: Step 20
|
||||
challengeType: 20
|
||||
dashedName: step-20
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
When you would pass your input puzzle board, `0` would be used for empty cells.
|
||||
|
||||
For a better visual representation, replace the empty cells in a row with a space using the `replace` method.
|
||||
|
||||
The `replace()` method takes two arguments, the first one is the character to be replaced and the second one is the character to be replaced with.
|
||||
|
||||
After replacing, assign the result to a variable `row_empty`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should replace each `0` in the row with a space using the `replace` method.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /row\.replace\s*\(\s*("|')0\1\s*,\s*("|') \2\s*\)/) })
|
||||
```
|
||||
|
||||
You should have `row_empty = row.repalce('0', ' ')` within the outermost `for` loop.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /row_empty\s*=\s*row\.replace\s*\(\s*("|')0\1\s*,\s*("|') \2\s*\)/m) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
--fcc-editable-region--
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
id: 6568a242a3e1efc22b07274d
|
||||
title: Step 21
|
||||
challengeType: 20
|
||||
dashedName: step-21
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
`board_string` is gradually built up as the loop iterates over each row, creating the full ASCII art representation of the sudoku board.
|
||||
|
||||
Add the modified `row_empty` string to the `board_string`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `board_string += row_empty` within the outermost `for` loop.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /board_string\s*\+=\s*row_empty/m) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
--fcc-editable-region--
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,48 +0,0 @@
|
||||
---
|
||||
id: 6568bb1ffe8462c427c0d386
|
||||
title: Step 22
|
||||
challengeType: 20
|
||||
dashedName: step-22
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Within the outermost `for` loop, create an `if` statement that checks if the current row index is less than `8`. This is because the last row of the sudoku board has an index of `8`, and you want to handle the last row differently.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `if index < 8:` within the outermost `for` loop.
|
||||
|
||||
```js
|
||||
assert.match(code, /if\s+index\s*<\s*8\s*:/m);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
--fcc-editable-region--
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,51 +0,0 @@
|
||||
---
|
||||
id: 6568bb656c67e9c54cced2d7
|
||||
title: Step 23
|
||||
challengeType: 20
|
||||
dashedName: step-23
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now, you need to verify if the row is the last row inside a 3x3 square. This occurs when `index % 3` is equal to `2`.
|
||||
|
||||
Inside your existing `if` block, nest another `if` to check that condition.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `if index % 3 == 2:` within the `if index < 8` statement.
|
||||
|
||||
```js
|
||||
assert.match(code,/if\s+index\s*%\s*3\s*==\s*2\s*:/m)
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
--fcc-editable-region--
|
||||
if index < 8:
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,53 +0,0 @@
|
||||
---
|
||||
id: 6568bba429481cc693fc2570
|
||||
title: Step 24
|
||||
challengeType: 20
|
||||
dashedName: step-24
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If the current row is the last row of a 3x3 square, in order to create a visually appealing border you need to append a different border string to `board_string` .
|
||||
|
||||
Inside the `if` statement, add the following string to the current value of `board_string`: `f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'` within the `if index % 3 == 2` statement.
|
||||
|
||||
```js
|
||||
assert.match(code, /board_string\s*\+=\s*f("|')╠═══\{\s*(?=[^\1])("|')╪═══\2\s*\*\s*2\s*\}\{\s*\2╬═══\2\s*\}\{\s*\2╪═══\2\s*\*\s*2\s*\}\{\s*\2╬═══\2\s*\}\{\s*\2╪═══\2\s*\*\s*2\s*\}╣\\n\1/)
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
--fcc-editable-region--
|
||||
if index % 3 == 2:
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,60 +0,0 @@
|
||||
---
|
||||
id: 6568bbc8c3bda1c773e23cf1
|
||||
title: Step 25
|
||||
challengeType: 20
|
||||
dashedName: step-25
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now, to handle other rows, if the inner condition is `False`, meaning the current row is not the last row of a 3x3 square, append the `middle_lines` string to `board_string`. Include this in an `else` block.
|
||||
|
||||
Recall that `middle_lines` represents the middle borders of the sudoku board and includes horizontal separators.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should add an `else` block to the `if` statement.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /else\s*:/m) })
|
||||
```
|
||||
|
||||
You should have `board_string += middle_lines` within the `else` block.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /board_string\s*\+=\s*middle_lines/m) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
--fcc-editable-region--
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,64 +0,0 @@
|
||||
---
|
||||
id: 6568bc19f3418dc8a8821187
|
||||
title: Step 26
|
||||
challengeType: 20
|
||||
dashedName: step-26
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now, you need to handle the last row of the entire board.
|
||||
|
||||
`lower_lines` represents the bottom border of the entire sudoku board.
|
||||
|
||||
Create an `else` block to append the `lower_lines` string to `board_string` when the outer `if` condition is false.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create an `else` block for the outermost `if` statement. Pay attention to the indentation.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /else\s*:/m) })
|
||||
```
|
||||
|
||||
You should have `board_string += lower_lines` within the outermost `else` clause.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /board_string\s*\+=\s*lower_lines/m) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
--fcc-editable-region--
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
id: 6568bc85c5beadca3e0f6eb1
|
||||
title: Step 27
|
||||
challengeType: 20
|
||||
dashedName: step-27
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
After the outer loop completes for all rows, return the final `board_string`. This string contains the complete visual representation of the sudoku board in ASCII art style, including borders and separators.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should return the `board_string` variable at the end of the outer `for` loop.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const str = __helpers.python.getDef(tCode, "__str__");
|
||||
const {function_body} = str;
|
||||
const indent = function_body.match(/ +/)[0];
|
||||
const returnStatement = `${indent}return board_string`;
|
||||
assert.match(code, new RegExp(returnStatement));
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
--fcc-editable-region--
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,65 +0,0 @@
|
||||
---
|
||||
id: 6568bd3741e379ccc220af1b
|
||||
title: Step 28
|
||||
challengeType: 20
|
||||
dashedName: step-28
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now you will work on a method that finds the empty cells in the sudoku board.
|
||||
For that, within the `Board` class, create a method named `find_empty_cell`. It takes `self` as a parameter, representing the instance of the class. Include the `pass` keyword inside the function body.
|
||||
|
||||
# --hints--
|
||||
|
||||
Your method should be named `find_empty_cell`.
|
||||
|
||||
```js
|
||||
assert.match(code, /def\s+find_empty_cell/);
|
||||
```
|
||||
|
||||
You should add the parameter `self` to the method.
|
||||
|
||||
```js
|
||||
assert.match(code, /def\s+find_empty_cell\(\s*self\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,78 +0,0 @@
|
||||
---
|
||||
id: 6568bd85482755cdd26443ae
|
||||
title: Step 29
|
||||
challengeType: 20
|
||||
dashedName: step-29
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the `find_empty_cell` method, create a `for` loop and use the `enumerate()` function to iterate over each row in the sudoku board.
|
||||
|
||||
Use `row` for the index of the current row and `contents` for the elements of the current row.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create a `for` loop to iterate over `enumerate(self.board)`.
|
||||
|
||||
```js
|
||||
const empty = __helpers.python.getDef(
|
||||
code,
|
||||
'find_empty_cell'
|
||||
);
|
||||
const { function_body } = empty;
|
||||
assert(
|
||||
function_body.match(
|
||||
/for\s+(\w+)\s*,\s*(?!\1)(\w+)\s+in\s+enumerate\s*\(\s*self\.board\s*\)\s*:/m
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
You should have `for row, contents in enumerate(self.board):` within the `find_empty_cell` method.
|
||||
|
||||
```js
|
||||
assert.match(
|
||||
code,
|
||||
/for\s+row\s*,\s*contents\s+in\s+enumerate\s*\(\s*self\.board\s*\)\s*:/m
|
||||
);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
--fcc-editable-region--
|
||||
def find_empty_cell(self):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
id: 6568bdb69e05a9cee01068a8
|
||||
title: Step 30
|
||||
challengeType: 20
|
||||
dashedName: step-30
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
In the body of the for loop, add a `try` block.
|
||||
|
||||
# --hints--
|
||||
|
||||
Add a `try` block.
|
||||
|
||||
```js
|
||||
assert.match(code, /try\s*\:/)
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
--fcc-editable-region--
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,68 +0,0 @@
|
||||
---
|
||||
id: 6568beebba98a3d1f26f6bf8
|
||||
title: Step 31
|
||||
challengeType: 20
|
||||
dashedName: step-31
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
In the `try` block, attempt to find the index of the first occurrence of `0` in the current row using `contents.index(0)`. Store the results in the variable `col`.
|
||||
|
||||
# --hints--
|
||||
|
||||
Use the index of the first occurrence of `0` in the current row using `contents.index(0)`.
|
||||
|
||||
```js
|
||||
assert.match(code, /contents\.index\(\s*0\s*\)/)
|
||||
```
|
||||
|
||||
You should have `col = contents.index(0)` within the `try` block.
|
||||
|
||||
```js
|
||||
assert.match(code, /col\s*=\s*contents\.index\(\s*0\s*\)/)
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
--fcc-editable-region--
|
||||
try:
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,65 +0,0 @@
|
||||
---
|
||||
id: 6568bf22bb5de0d2e8260cf3
|
||||
title: Step 32
|
||||
challengeType: 20
|
||||
dashedName: step-32
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If `0` is found, the code immediately returns a tuple (row, col) with the row index and column index of the empty cell.
|
||||
|
||||
Return the `row` and `col` values
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `return row, col` within the `try` block.
|
||||
|
||||
```js
|
||||
assert.match(code, /return\s*row\s*,\s*col/)
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
--fcc-editable-region--
|
||||
try:
|
||||
col = contents.index(0)
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,64 +0,0 @@
|
||||
---
|
||||
id: 6568bf5e5b2f4bd3eb7ef995
|
||||
title: Step 33
|
||||
challengeType: 20
|
||||
dashedName: step-33
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Create an `except` block to handle the `ValueError` exception that is thrown if `0` is not found.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `except ValueError:` within the innermost `for` loop.
|
||||
|
||||
```js
|
||||
assert.match(code, /except\s+ValueError/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
--fcc-editable-region--
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,68 +0,0 @@
|
||||
---
|
||||
id: 6568bf853bf06dd4ed25d4ca
|
||||
title: Step 34
|
||||
challengeType: 20
|
||||
dashedName: step-34
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If the value `0` is not present in the current row, an exception would be thrown and the `except` block would execute.
|
||||
|
||||
The `except` block should pass and continue to the next row.
|
||||
Achieve this by using `pass`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `pass` within the `except` block.
|
||||
|
||||
```js
|
||||
assert.match(code, /pass/)
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
--fcc-editable-region--
|
||||
except ValueError:
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,75 +0,0 @@
|
||||
---
|
||||
id: 6568bfb601a54ed5b367b44f
|
||||
title: Step 35
|
||||
challengeType: 20
|
||||
dashedName: step-35
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If the loop completes without finding any empty cells, the method should return `None` to indicate that the sudoku board is filled.
|
||||
|
||||
Return `None` outside the `for` loop block.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `return None` outwith the `for` loop.
|
||||
|
||||
```js
|
||||
({ test: () =>
|
||||
{
|
||||
const empty = __helpers.python.getDef(code, "find_empty_cell");
|
||||
const {function_body} = empty;
|
||||
const indent = function_body.match(/ +/)[0];
|
||||
const re = new RegExp(`^${indent}return\\s+None`, "m");
|
||||
assert.match(function_body, re);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
|
||||
--fcc-editable-region--
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,86 +0,0 @@
|
||||
---
|
||||
id: 6568bfd65322add674039bde
|
||||
title: Step 36
|
||||
challengeType: 20
|
||||
dashedName: step-36
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Next, you will work on a method that checks if a given number can be inserted into a specified row of the sudoku board.
|
||||
|
||||
Create a method named `valid_in_row`. It should take three parameters:
|
||||
|
||||
- `self`: representing the instance of the class.
|
||||
- `row`: representing the row index.
|
||||
- `num`: representing the number to be checked.
|
||||
|
||||
Also, don't forget to add the `pass` keyword in the function body.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have a `valid_in_row` method.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const board = __helpers.python.getBlock("\n" + tCode, "class Board");
|
||||
const valid = __helpers.python.getDef(board.block_body, "valid_in_row");
|
||||
assert.exists(valid);
|
||||
```
|
||||
|
||||
You should have `def valid_in_row(self, row, num)` within the `Board` class.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_parameters} = __helpers.python.getDef(tCode, "valid_in_row");
|
||||
assert.match(function_parameters, /self\s*,\s*row\s*,\s*num/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,71 +0,0 @@
|
||||
---
|
||||
id: 6568c0013b3b62d7617518c7
|
||||
title: Step 37
|
||||
challengeType: 20
|
||||
dashedName: step-37
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Create an expression that checks if the number is not already present in that row.
|
||||
|
||||
You should check if the number(`num`) is not present in `self.board[row]`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `num not in self.board[row]` within `valid_in_row`.
|
||||
|
||||
```js
|
||||
assert.match(code, /num\s+not\s+in\s+self\.board\s*\[\s*row\s*\]/)
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
--fcc-editable-region--
|
||||
def valid_in_row(self, row, num):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,76 +0,0 @@
|
||||
---
|
||||
id: 6568c024933423d85d5ed93c
|
||||
title: Step 38
|
||||
challengeType: 20
|
||||
dashedName: step-38
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If `num` is not in the row, the expression evaluates to `True` and it means the number is valid for insertion.
|
||||
|
||||
If `num` is in the row, the expression evaluates to `False` and insertion would violate the rules.
|
||||
|
||||
Return the value from the expression you wrote in the previous step, so that the validity of a number can be checked.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `return num not in self.board[row]` within `valid_in_row`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const valid = __helpers.python.getDef(tCode, "valid_in_row");
|
||||
const {function_body} = valid;
|
||||
assert.match(function_body, /return\s+num\s+not\s+in\s+self\.board\s*\[\s*row\s*\]/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
--fcc-editable-region--
|
||||
def valid_in_row(self, row, num):
|
||||
num not in self.board[row]
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,89 +0,0 @@
|
||||
---
|
||||
id: 6568c073d5f37fd99ab2ab0c
|
||||
title: Step 39
|
||||
challengeType: 20
|
||||
dashedName: step-39
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Next, you will create a method that checks if a number can be inserted in a specified column of the sudoku board by checking if the number is not already present in that column for any row.
|
||||
|
||||
For that, within the `Board` class, create a method named `valid_in_col`.
|
||||
|
||||
It should take three parameters:
|
||||
|
||||
- `self`: representing the instance of the class.
|
||||
- `col`: representing the column index.
|
||||
- `num`: representing the number to be checked.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have a `valid_in_col` method.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {block_body} = __helpers.python.getBlock("\n" + tCode, "class Board");
|
||||
const valid = __helpers.python.getDef(block_body, "valid_in_col");
|
||||
assert.exists(valid);
|
||||
```
|
||||
|
||||
The method should take three parameters: `self`, `col`, and `num`. Order matters
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_parameters} = __helpers.python.getDef(tCode, "valid_in_col");
|
||||
assert.match(function_parameters, /self\s*,\s*col\s*,\s*num/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,77 +0,0 @@
|
||||
---
|
||||
id: 6568c0a5edddc3daa65d20b2
|
||||
title: Step 40
|
||||
challengeType: 20
|
||||
dashedName: step-40
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now, you need to check if a given number is not equal to the number in the specified column of the current row.
|
||||
|
||||
For that, first, iterate over the rows of the 2D list `self.board` using a `for` loop in the range `0` to `8`. Use `row` as the iteration variable.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `for row in range(9)` within `valid_in_col`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const valid = __helpers.python.getDef(tCode, "valid_in_col");
|
||||
const {function_body} = valid;
|
||||
assert.match(function_body, /for\s+row\s+in\s+range\(\s*9\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
--fcc-editable-region--
|
||||
def valid_in_col(self, col, num):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,77 +0,0 @@
|
||||
---
|
||||
id: 6569d83fe4dcc614c2ff971d
|
||||
title: Step 41
|
||||
challengeType: 20
|
||||
dashedName: step-41
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
For each element in the specified column (`col`) of the current row (`row`), check whether the value at the current position in the 2D list is not equal to the provided `num`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `self.board[row][col] != num` within `valid_in_col`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const valid = __helpers.python.getDef(tCode, "valid_in_col");
|
||||
const {function_body} = valid;
|
||||
assert.match(function_body, /self\.board\s*\[\s*row\s*\]\s*\[\s*col\s*\]\s*!=\s*num/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
|
||||
--fcc-editable-region--
|
||||
def valid_in_col(self, col, num):
|
||||
|
||||
--fcc-editable-region--
|
||||
for row in range(9)
|
||||
```
|
||||
@@ -1,87 +0,0 @@
|
||||
---
|
||||
id: 6569d8a4b8d85515cbb1ce72
|
||||
title: Step 42
|
||||
challengeType: 20
|
||||
dashedName: step-42
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
This expression generates a list of boolean values representing whether the condition `self.board[row][col] != num` is `True` or `False` for each element in the specified column across all rows.
|
||||
|
||||
Pass this generator expression to the `all()` function to check if all the elements in the column are different from `num`.
|
||||
|
||||
Recall that the syntax of the `all` function is as follows:
|
||||
|
||||
```py
|
||||
all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
```
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `all(self.board[row][col] != num for row in range(9))` within `valid_in_col`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const valid = __helpers.python.getDef(tCode, "valid_in_col");
|
||||
const {function_body} = valid;
|
||||
assert.match(function_body, /all\s*\(\s*self\.board\s*\[\s*row\s*\]\s*\[\s*col\s*\]\s*!=\s*num\s+for\s+row\s+in\s+range\s*\(\s*9\s*\)\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
--fcc-editable-region--
|
||||
def valid_in_col(self, col, num):
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,78 +0,0 @@
|
||||
---
|
||||
id: 6569d946293d4f185e32e2da
|
||||
title: Step 43
|
||||
challengeType: 20
|
||||
dashedName: step-43
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Return the result of the `all()` function call.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should return the result of the `all()` function call.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const valid = __helpers.python.getDef(tCode, "valid_in_col");
|
||||
const {function_body} = valid;
|
||||
assert.match(function_body, /return\s+all\s*\(\s*self\.board\s*\[\s*row\s*\]\s*\[\s*col\s*\]\s*!=\s*num\s+for\s+row\s+in\s+range\s*\(\s*9\s*\)\s*\)/m);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
--fcc-editable-region--
|
||||
def valid_in_col(self, col, num):
|
||||
all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,96 +0,0 @@
|
||||
---
|
||||
id: 6569d98303af38193149b66e
|
||||
title: Step 44
|
||||
challengeType: 20
|
||||
dashedName: step-44
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Next, you will work on a method that checks if a number can be inserted in the 3x3 square.
|
||||
|
||||
Inside the `Board` class, create a method named `valid_in_square`.
|
||||
|
||||
It should take four parameters:
|
||||
|
||||
- `self`: represents the instance of the class.
|
||||
- `row`: represents the row index.
|
||||
- `col`: represents the column index.
|
||||
- `num`: represents the number to be checked.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have a `valid_in_square` method.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {block_body} = __helpers.python.getBlock("\n" + tCode, "class Board");
|
||||
const valid = __helpers.python.getDef(block_body, "valid_in_square");
|
||||
assert.exists(valid);
|
||||
```
|
||||
|
||||
The method should take four parameters: `self`, `row`, `col`, and `num`. Don't forget to add `pass` in the function body. Order matters.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_parameters} = __helpers.python.getDef(tCode, "valid_in_square");
|
||||
assert.match(function_parameters, /self\s*,\s*row\s*,\s*col\s*,\s*num/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,86 +0,0 @@
|
||||
---
|
||||
id: 6569d9dfd53db11b176d2963
|
||||
title: Step 45
|
||||
challengeType: 20
|
||||
dashedName: step-45
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now you need to calculate the starting row index for the 3x3 block in the board grid.
|
||||
|
||||
For that, ensure that the starting row index for each 3x3 block is a multiple of 3.
|
||||
|
||||
This can be achieved by this mathematical operation: `(row // 3) * 3`.
|
||||
Assign the result of this calculation to `row_start`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should assign the result of `(row // 3) * 3` to `row_start`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const valid = __helpers.python.getDef(tCode, "valid_in_square");
|
||||
const {function_body} = valid;
|
||||
assert.match(function_body, /row_start\s*=\s*\(\s*row\s*\/\/\s*3\s*\)\s*\*\s*3/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
--fcc-editable-region--
|
||||
def valid_in_square(self, row, col, num):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,87 +0,0 @@
|
||||
---
|
||||
id: 6569da02e7e2641be14ff922
|
||||
title: Step 46
|
||||
challengeType: 20
|
||||
dashedName: step-46
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Next, you need to calculate the starting column index for the 3x3 block in the board grid.
|
||||
|
||||
For that, ensure that the starting row index for each 3x3 block is a multiple of 3.
|
||||
|
||||
Similar to the previous step, this can be achieved by this mathematical operation: `(col // 3) * 3`.
|
||||
Assign the result of this calculation to `col_start`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should assign the result of `(col // 3) * 3` to `col_start`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const valid = __helpers.python.getDef(tCode, "valid_in_square");
|
||||
const {function_body} = valid;
|
||||
assert.match(function_body, /col_start\s*=\s*\(\s*col\s*\/\/\s*3\s*\)\s*\*\s*3/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
--fcc-editable-region--
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,83 +0,0 @@
|
||||
---
|
||||
id: 6569de93a5340b202667deda
|
||||
title: Step 47
|
||||
challengeType: 20
|
||||
dashedName: step-47
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Create a `for` loop that starts at `row_start` and ends just before `row_start + 3`. You can use the `range()` function to generate the sequence. As an example, if `row_start` is `3`, the loop will iterate over the numbers `3`, `4`, and `5`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `for row_no in range(row_start, row_start + 3):` within `valid_in_square`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const valid = __helpers.python.getDef(tCode, "valid_in_square");
|
||||
const {function_body} = valid;
|
||||
assert.match(function_body, /for\s+(\w+)\s+in\s+range\s*\(\s*row_start\s*,\s*row_start\s*\+\s*3\s*\)\s*:/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
--fcc-editable-region--
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,84 +0,0 @@
|
||||
---
|
||||
id: 6569def38470282151f873ce
|
||||
title: Step 48
|
||||
challengeType: 20
|
||||
dashedName: step-48
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the loop created in the previous step, nest another `for` loop to iterate over a sequence of three elements starting at `col_start`. Again, use the `range()` function to generate the sequence.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `for col_no in range(col_start, col_start + 3):` within `valid_in_square`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const valid = __helpers.python.getDef(tCode, "valid_in_square");
|
||||
const {function_body} = valid;
|
||||
assert.match(function_body, /for\s+(\w+)\s+in\s+range\s*\(\s*col_start\s*,\s*col_start\s*\+\s*3\s*\)\s*:/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
--fcc-editable-region--
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,87 +0,0 @@
|
||||
---
|
||||
id: 6569df1d6fb83d22623b38c5
|
||||
title: Step 49
|
||||
challengeType: 20
|
||||
dashedName: step-49
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The next step is to check if the specified number (`num`) is already present in the current cell of the 3x3 square.
|
||||
|
||||
Inside the inner `for` loop, create an `if` statement that checks if the current cell in `self.board` is equal to `num`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `if self.board[row_no][col_no] == num` within `valid_in_square`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const innerFor = __helpers.python.getBlock(tCode, "for col_no in range(col_start, col_start + 3)");
|
||||
const {block_body} = innerFor;
|
||||
assert.match(block_body, /if\s+self\.board\s*\[\s*row_no\s*\]\s*\[\s*col_no\s*\]\s*==\s*num\s*\:/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
--fcc-editable-region--
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,86 +0,0 @@
|
||||
---
|
||||
id: 6569df6916294723e01f0035
|
||||
title: Step 50
|
||||
challengeType: 20
|
||||
dashedName: step-50
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the `if` block, return `False` to indicate that the number cannot be inserted into the square.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should return `False` inside the `if` block.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const innerIf = __helpers.python.getBlock(tCode, "if self.board[row_no][col_no] == num");
|
||||
const {block_body} = innerIf;
|
||||
assert.match(block_body, /return\s+False/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
--fcc-editable-region--
|
||||
if self.board[row_no][col_no] == num:
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,91 +0,0 @@
|
||||
---
|
||||
id: 6569df9e20f74a251d482c5d
|
||||
title: Step 51
|
||||
challengeType: 20
|
||||
dashedName: step-51
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If the number is not present, it can be inserted into the square without violating the rules of sudoku.
|
||||
|
||||
Return `True` in that case, and pay attention to the indentation.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `return True` outwith the outermost `for` loop.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const valid = __helpers.python.getDef(tCode, "valid_in_square");
|
||||
const {function_body} = valid;
|
||||
const indent = function_body.match(/ +/)[0];
|
||||
const re = new RegExp(`^${indent}return\\s+True`, "m");
|
||||
assert.match(function_body, re);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
--fcc-editable-region--
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,104 +0,0 @@
|
||||
---
|
||||
id: 6569dffeee007f26d2b56d46
|
||||
title: Step 52
|
||||
challengeType: 20
|
||||
dashedName: step-52
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Within the `Board` class, create another method `is_valid`.
|
||||
It would take three parameters:
|
||||
|
||||
- `self` (representing the instance of the class),
|
||||
- `empty` (a tuple representing the row and column indices of an empty cell)
|
||||
- `num` (representing the number to be checked).
|
||||
|
||||
This method checks if a given number is a valid choice for an empty cell in the sudoku board by validating its compatibility with the row, column, and 3x3 square of the specified empty cell.
|
||||
|
||||
# --hints--
|
||||
|
||||
The method name should be `is_valid`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const board = __helpers.python.getBlock("\n" + tCode, "class Board");
|
||||
const valid = __helpers.python.getDef(board.block_body, "is_valid");
|
||||
assert.exists(valid);
|
||||
```
|
||||
|
||||
The method should take three parameters: `self`, `empty`, and `num`. Order matters
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const valid = __helpers.python.getDef(tCode, "is_valid");
|
||||
const {function_parameters} = valid;
|
||||
assert.match(function_parameters, /self\s*,\s*empty\s*,\s*num/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,89 +0,0 @@
|
||||
---
|
||||
id: 6569e2a01a97b231862ba2ff
|
||||
title: Step 53
|
||||
challengeType: 20
|
||||
dashedName: step-53
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the method, unpack the `empty` tuple into `row` and `col`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `row, col = empty` within `is_valid`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "is_valid");
|
||||
assert.match(function_body, /row\s*,\s*col\s*=\s*empty/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
--fcc-editable-region--
|
||||
def is_valid(self, empty, num):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,91 +0,0 @@
|
||||
---
|
||||
id: 6569e2e1944fe7329ab21c7f
|
||||
title: Step 54
|
||||
challengeType: 20
|
||||
dashedName: step-54
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Check if the number is valid for insertion in the specified row by calling `self.valid_in_row(row, num)`
|
||||
Assign the result to `valid_in_row`
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `valid_in_row = self.valid_in_row(row, num)` within `is_valid`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "is_valid");
|
||||
assert.match(function_body, /valid_in_row\s*=\s*self\.valid_in_row\s*\(\s*row\s*,\s*num\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
--fcc-editable-region--
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,93 +0,0 @@
|
||||
---
|
||||
id: 6569e309feb5d333867a034a
|
||||
title: Step 55
|
||||
challengeType: 20
|
||||
dashedName: step-55
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Check if the number is valid for insertion in the specified column by calling `self.valid_in_col(col, num)`
|
||||
|
||||
Assign the result to `valid_in_col`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `valid_in_col = self.valid_in_col(col, num)` within `is_valid`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "is_valid");
|
||||
assert.match(function_body, /valid_in_col\s*=\s*self\.valid_in_col\s*\(\s*col\s*,\s*num\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
--fcc-editable-region--
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,94 +0,0 @@
|
||||
---
|
||||
id: 6569e33a708a3834f6d4879b
|
||||
title: Step 56
|
||||
challengeType: 20
|
||||
dashedName: step-56
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Check if the number is valid for insertion in the 3x3 square that contains the specified cell by calling `self.valid_in_square(row, col, num)`.
|
||||
|
||||
Assign the result to `valid_in_square`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `valid_in_square = self.valid_in_square(row, col, num)` within `is_valid`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "is_valid");
|
||||
assert.match(function_body, /valid_in_square\s*=\s*self\.valid_in_square\s*\(\s*row\s*,\s*col\s*,\s*num\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
--fcc-editable-region--
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,93 +0,0 @@
|
||||
---
|
||||
id: 6569e37ec28e853628f18a86
|
||||
title: Step 57
|
||||
challengeType: 20
|
||||
dashedName: step-57
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Insert `valid_in_row`, `valid_in_col`, and `valid_in_square` into a list and pass it to the `all()` function. This will verify that all the function calls return `True`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `all([valid_in_row, valid_in_col, valid_in_square])` within `is_valid`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "is_valid");
|
||||
assert.match(function_body, /all\s*\(\s*\[\s*valid_in_row\s*,\s*valid_in_col\s*,\s*valid_in_square\s*\]\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
--fcc-editable-region--
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,91 +0,0 @@
|
||||
---
|
||||
id: 6569e3a134fea0371fa008de
|
||||
title: Step 58
|
||||
challengeType: 20
|
||||
dashedName: step-58
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now, return the result of the `all()` call.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should return the result of the `all()` call.
|
||||
|
||||
```js
|
||||
({ test: () => assert.match(code, /^\s{8}return\s+all\s*\(\s*\[\s*(valid_in_)(row|col|square)\s*,\s*\1(?!\2)(row|col|square)\s*,\s*\1(?!\2|\3)(row|col|square)\s*\]\s*\)/m) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
--fcc-editable-region--
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
all([valid_in_row, valid_in_col, valid_in_square])
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,105 +0,0 @@
|
||||
---
|
||||
id: 6569e3d1418b373839a0aa7b
|
||||
title: Step 59
|
||||
challengeType: 20
|
||||
dashedName: step-59
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Next, you will work on a method that attempts to solve the sudoku in-place, meaning it would modify the existing sudoku board rather than creating a new one.
|
||||
|
||||
Within the board class, create a method `solver` that takes one argument(`self`, representing the instance of the class).
|
||||
|
||||
# --hints--
|
||||
|
||||
Your method should be named `solver`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, "");
|
||||
const board = __helpers.python.getBlock("\n" + tCode, "class Board");
|
||||
const solver = __helpers.python.getDef(board.block_body, "solver");
|
||||
assert.exists(solver);
|
||||
```
|
||||
|
||||
You should add the parameter `self` to the method.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, "");
|
||||
const { function_parameters } = __helpers.python.getDef(tCode, "solver");
|
||||
assert.match(function_parameters, /self/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,102 +0,0 @@
|
||||
---
|
||||
id: 6569e41657a9923953aa7d3c
|
||||
title: Step 60
|
||||
challengeType: 20
|
||||
dashedName: step-60
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
First, check if there are any empty cells left in the sudoku board.
|
||||
|
||||
Use the `find_empty_cell` function call on `self`.
|
||||
|
||||
Also, use the walrus operator (:=) to assign the result of `self.find_empty_cell()` to the variable `next_empty`.
|
||||
|
||||
By using the walrus operator, you can combine the assignment and the conditional check into a single line, making the code more concise and readable.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `next_empty := self.find_empty_cell()` within the `solver` method.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solver");
|
||||
assert.match(function_body, /next_empty\s*:=\s*self\.find_empty_cell\(\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
--fcc-editable-region--
|
||||
def solver(self):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,96 +0,0 @@
|
||||
---
|
||||
id: 6569e481e67f123ad25c5d20
|
||||
title: Step 61
|
||||
challengeType: 20
|
||||
dashedName: step-61
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Place the condition in an `if` statement and check if it is `None`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `if (next_empty := self.find_empty_cell()) is None:` within `solver`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solver");
|
||||
assert.match(function_body, /if\s*\(\s*next_empty\s*:=\s*self\.find_empty_cell\(\s*\)\s*\)\s*is\s*None:/)
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
--fcc-editable-region--
|
||||
def solver(self):
|
||||
next_empty := self.find_empty_cell()
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,97 +0,0 @@
|
||||
---
|
||||
id: 6569f6b48716b5402504e216
|
||||
title: Step 62
|
||||
challengeType: 20
|
||||
dashedName: step-62
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If there are no empty cells (i.e., `next_empty` is `None`), the puzzle is solved. So, return `True`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should return `True` within the `if` statement.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solver");
|
||||
assert.match(function_body, /return\s*True/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
--fcc-editable-region--
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,98 +0,0 @@
|
||||
---
|
||||
id: 6569f6ebe558bd4136da96cc
|
||||
title: Step 63
|
||||
challengeType: 20
|
||||
dashedName: step-63
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Create an `else` block to cater the case where there are empty cells and the puzzle is unsolved.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have an `else` clause within `solver`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solver");
|
||||
assert.match(function_body, /else:/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
--fcc-editable-region--
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,100 +0,0 @@
|
||||
---
|
||||
id: 6569f70a66ccdc42097ca051
|
||||
title: Step 64
|
||||
challengeType: 20
|
||||
dashedName: step-64
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If there are still empty cells, create a loop in the `else` block that iterates over numbers from `1` to `9` (inclusive). Your loop should use the variable named `guess`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `for guess in range(1,10):` within the `else` block.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solver");
|
||||
const {block_body} = __helpers.python.getBlock(function_body, "else");
|
||||
assert.match(block_body, /for\s+\w+\s+in\s+range\(\s*1\s*,\s*10\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
--fcc-editable-region--
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,101 +0,0 @@
|
||||
---
|
||||
id: 6569f770fd7dc443d6293095
|
||||
title: Step 65
|
||||
challengeType: 20
|
||||
dashedName: step-65
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
For each number (`guess`), check if the number is a valid choice for the current empty cell using `self.is_valid(next_empty, guess)`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `self.is_valid(next_empty, guess)` within the `for` loop.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solver");
|
||||
const {block_body} = __helpers.python.getBlock(function_body, "for guess in range(1, 10)");
|
||||
assert.match(block_body, /self\.is_valid\(\s*next_empty\s*,\s*guess\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
--fcc-editable-region--
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,104 +0,0 @@
|
||||
---
|
||||
id: 6569f7c7f6954944d207775f
|
||||
title: Step 66
|
||||
challengeType: 20
|
||||
dashedName: step-66
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If the guess is valid, the method updates the sudoku board with the guess by assigning `guess` to the cell specified by next_empty.
|
||||
|
||||
Unpack the `next_empty` tuple to `row, col`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `row, col = next_empty` within the innermost `if` statement.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solver");
|
||||
const {block_body} = __helpers.python.getBlock(function_body, "if self.is_valid(next_empty, guess)");
|
||||
assert.match(block_body, /row\s*,\s*col\s*=\s*next_empty/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
--fcc-editable-region--
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
if self.is_valid(next_empty, guess):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,103 +0,0 @@
|
||||
---
|
||||
id: 6569f7f2fa74c045e95676ac
|
||||
title: Step 67
|
||||
challengeType: 20
|
||||
dashedName: step-67
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Access the cell at the given row and column in the sudoku board, and assign it the value of `guess`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `self.board[row][col] = guess` within the innermost `if` block.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solver");
|
||||
const {block_body} = __helpers.python.getBlock(function_body, "if self.is_valid(next_empty, guess)");
|
||||
assert.match(block_body, /self\.board\s*\[\s*row\s*\]\s*\[\s*col\s*\]\s*=\s*guess/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
--fcc-editable-region--
|
||||
if self.is_valid(next_empty, guess):
|
||||
row, col = next_empty
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,104 +0,0 @@
|
||||
---
|
||||
id: 6569fa5b9d507748bf4ec722
|
||||
title: Step 68
|
||||
challengeType: 20
|
||||
dashedName: step-68
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
While staying in the `if` block, recursively call `self.solver()` to try to solve the rest of the sudoku.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `self.solver()` within the innermost `if` block.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solver");
|
||||
const {block_body} = __helpers.python.getBlock(function_body, "if self.is_valid(next_empty, guess)");
|
||||
assert.match(block_body, /self\.solver\(\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
--fcc-editable-region--
|
||||
if self.is_valid(next_empty, guess):
|
||||
row, col = next_empty
|
||||
self.board[row][col] = guess
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,115 +0,0 @@
|
||||
---
|
||||
id: 6569fa85d8f9ed49c8dfb37d
|
||||
title: Step 69
|
||||
challengeType: 20
|
||||
dashedName: step-69
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If the recursive call to `self.solver()` returns `True`, it means the sudoku is solved.
|
||||
|
||||
If the recursive call returns `True`, return `True` from the method.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `if self.solver():` within the innermost `if` block.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solver");
|
||||
const {block_body} = __helpers.python.getBlock(function_body, "if self.is_valid(next_empty, guess)");
|
||||
assert.match(block_body, /if\s+self\.solver\(\s*\):/);
|
||||
```
|
||||
|
||||
You should have `return True` within `if self.solver():`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solver");
|
||||
const {block_body} = __helpers.python.getBlock(function_body, "if self.solver()");
|
||||
assert.match(block_body, /return\s+True/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
--fcc-editable-region--
|
||||
if self.is_valid(next_empty, guess):
|
||||
row, col = next_empty
|
||||
self.board[row][col] = guess
|
||||
self.solver()
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,108 +0,0 @@
|
||||
---
|
||||
id: 6569fabbfe1c094ad838ec4c
|
||||
title: Step 70
|
||||
challengeType: 20
|
||||
dashedName: step-70
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If `self.solver()` returns `False`, this means the `guess` led to an unsolvable sudoku.
|
||||
|
||||
Outside the innermost `if` block, undo the guess by setting the cell value back to `0`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `self.board[row][col] = 0` outside the innermost `if` block.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solver");
|
||||
const {block_body} = __helpers.python.getBlock(function_body, "if self.is_valid(next_empty, guess)");
|
||||
assert.match(block_body, /self\.board\s*\[\s*row\s*\]\s*\[\s*col\s*\]\s*=\s*0/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
--fcc-editable-region--
|
||||
if self.is_valid(next_empty, guess):
|
||||
row, col = next_empty
|
||||
self.board[row][col] = guess
|
||||
if self.solver():
|
||||
return True
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,106 +0,0 @@
|
||||
---
|
||||
id: 6569fbbfee025a4e850b6eaf
|
||||
title: Step 71
|
||||
challengeType: 20
|
||||
dashedName: step-71
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Make your method return `False` when none of the guesses leads to a solution.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should return `False` within the outermost `else` block.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solver");
|
||||
assert.match(function_body, /return\s+False/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
--fcc-editable-region--
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
if self.is_valid(next_empty, guess):
|
||||
row, col = next_empty
|
||||
self.board[row][col] = guess
|
||||
if self.solver():
|
||||
return True
|
||||
self.board[row][col] = 0
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,128 +0,0 @@
|
||||
---
|
||||
id: 6569fc21837cab5029d82e26
|
||||
title: Step 72
|
||||
challengeType: 20
|
||||
dashedName: step-72
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Outside the class definition, create a function to print and solve the sudoku board.
|
||||
|
||||
Name it `solve_sudoku`. It should take a single parameter `board` that is a 2D list.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should not have a method `solve_sudoku` within the `Board` class.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {block_body} = __helpers.python.getBlock("\n" + tCode, "class Board");
|
||||
const solve = __helpers.python.getDef(block_body, "solve_sudoku");
|
||||
assert.notExists(solve);
|
||||
```
|
||||
|
||||
You should have a function named `solve_sudoku`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const solve = __helpers.python.getDef(tCode, "solve_sudoku");
|
||||
assert.exists(solve);
|
||||
```
|
||||
|
||||
The method should take a single `board` parameter.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_parameters} = __helpers.python.getDef(tCode, "solve_sudoku");
|
||||
assert.match(function_parameters, /board/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
if self.is_valid(next_empty, guess):
|
||||
row, col = next_empty
|
||||
self.board[row][col] = guess
|
||||
if self.solver():
|
||||
return True
|
||||
self.board[row][col] = 0
|
||||
|
||||
return False
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
```
|
||||
@@ -1,112 +0,0 @@
|
||||
---
|
||||
id: 6569fc63a404c8519d918095
|
||||
title: Step 73
|
||||
challengeType: 20
|
||||
dashedName: step-73
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the `solve_sudoku` function, create a `gameboard` variable and assign it an instance of the `Board` class passing `board` as the argument.
|
||||
|
||||
This initializes the sudoku board with the given initial state.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `gameboard = Board(board)` within the `solve_sudoku` function.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solve_sudoku");
|
||||
assert.match(function_body, /gameboard\s*=\s*Board\(\s*board\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
if self.is_valid(next_empty, guess):
|
||||
row, col = next_empty
|
||||
self.board[row][col] = guess
|
||||
if self.solver():
|
||||
return True
|
||||
self.board[row][col] = 0
|
||||
|
||||
return False
|
||||
|
||||
--fcc-editable-region--
|
||||
def solve_sudoku(board):
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,113 +0,0 @@
|
||||
---
|
||||
id: 6569fca3cd7a9f52f322a298
|
||||
title: Step 74
|
||||
challengeType: 20
|
||||
dashedName: step-74
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now, add another `print()` call passing `gameboard` as the argument to print the current state of the sudoku board.
|
||||
|
||||
Add a `print` call to print the following: `f'\nPuzzle to solve:\n{gameboard}'`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `print(f'\nPuzzle to solve:\n{gameboard}')` within the `solve_sudoku` function.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solve_sudoku");
|
||||
assert.match(function_body, /print\(\s*f'\\nPuzzle to solve:\\n\{gameboard\}'\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
if self.is_valid(next_empty, guess):
|
||||
row, col = next_empty
|
||||
self.board[row][col] = guess
|
||||
if self.solver():
|
||||
return True
|
||||
self.board[row][col] = 0
|
||||
|
||||
return False
|
||||
|
||||
--fcc-editable-region--
|
||||
def solve_sudoku(board):
|
||||
gameboard = Board(board)
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,124 +0,0 @@
|
||||
---
|
||||
id: 6569fd01dab2ea547d98f093
|
||||
title: Step 75
|
||||
challengeType: 20
|
||||
dashedName: step-75
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Create an `if` statement that checks if the `solver()` method call from the `gameboard` object returns `True`.
|
||||
|
||||
Then, add a `print()` call inside the `if` block passing the following string: `'\nSolved puzzle:'`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `if gameboard.solver():` within the `solve_sudoku` function.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solve_sudoku");
|
||||
const ifBlock = __helpers.python.getBlock(function_body, /if\s+gameboard\.solver\s*\(\s*\)\s*/);
|
||||
assert.exists(ifBlock);
|
||||
```
|
||||
|
||||
You should have `print('\nSolved puzzle:')` within the `if` block.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solve_sudoku");
|
||||
const {block_body} = __helpers.python.getBlock(function_body, /if\s+gameboard\.solver\s*\(\s*\)\s*/);
|
||||
assert.match(block_body, /print\s*\(\s*("|')\\nSolved puzzle:\1\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
if self.is_valid(next_empty, guess):
|
||||
row, col = next_empty
|
||||
self.board[row][col] = guess
|
||||
if self.solver():
|
||||
return True
|
||||
self.board[row][col] = 0
|
||||
|
||||
return False
|
||||
|
||||
--fcc-editable-region--
|
||||
def solve_sudoku(board):
|
||||
gameboard = Board(board)
|
||||
print(f'\nPuzzle to solve:\n{gameboard}')
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,115 +0,0 @@
|
||||
---
|
||||
id: 6569fd352879475599d0ec66
|
||||
title: Step 76
|
||||
challengeType: 20
|
||||
dashedName: step-76
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Add another `print` call to print the current state of the board.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `print(gameboard)` within the `if` statement.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solve_sudoku");
|
||||
const {block_body} = __helpers.python.getBlock(function_body, /if\s+gameboard\.solver\s*\(\s*\)\s*/);
|
||||
assert.match(block_body, /print\s*\(\s*gameboard\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
if self.is_valid(next_empty, guess):
|
||||
row, col = next_empty
|
||||
self.board[row][col] = guess
|
||||
if self.solver():
|
||||
return True
|
||||
self.board[row][col] = 0
|
||||
|
||||
return False
|
||||
|
||||
def solve_sudoku(board):
|
||||
gameboard = Board(board)
|
||||
print(f'\nPuzzle to solve:\n{gameboard}')
|
||||
--fcc-editable-region--
|
||||
if gameboard.solver():
|
||||
print('\nSolved puzzle:')
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,125 +0,0 @@
|
||||
---
|
||||
id: 6569fd6d3cb95856c9ed2190
|
||||
title: Step 77
|
||||
challengeType: 20
|
||||
dashedName: step-77
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Create an `else` clause and print the following string inside the new `else` block: `'\nThe provided puzzle is unsolvable.'`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have an `else` clause within `solve_sudoku`.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solve_sudoku");
|
||||
const elseBlock = __helpers.python.getBlock(function_body, /else\s*/);
|
||||
assert.exists(elseBlock);
|
||||
```
|
||||
|
||||
You should have `print('\nThe provided puzzle is unsolvable.')` within the `else` block.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solve_sudoku");
|
||||
const {block_body} = __helpers.python.getBlock(function_body, /else\s*/);
|
||||
assert.match(block_body, /print\s*\(\s*("|')\\nThe provided puzzle is unsolvable.\1\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
if self.is_valid(next_empty, guess):
|
||||
row, col = next_empty
|
||||
self.board[row][col] = guess
|
||||
if self.solver():
|
||||
return True
|
||||
self.board[row][col] = 0
|
||||
|
||||
return False
|
||||
|
||||
--fcc-editable-region--
|
||||
def solve_sudoku(board):
|
||||
gameboard = Board(board)
|
||||
print(f'\nPuzzle to solve:\n{gameboard}')
|
||||
if gameboard.solver():
|
||||
print('\nSolved puzzle:')
|
||||
print(gameboard)
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,118 +0,0 @@
|
||||
---
|
||||
id: 6569fdc59fe1b658bc9e23a4
|
||||
title: Step 78
|
||||
challengeType: 20
|
||||
dashedName: step-78
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
In the end, return your instance of the `Board` class, which represents the final state of the sudoku board after attempting to solve it.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `return gameboard` within the `solve_sudoku` function.
|
||||
|
||||
```js
|
||||
const tCode = code.replace(/\r/g, '');
|
||||
const {function_body} = __helpers.python.getDef(tCode, "solve_sudoku");
|
||||
assert.match(function_body, /return\s+gameboard/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
if self.is_valid(next_empty, guess):
|
||||
row, col = next_empty
|
||||
self.board[row][col] = guess
|
||||
if self.solver():
|
||||
return True
|
||||
self.board[row][col] = 0
|
||||
|
||||
return False
|
||||
|
||||
--fcc-editable-region--
|
||||
def solve_sudoku(board):
|
||||
gameboard = Board(board)
|
||||
print(f'\nPuzzle to solve:\n{gameboard}')
|
||||
if gameboard.solver():
|
||||
print('\nSolved puzzle:')
|
||||
print(gameboard)
|
||||
|
||||
else:
|
||||
print('\nThe provided puzzle is unsolvable.')
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -1,246 +0,0 @@
|
||||
---
|
||||
id: 6569fe0fe5b5425a1bb1f534
|
||||
title: Step 79
|
||||
challengeType: 20
|
||||
dashedName: step-79
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now it's time to play the game!
|
||||
|
||||
A puzzle has been given in the code.
|
||||
|
||||
Call the `solve_sudoku` method with `puzzle` as input.
|
||||
|
||||
Now, you can see the solved puzzle as the output.
|
||||
|
||||
With this, you are finished with building the sudoku solver!
|
||||
|
||||
# --hints--
|
||||
|
||||
Call the `solve_sudoku` method with `puzzle` as input.
|
||||
|
||||
```js
|
||||
assert.match(code, /solve_sudoku\(\s*puzzle\s*\)/);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
if self.is_valid(next_empty, guess):
|
||||
row, col = next_empty
|
||||
self.board[row][col] = guess
|
||||
if self.solver():
|
||||
return True
|
||||
self.board[row][col] = 0
|
||||
|
||||
return False
|
||||
|
||||
def solve_sudoku(board):
|
||||
gameboard = Board(board)
|
||||
print(f'\nPuzzle to solve:\n{gameboard}')
|
||||
if gameboard.solver():
|
||||
print('\nSolved puzzle:')
|
||||
print(gameboard)
|
||||
|
||||
else:
|
||||
print('\nThe provided puzzle is unsolvable.')
|
||||
return gameboard
|
||||
--fcc-editable-region--
|
||||
puzzle = [
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def __str__(self):
|
||||
upper_lines = f'\n╔═══{"╤═══"*2}{"╦═══"}{"╤═══"*2}{"╦═══"}{"╤═══"*2}╗\n'
|
||||
middle_lines = f'╟───{"┼───"*2}{"╫───"}{"┼───"*2}{"╫───"}{"┼───"*2}╢\n'
|
||||
lower_lines = f'╚═══{"╧═══"*2}{"╩═══"}{"╧═══"*2}{"╩═══"}{"╧═══"*2}╝\n'
|
||||
board_string = upper_lines
|
||||
for index, line in enumerate(self.board):
|
||||
row_list = []
|
||||
for square_no, part in enumerate([line[:3], line[3:6], line[6:]], start=1):
|
||||
row_square = '|'.join(str(item) for item in part)
|
||||
row_list.extend(row_square)
|
||||
if square_no != 3:
|
||||
row_list.append('║')
|
||||
|
||||
row = f'║ {" ".join(row_list)} ║\n'
|
||||
row_empty = row.replace('0', ' ')
|
||||
board_string += row_empty
|
||||
|
||||
if index < 8:
|
||||
if index % 3 == 2:
|
||||
board_string += f'╠═══{"╪═══"*2}{"╬═══"}{"╪═══"*2}{"╬═══"}{"╪═══"*2}╣\n'
|
||||
else:
|
||||
board_string += middle_lines
|
||||
else:
|
||||
board_string += lower_lines
|
||||
|
||||
return board_string
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
def valid_in_row(self, row, num):
|
||||
return num not in self.board[row]
|
||||
|
||||
def valid_in_col(self, col, num):
|
||||
return all(
|
||||
self.board[row][col] != num
|
||||
for row in range(9)
|
||||
)
|
||||
|
||||
def valid_in_square(self, row, col, num):
|
||||
row_start = (row // 3) * 3
|
||||
col_start=(col // 3) * 3
|
||||
for row_no in range(row_start, row_start + 3):
|
||||
for col_no in range(col_start, col_start + 3):
|
||||
if self.board[row_no][col_no] == num:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self, empty, num):
|
||||
row, col = empty
|
||||
valid_in_row = self.valid_in_row(row, num)
|
||||
valid_in_col = self.valid_in_col(col, num)
|
||||
valid_in_square = self.valid_in_square(row, col, num)
|
||||
return all([valid_in_row, valid_in_col, valid_in_square])
|
||||
|
||||
def solver(self):
|
||||
if (next_empty := self.find_empty_cell()) is None:
|
||||
return True
|
||||
else:
|
||||
for guess in range(1, 10):
|
||||
if self.is_valid(next_empty, guess):
|
||||
row, col = next_empty
|
||||
self.board[row][col] = guess
|
||||
if self.solver():
|
||||
return True
|
||||
self.board[row][col] = 0
|
||||
|
||||
return False
|
||||
|
||||
def solve_sudoku(board):
|
||||
gameboard = Board(board)
|
||||
print('\nPuzzle to solve:')
|
||||
print(gameboard)
|
||||
if gameboard.solver():
|
||||
print('\nSolved puzzle:')
|
||||
print(gameboard)
|
||||
|
||||
else:
|
||||
print('\nThe provided puzzle is unsolvable.')
|
||||
return gameboard
|
||||
|
||||
puzzle = [
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
|
||||
solve_sudoku(puzzle)
|
||||
```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
id: 656873ffdc638f7e290f60de
|
||||
id: 66068fb0bfddba2b7977eb60
|
||||
title: Step 1
|
||||
challengeType: 20
|
||||
dashedName: step-1
|
||||
@@ -11,20 +11,21 @@ In this project, you will learn about classes and objects by building a sudoku p
|
||||
|
||||
In Python, a class is a blueprint for creating objects. Objects created from a class are instances of that class. You can create a class using this syntax:
|
||||
|
||||
```js
|
||||
```py
|
||||
class ClassName:
|
||||
pass
|
||||
```
|
||||
|
||||
First, you will create a 9x9 board by using classes and then populate it with the puzzle values.
|
||||
Where `class` is the keyword required to define the class and `ClassName` is the name of the class, written by convention in *PascalCase*.
|
||||
|
||||
Begin by creating a `Board` class.
|
||||
|
||||
# --hints--
|
||||
|
||||
Your class should be named `Board`.
|
||||
You should create a class named `Board`.
|
||||
|
||||
```js
|
||||
assert.match(code, /class\s+Board\s*\:/);
|
||||
({ test: () => assert(runPython(`_Node(_code).has_class("Board")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
id: 66069167b3307b2f4067b22b
|
||||
title: Step 2
|
||||
challengeType: 20
|
||||
dashedName: step-2
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
A new instance of a class is created by using the function notation, which involves appending a pair of parentheses to the class name.
|
||||
|
||||
Outside the class definition, create an instance of the `Board` class and assign it to a variable named `gameboard`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should declare a variable `gameboard` outside the `Board` class.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).has_variable("gameboard")`)) })
|
||||
```
|
||||
|
||||
Your `gameboard` variable should have the value of `Board()`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_variable("gameboard").is_equivalent("gameboard = Board()")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Board:
|
||||
pass
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
id: 6606927d010be4300a4e5330
|
||||
title: Step 3
|
||||
challengeType: 20
|
||||
dashedName: step-3
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The instantiation creates an empty object. But classes can have methods, which are like local functions for each instance. Within a class, methods are declared as follows:
|
||||
|
||||
```py
|
||||
class ClassName:
|
||||
def method_name():
|
||||
pass
|
||||
```
|
||||
|
||||
Inside the `Board` class, replace `pass` with an empty method `spam`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should define a method named `spam` inside the `Board` class.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_class("Board").has_function("spam")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Board:
|
||||
pass
|
||||
|
||||
gameboard = Board()
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
id: 6606933d6813a8308c962dd1
|
||||
title: Step 4
|
||||
challengeType: 20
|
||||
dashedName: step-4
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
In order to be an instance method, a method requires a special parameter, named `self` by convention. This parameter is a reference to the instance of the class and must always be the first parameter.
|
||||
|
||||
Add a `self` parameter to your `spam` method.
|
||||
|
||||
# --hints--
|
||||
|
||||
Your `spam` method should have a `self` parameter.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_class("Board").find_function("spam").has_args("self")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Board:
|
||||
def spam():
|
||||
pass
|
||||
|
||||
gameboard = Board()
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
id: 660699119472f332798860ad
|
||||
title: Step 5
|
||||
challengeType: 20
|
||||
dashedName: step-5
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now, replace `pass` with a `print` call and pass it the string `'Spam!'`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should delete `pass` and print the string `'Spam!'` within the `spam` method.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_class("Board").find_function("spam").find_body().is_equivalent("print('Spam!')")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Board:
|
||||
def spam(self):
|
||||
pass
|
||||
|
||||
gameboard = Board()
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
id: 660699aabc59c532f2d556e5
|
||||
title: Step 6
|
||||
challengeType: 20
|
||||
dashedName: step-6
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
To call an instance method, you need to use dot notation:
|
||||
|
||||
```py
|
||||
instance_name.method_name()
|
||||
```
|
||||
|
||||
Where `instance_name` is the instance or object, and `method_name` is the method you want to call.
|
||||
|
||||
Call the `spam` method of the `gameboard` object.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should call the `spam` method of the `gameboard` object with `gameboard.spam()`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).has_call("gameboard.spam()")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Board:
|
||||
def spam(self):
|
||||
print('Spam!')
|
||||
|
||||
gameboard = Board()
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
id: 66069b0b36053733a2f012fe
|
||||
title: Step 7
|
||||
challengeType: 20
|
||||
dashedName: step-7
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now, delete your `spam` call.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should not have `gameboard.spam()` in your code.
|
||||
|
||||
```js
|
||||
({ test: () => assert.isFalse(runPython(`_Node(_code).has_call("gameboard.spam()")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Board:
|
||||
def spam(self):
|
||||
print('Spam!')
|
||||
|
||||
gameboard = Board()
|
||||
gameboard.spam()
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
id: 66069b992c1c5e3451f3deb0
|
||||
title: Step 8
|
||||
challengeType: 20
|
||||
dashedName: step-8
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The instantiation creates an empty object. The `__init__` method is a special method that allows you to instantiate an object to a customized state. When a class implements an `__init__` method, `__init__` is automatically called upon instantiation.
|
||||
|
||||
Inside your `Board` class, delete the `spam` method and replace it with an `__init__` method that includes a `self` parameter.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should not have a `spam` method in your `Board` class.
|
||||
|
||||
```js
|
||||
({ test: () => assert.isFalse(runPython(`_Node(_code).find_class("Board").has_function("spam")`)) })
|
||||
```
|
||||
|
||||
You should define an `__init__` method in your `Board` class.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_class("Board").has_function("__init__")`)) })
|
||||
```
|
||||
|
||||
Your `__init__` method should have a `self` parameter.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_class("Board").find_function("__init__").has_args("self")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Board:
|
||||
def spam(self):
|
||||
print('Spam!')
|
||||
|
||||
gameboard = Board()
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
id: 66069d65162e61357c793e0c
|
||||
title: Step 9
|
||||
challengeType: 20
|
||||
dashedName: step-9
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The sudoku puzzle to solve will be a list of lists, as the following:
|
||||
|
||||
```py
|
||||
[
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
```
|
||||
|
||||
Note that the empty cells are filled with a zero.
|
||||
|
||||
Declare a `puzzle` variable and assign it the list of lists in the example above.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should declare a variable `puzzle` and assign it the provided 2D-list.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_variable("puzzle").is_equivalent("puzzle = [[0, 0, 2, 0, 0, 8, 0, 0, 0], [0, 0, 0, 0, 0, 3, 7, 6, 2], [4, 3, 0, 0, 0, 0, 8, 0, 0], [0, 5, 0, 0, 3, 0, 0, 9, 0], [0, 4, 0, 0, 0, 0, 0, 2, 6], [0, 0, 0, 4, 6, 7, 0, 0, 0], [0, 8, 6, 7, 0, 4, 0, 0, 0], [0, 0, 0, 5, 1, 9, 0, 0, 8], [1, 7, 0, 0, 0, 6, 0, 0, 5]]")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
|
||||
class Board:
|
||||
def __init__(self):
|
||||
pass
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
gameboard = Board()
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
id: 66069e5759b800364707988e
|
||||
title: Step 10
|
||||
challengeType: 20
|
||||
dashedName: step-10
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Going back to the `__init__` method, it requires an additional parameter representing the puzzle to solve.
|
||||
|
||||
Add a second parameter named `board` to the `__init__` method and fix the instantiation of `gameboard` by passing it the `puzzle` list as you would pass an argument to a function call.
|
||||
|
||||
# --hints--
|
||||
|
||||
Your `__init__` method should have two parameters in the order: `self`, and `board`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_class("Board").find_function("__init__").has_args("self, board")`)) })
|
||||
```
|
||||
|
||||
Your `gameboard` variable should have the value of `Board(puzzle)`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_variable("gameboard").is_equivalent("gameboard = Board(puzzle)")`)) })
|
||||
```
|
||||
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Board:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
puzzle = [
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
|
||||
gameboard = Board()
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
id: 66069f86f58f85371d47123e
|
||||
title: Step 11
|
||||
challengeType: 20
|
||||
dashedName: step-11
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
An attribute is a variable associated with an object, which is used to store data as regular variables.
|
||||
|
||||
Inside the `__init__` method, assign the `board` parameter (which is passed when creating an instance of the `Board` class) to an instance attribute `board` using `self.board`.
|
||||
|
||||
`self.board` refers to the `board` attribute of the instance of the class. It's a variable that belongs to the object created from the `Board` class.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should delete `pass` and assign the `board` parameter to `self.board` inside the `__init__` method.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_class("Board").find_function("__init__").find_body().is_equivalent("self.board = board")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
pass
|
||||
|
||||
puzzle = [
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
|
||||
gameboard = Board(puzzle)
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
id: 6606a219f9efbf38ad496f67
|
||||
title: Step 12
|
||||
challengeType: 20
|
||||
dashedName: step-12
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
You can also use dot notation to access an instance attribute.
|
||||
|
||||
Outside the `Board` class, after initializing the `gameboard` object, use `gameboard.board` to access the `board` attribute of your `gameboard` object and print the result to the screen.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should print `gameboard.board`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).has_call("print(gameboard.board)")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
puzzle = [
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
|
||||
gameboard = Board(puzzle)
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
id: 6606a2f8a6a36f39518e0439
|
||||
title: Step 13
|
||||
challengeType: 20
|
||||
dashedName: step-13
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
As you can see, the board is printed on the screen. Now, delete your `print` call.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should not have `print(gameboard.board)` in your code.
|
||||
|
||||
```js
|
||||
({ test: () => assert.isFalse(runPython(`_Node(_code).has_call("print(gameboard.board)")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
puzzle = [
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
|
||||
gameboard = Board(puzzle)
|
||||
print(gameboard.board)
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
id: 6606a3ccb1eea93a23c066bf
|
||||
title: Step 14
|
||||
challengeType: 20
|
||||
dashedName: step-14
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now you'll work on a method that finds the empty cells in the sudoku board.
|
||||
|
||||
Within the `Board` class, create an empty method named `find_empty_cell` and give it a `self` parameter.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should define a method named `find_empty_cell` inside your `Board` class.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_class("Board").has_function("find_empty_cell")`)) })
|
||||
```
|
||||
|
||||
Your `find_empty_cell` method should have a parameter `self`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_class("Board").find_function("find_empty_cell").has_args("self")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
--fcc-editable-region--
|
||||
puzzle = [
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
|
||||
gameboard = Board(puzzle)
|
||||
```
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
id: 6606a4641ec48b3a9fe8c2fc
|
||||
title: Step 15
|
||||
challengeType: 20
|
||||
dashedName: step-15
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The `enumerate` built-in function takes an iterable as its argument and returns an enumerate object you can iterate over.
|
||||
It provides the count (which by default starts at zero) and the value from the iterable.
|
||||
|
||||
```py
|
||||
iterable = ['a', 'b', 'c']
|
||||
for i, j in enumerate(iterable):
|
||||
print(i, j)
|
||||
```
|
||||
|
||||
The loop from the example above would output the tuples `0, a`, `1, b`, and `2, c`.
|
||||
|
||||
Inside the `find_empty_cell` method, replace `pass` with a `for` loop that uses the `enumerate()` function to iterate over each row in the sudoku board. Use `row` as the index of the current row and `contents` for the elements of the current row.
|
||||
|
||||
|
||||
# --hints--
|
||||
|
||||
You should replace `pass` with a `for` loop that iterates over `enumerate(self.board)`. Use `row` and `contents` as the loop variables.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_class("Board").find_function("find_empty_cell").find_body().is_equivalent("for row, contents in enumerate(self.board):\\n pass")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
--fcc-editable-region--
|
||||
def find_empty_cell(self):
|
||||
pass
|
||||
--fcc-editable-region--
|
||||
puzzle = [
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
|
||||
gameboard = Board(puzzle)
|
||||
```
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
id: 6606b0d602d1e33e81bcef0d
|
||||
title: Step 16
|
||||
challengeType: 20
|
||||
dashedName: step-16
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
You need to locate the empty cell, which is filled with the number zero.
|
||||
|
||||
Replace `pass` with a variable `col` and assign it a call to `.index()` on `contents`, passing `0` as the argument.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should replace `pass` with a variable `col` and assign it `contents.index(0)`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_class("Board").find_function("find_empty_cell").find_for_loops()[0].find_bodies()[0].is_equivalent("col = contents.index(0)")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
--fcc-editable-region--
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
pass
|
||||
--fcc-editable-region--
|
||||
puzzle = [
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
|
||||
gameboard = Board(puzzle)
|
||||
```
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
id: 6606b224a69a293f98f8db8f
|
||||
title: Step 17
|
||||
challengeType: 20
|
||||
dashedName: step-17
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The `.index()` method raises a `ValueError` exception when the value is not found. To prevent the program from halting execution, you'll nest this line of code inside a `try` block. The `try` statement is used to encapsulate code that might raise an exception. The `except` clause, on the other hand, offers alternative code to execute if an exception occurs:
|
||||
|
||||
```py
|
||||
try:
|
||||
<code>
|
||||
except:
|
||||
<code>
|
||||
```
|
||||
|
||||
Put the assignment of `col` inside a `try` block. Then, create an `except` clause and fill its body with `pass`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should put the assignment of `col` inside a `try` block and create an `except` clause.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_class("Board").find_function("find_empty_cell").find_for_loops()[0].find_bodies()[0].is_equivalent("try:\\n col = contents.index(0)\\nexcept:\\n pass")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
--fcc-editable-region--
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
col = contents.index(0)
|
||||
--fcc-editable-region--
|
||||
puzzle = [
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
|
||||
gameboard = Board(puzzle)
|
||||
```
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
id: 6606b63c0fd55e4314d2ec85
|
||||
title: Step 18
|
||||
challengeType: 20
|
||||
dashedName: step-18
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If `0` is found, the function should immediately return a tuple containing the row index and column index of the empty cell.
|
||||
|
||||
Inside the `try` block, after the assignment of `col`, return `row, col`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should return `row, col` from the `try` block.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_class("Board").find_function("find_empty_cell").find_for_loops()[0].find_bodies()[0].is_equivalent("try:\\n col = contents.index(0)\\n return row, col\\nexcept:\\n pass")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
--fcc-editable-region--
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
except:
|
||||
pass
|
||||
--fcc-editable-region--
|
||||
puzzle = [
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
|
||||
gameboard = Board(puzzle)
|
||||
```
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
id: 6606b6b7760d0643c3b4eb29
|
||||
title: Step 19
|
||||
challengeType: 20
|
||||
dashedName: step-19
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If the code inside the `try` block raises an exception, you want the program to continue running, and the `pass` statement accomplishes this.
|
||||
|
||||
Although this code works, specifying the exception type after the `except` keyword is considered good practice.
|
||||
|
||||
Since you know that a `ValueError` might be raised, leave a space after the `except` keyword and add `ValueError` after that.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have `except ValueError:` in your code.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_class("Board").find_function("find_empty_cell").find_for_loops()[0].find_bodies()[0].is_equivalent("try:\\n col = contents.index(0)\\n return row, col\\nexcept ValueError:\\n pass")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
--fcc-editable-region--
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except:
|
||||
pass
|
||||
--fcc-editable-region--
|
||||
puzzle = [
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
|
||||
gameboard = Board(puzzle)
|
||||
```
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
id: 6606b8d31356fe4563f0e99c
|
||||
title: Step 20
|
||||
challengeType: 20
|
||||
dashedName: step-20
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Outside the `for` loop, return `None`. This handles the case in which no empty cell is found, indicating that the sudoku board is completely filled.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should return `None` after the `for` loop.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_class("Board").find_function("find_empty_cell").has_return("None")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
--fcc-editable-region--
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
--fcc-editable-region--
|
||||
puzzle = [
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
|
||||
gameboard = Board(puzzle)
|
||||
```
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
id: 6606b961ebcf04460f8af76e
|
||||
title: Step 21
|
||||
challengeType: 20
|
||||
dashedName: step-21
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Test that the `find_empty_cell` method works properly by calling it on `gameboard` and printing the result.
|
||||
|
||||
Note that, although `find_empty_cell` is defined with one parameter, you must not give it a value by passing an argument to the function call, since `self` is automatically passed in as the object you are calling the method on.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should print `gameboard.find_empty_cell()`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).has_call("print(gameboard.find_empty_cell())")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Board:
|
||||
def __init__(self, board):
|
||||
self.board = board
|
||||
|
||||
def find_empty_cell(self):
|
||||
for row, contents in enumerate(self.board):
|
||||
try:
|
||||
col = contents.index(0)
|
||||
return row, col
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
|
||||
puzzle = [
|
||||
[0, 0, 2, 0, 0, 8, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 3, 7, 6, 2],
|
||||
[4, 3, 0, 0, 0, 0, 8, 0, 0],
|
||||
[0, 5, 0, 0, 3, 0, 0, 9, 0],
|
||||
[0, 4, 0, 0, 0, 0, 0, 2, 6],
|
||||
[0, 0, 0, 4, 6, 7, 0, 0, 0],
|
||||
[0, 8, 6, 7, 0, 4, 0, 0, 0],
|
||||
[0, 0, 0, 5, 1, 9, 0, 0, 8],
|
||||
[1, 7, 0, 0, 0, 6, 0, 0, 5]
|
||||
]
|
||||
|
||||
gameboard = Board(puzzle)
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user