Compare commits

...

6 Commits

Author SHA1 Message Date
Ronald Ngounou
f82260cbce
Merge 17264a496b into e3bd7721c8 2024-11-16 05:46:10 -05:00
Christian Clauss
e3bd7721c8
validate_filenames.py Shebang python for Windows (#12371) 2024-11-15 14:59:14 +01:00
pre-commit-ci[bot]
e3f3d668be
[pre-commit.ci] pre-commit autoupdate (#12370)
* [pre-commit.ci] pre-commit autoupdate

updates:
- [github.com/astral-sh/ruff-pre-commit: v0.7.2 → v0.7.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.7.2...v0.7.3)
- [github.com/abravalheri/validate-pyproject: v0.22 → v0.23](https://github.com/abravalheri/validate-pyproject/compare/v0.22...v0.23)

* Update sudoku_solver.py

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Christian Clauss <cclauss@me.com>
2024-11-11 21:05:50 +01:00
pre-commit-ci[bot]
3e9ca92ca9
[pre-commit.ci] pre-commit autoupdate (#12349)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.7.1 → v0.7.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.7.1...v0.7.2)
- [github.com/tox-dev/pyproject-fmt: v2.4.3 → v2.5.0](https://github.com/tox-dev/pyproject-fmt/compare/v2.4.3...v2.5.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-11-04 21:09:03 +01:00
Ronald Ngounou
17264a496b test: Add two testcases in sigmid.py 2024-10-06 02:03:32 -04:00
Ronald Ngounou
adda95ea58 Update docstrings in the functions definitions. 2024-10-05 18:42:43 -04:00
4 changed files with 54 additions and 23 deletions

View File

@ -16,7 +16,7 @@ repos:
- id: auto-walrus
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.1
rev: v0.7.3
hooks:
- id: ruff
- id: ruff-format
@ -29,7 +29,7 @@ repos:
- tomli
- repo: https://github.com/tox-dev/pyproject-fmt
rev: "v2.4.3"
rev: "v2.5.0"
hooks:
- id: pyproject-fmt
@ -42,7 +42,7 @@ repos:
pass_filenames: false
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.22
rev: v0.23
hooks:
- id: validate-pyproject

View File

@ -9,7 +9,9 @@ import time
def cross(items_a, items_b):
"Cross product of elements in A and elements in B."
"""
Cross product of elements in A and elements in B.
"""
return [a + b for a in items_a for b in items_b]
@ -27,7 +29,7 @@ peers = {s: set(sum(units[s], [])) - {s} for s in squares} # noqa: RUF017
def test():
"A set of unit tests."
"""A set of unit tests."""
assert len(squares) == 81
assert len(unitlist) == 27
assert all(len(units[s]) == 3 for s in squares)
@ -47,8 +49,10 @@ def test():
def parse_grid(grid):
"""Convert grid to a dict of possible values, {square: digits}, or
return False if a contradiction is detected."""
"""
Convert grid to a dict of possible values, {square: digits}, or
return False if a contradiction is detected.
"""
## To start, every square can be any digit; then assign values from the grid.
values = {s: digits for s in squares}
for s, d in grid_values(grid).items():
@ -58,15 +62,19 @@ def parse_grid(grid):
def grid_values(grid):
"Convert grid into a dict of {square: char} with '0' or '.' for empties."
"""
Convert grid into a dict of {square: char} with '0' or '.' for empties.
"""
chars = [c for c in grid if c in digits or c in "0."]
assert len(chars) == 81
return dict(zip(squares, chars))
def assign(values, s, d):
"""Eliminate all the other values (except d) from values[s] and propagate.
Return values, except return False if a contradiction is detected."""
"""
Eliminate all the other values (except d) from values[s] and propagate.
Return values, except return False if a contradiction is detected.
"""
other_values = values[s].replace(d, "")
if all(eliminate(values, s, d2) for d2 in other_values):
return values
@ -75,8 +83,10 @@ def assign(values, s, d):
def eliminate(values, s, d):
"""Eliminate d from values[s]; propagate when values or places <= 2.
Return values, except return False if a contradiction is detected."""
"""
Eliminate d from values[s]; propagate when values or places <= 2.
Return values, except return False if a contradiction is detected.
"""
if d not in values[s]:
return values ## Already eliminated
values[s] = values[s].replace(d, "")
@ -99,7 +109,9 @@ def eliminate(values, s, d):
def display(values):
"Display these values as a 2-D grid."
"""
Display these values as a 2-D grid.
"""
width = 1 + max(len(values[s]) for s in squares)
line = "+".join(["-" * (width * 3)] * 3)
for r in rows:
@ -114,11 +126,14 @@ def display(values):
def solve(grid):
"""
Solve the grid.
"""
return search(parse_grid(grid))
def some(seq):
"Return some element of seq that is true."
"""Return some element of seq that is true."""
for e in seq:
if e:
return e
@ -126,7 +141,9 @@ def some(seq):
def search(values):
"Using depth-first search and propagation, try all possible values."
"""
Using depth-first search and propagation, try all possible values.
"""
if values is False:
return False ## Failed earlier
if all(len(values[s]) == 1 for s in squares):
@ -137,9 +154,11 @@ def search(values):
def solve_all(grids, name="", showif=0.0):
"""Attempt to solve a sequence of grids. Report results.
"""
Attempt to solve a sequence of grids. Report results.
When showif is a number of seconds, display puzzles that take longer.
When showif is None, don't display any puzzles."""
When showif is None, don't display any puzzles.
"""
def time_solve(grid):
start = time.monotonic()
@ -162,7 +181,9 @@ def solve_all(grids, name="", showif=0.0):
def solved(values):
"A puzzle is solved if each unit is a permutation of the digits 1 to 9."
"""
A puzzle is solved if each unit is a permutation of the digits 1 to 9.
"""
def unitsolved(unit):
return {values[s] for s in unit} == set(digits)
@ -172,13 +193,15 @@ def solved(values):
def from_file(filename, sep="\n"):
"Parse a file into a list of strings, separated by sep."
return open(filename).read().strip().split(sep) # noqa: SIM115
return open(filename).read().strip().split(sep)
def random_puzzle(assignments=17):
"""Make a random puzzle with N or more assignments. Restart on contradictions.
"""
Make a random puzzle with N or more assignments. Restart on contradictions.
Note the resulting puzzle is not guaranteed to be solvable, but empirically
about 99.8% of them are solvable. Some have multiple solutions."""
about 99.8% of them are solvable. Some have multiple solutions.
"""
values = {s: digits for s in squares}
for s in shuffled(squares):
if not assign(values, s, random.choice(values[s])):
@ -190,7 +213,9 @@ def random_puzzle(assignments=17):
def shuffled(seq):
"Return a randomly shuffled copy of the input sequence."
"""
Return a randomly shuffled copy of the input sequence.
"""
seq = list(seq)
random.shuffle(seq)
return seq

View File

@ -29,6 +29,12 @@ def sigmoid(vector: np.ndarray) -> np.ndarray:
>>> sigmoid(np.array([0.0]))
array([0.5])
>>> sigmoid(np.array([100.0]))
array([1.])
>>> sigmoid(np.array([-100.0]))
array([3.72007598e-44])
"""
return 1 / (1 + np.exp(-vector))

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!python
import os
try: