Finding Exact Covers in NumPy
=============================
[![PyPI version](https://badge.fury.io/py/exact-cover.svg)](https://badge.fury.io/py/exact-cover)
![Deploy wheels to pypi](https://github.com/jwg4/exact_cover/workflows/Deploy%20wheels%20to%20pypi/badge.svg)
![Run Python tests](https://github.com/jwg4/exact_cover/workflows/Run%20Python%20tests/badge.svg)
This is a Python 3 package to solve exact cover problems using Numpy. It is based on https://github.com/moygit/exact_cover_np by Moy Easwaran. Jack Grahl ported it to Python 3, fixed some bugs and made lots of small improvements to the packaging.
The original package by Moy was designed to solve sudoku. Now this package is only designed to solve exact cover problems given as boolean arrays. It can be used to solve sudoku and a variety of combinatorial problems. However the code to reduce a sudoku to an exact cover problem is no longer part of this project. It can be found at:
- https://pypi.org/project/xudoku/
- https://github.com/jwg4/xudoku
Another project, 'polyomino' by Jack Grahl uses this algorithm to solve polyomino tiling problems. It can be found at:
- https://pypi.org/project/polyomino/
- https://github.com/jwg4/polyomino
Summary
-------
The exact cover problem is as follows: given a set X and a
collection S of subsets of X, we want to find a subcollection S*
of S that is an exact cover or partition of X. In other words,
S* is a bunch of subsets of X whose union is X, and which have
empty intersection with each other. (Example below; more details [on
wikipedia](https://en.wikipedia.org/wiki/Exact_cover).)
This NumPy module uses Donald Knuth's Algorithm X
(also known as Dancing Links) to find
exact covers of sets.
For details on Algorithm X please see either
[the Wikipedia page](https://en.wikipedia.org/wiki/Knuth%27s_Algorithm_X)
or [Knuth's paper](http://arxiv.org/pdf/cs/0011047v1).
Specifically, we use the Knuth/Hitotsumatsu/Noshita method of
Dancing Links for efficient backtracking. Please see
[Knuth's paper](http://arxiv.org/pdf/cs/0011047v1)
for details.
How to Use It
-------------
Suppose X = {0,1,2,3,4}, and suppose S = {A,B,C,D}, where
A = {0, 3}
B = {0, 1, 2}
C = {1, 2}
D = {4}.
Here we can just eyeball these sets and conclude that S* = {A,C,D} forms an
exact cover: each element of X is in one of these sets (i.e. is
"covered" by one of these sets), and no element of X is in more than
one.
We'd use `exact_cover` to solve the problem as follows:
using 1 to denote that a particular member of X is in a subset and 0 to
denote that it's not, we can represent the sets as
A = 1,0,0,1,0 # The 0th and 3rd entries are 1 since 0 and 3 are in A; the rest are 0.
B = 1,1,1,0,0 # The 0th, 1st, and 2nd entries are 1, and the rest are 0,
C = 0,1,1,0,0 # etc.
D = 0,0,0,0,1
Now we can call `exact_cover`:
>>> import numpy as np
>>> import exact_cover as ec
>>> S = np.array([[1,0,0,1,0],[1,1,1,0,0],[0,1,1,0,0],[0,0,0,0,1]], dtype=bool)
>>> print(ec.get_exact_cover(S))
[0 2 3]
This is telling us that the 0th row (i.e. A), the 2nd row (i.e. C),
and the 3rd row (i.e. D) together form an exact cover.
To see the total number of distinct solutions, we can use the function get_solution_count:
>>> ec.get_solution_count(S)
1
See the file examples.md for more detailed examples of use.
Implementation Overview
-----------------------
The NumPy module (`exact_cover`) is implemented in four pieces:
- The lowest level is `quad_linked_list`, which implements a circular
linked-list with left-, right-, up-, and down-links.
- This is used in `sparse_matrix` to implement the type of sparse
representation of matrices that Knuth describes in his paper (in
brief, each column contains all its non-zero entries, and each
non-zero cell also points to the (horizontally) next non-zero cell
in either direction).
- Sparse matrices are used in `dlx` to implement Knuth's Dancing
Links version of his Algorithm X, which calculates exact covers.
- `exact_cover` provides the glue code letting us invoke
`dlx` on NumPy arrays.
The package now has some pure Python modules for helper functions, with the main algorithm in the C-only package `exact_cover_impl`.
How to develop
--------------
The package uses poetry and most of the setup for development uses that tool.
To install locally (as an editable package):
`poetry install`
To build:
`poetry build`
To run tests:
`poetry run test` or `poetry run doctest`
To open a Python shell with the package available:
`poetry run python`
The exception is running the C unit tests:
`make c_tests`
Repository
----------
- build/ The location where files are built.
- dist/ The location for fully prepared files.
- exact_cover/ The Python code.
- obj/ Where the compiled C code is going to be output.
- src/ The C sources.
- tests/ Tests for both the Python package and the C code.
- tools/ Code used in analysing and working with the library. This is not distributed with the package.
Acknowledgements
----------------
Thanks very much to Moy Easwaran (https://github.com/moygit) for his inspiring work!
Munit aka µnit (https://nemequ.github.io/munit/) is a wonderful unit testing framework for C code.
Raw data
{
"_id": null,
"home_page": "https://github.com/jwg4/exact_cover",
"name": "exact-cover",
"maintainer": "Jack Grahl",
"docs_url": null,
"requires_python": "<4.0,>=3.7",
"maintainer_email": "jack.grahl@gmail.com",
"keywords": null,
"author": "Moy Easwaran",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/34/95/956415fa886ccd74c86cc8de35a97cec3e2e6890be5d90f730c08a8fcc40/exact_cover-1.4.0.tar.gz",
"platform": null,
"description": "Finding Exact Covers in NumPy\n=============================\n\n[![PyPI version](https://badge.fury.io/py/exact-cover.svg)](https://badge.fury.io/py/exact-cover)\n![Deploy wheels to pypi](https://github.com/jwg4/exact_cover/workflows/Deploy%20wheels%20to%20pypi/badge.svg)\n![Run Python tests](https://github.com/jwg4/exact_cover/workflows/Run%20Python%20tests/badge.svg)\n\nThis is a Python 3 package to solve exact cover problems using Numpy. It is based on https://github.com/moygit/exact_cover_np by Moy Easwaran. Jack Grahl ported it to Python 3, fixed some bugs and made lots of small improvements to the packaging.\n\nThe original package by Moy was designed to solve sudoku. Now this package is only designed to solve exact cover problems given as boolean arrays. It can be used to solve sudoku and a variety of combinatorial problems. However the code to reduce a sudoku to an exact cover problem is no longer part of this project. It can be found at:\n - https://pypi.org/project/xudoku/\n - https://github.com/jwg4/xudoku\n\nAnother project, 'polyomino' by Jack Grahl uses this algorithm to solve polyomino tiling problems. It can be found at:\n - https://pypi.org/project/polyomino/\n - https://github.com/jwg4/polyomino\n\nSummary\n-------\n\nThe exact cover problem is as follows: given a set X and a\ncollection S of subsets of X, we want to find a subcollection S*\nof S that is an exact cover or partition of X. In other words,\nS* is a bunch of subsets of X whose union is X, and which have\nempty intersection with each other. (Example below; more details [on\nwikipedia](https://en.wikipedia.org/wiki/Exact_cover).)\n\nThis NumPy module uses Donald Knuth's Algorithm X\n(also known as Dancing Links) to find\nexact covers of sets.\nFor details on Algorithm X please see either\n[the Wikipedia page](https://en.wikipedia.org/wiki/Knuth%27s_Algorithm_X)\nor [Knuth's paper](http://arxiv.org/pdf/cs/0011047v1).\nSpecifically, we use the Knuth/Hitotsumatsu/Noshita method of\nDancing Links for efficient backtracking. Please see\n[Knuth's paper](http://arxiv.org/pdf/cs/0011047v1)\nfor details.\n\nHow to Use It\n-------------\n\nSuppose X = {0,1,2,3,4}, and suppose S = {A,B,C,D}, where\n\n A = {0, 3}\n B = {0, 1, 2}\n C = {1, 2}\n D = {4}.\n\nHere we can just eyeball these sets and conclude that S* = {A,C,D} forms an\nexact cover: each element of X is in one of these sets (i.e. is\n\"covered\" by one of these sets), and no element of X is in more than\none.\n\nWe'd use `exact_cover` to solve the problem as follows:\nusing 1 to denote that a particular member of X is in a subset and 0 to\ndenote that it's not, we can represent the sets as\n\n A = 1,0,0,1,0 # The 0th and 3rd entries are 1 since 0 and 3 are in A; the rest are 0.\n B = 1,1,1,0,0 # The 0th, 1st, and 2nd entries are 1, and the rest are 0,\n C = 0,1,1,0,0 # etc.\n D = 0,0,0,0,1\n\nNow we can call `exact_cover`:\n\n >>> import numpy as np\n >>> import exact_cover as ec\n >>> S = np.array([[1,0,0,1,0],[1,1,1,0,0],[0,1,1,0,0],[0,0,0,0,1]], dtype=bool)\n >>> print(ec.get_exact_cover(S))\n [0 2 3]\n\nThis is telling us that the 0th row (i.e. A), the 2nd row (i.e. C),\nand the 3rd row (i.e. D) together form an exact cover.\n\nTo see the total number of distinct solutions, we can use the function get_solution_count:\n\n >>> ec.get_solution_count(S)\n 1\n\nSee the file examples.md for more detailed examples of use.\n\n\nImplementation Overview\n-----------------------\n\nThe NumPy module (`exact_cover`) is implemented in four pieces:\n\n- The lowest level is `quad_linked_list`, which implements a circular\n linked-list with left-, right-, up-, and down-links.\n- This is used in `sparse_matrix` to implement the type of sparse\n representation of matrices that Knuth describes in his paper (in\n brief, each column contains all its non-zero entries, and each\n non-zero cell also points to the (horizontally) next non-zero cell\n in either direction).\n- Sparse matrices are used in `dlx` to implement Knuth's Dancing\n Links version of his Algorithm X, which calculates exact covers.\n- `exact_cover` provides the glue code letting us invoke\n `dlx` on NumPy arrays.\n\nThe package now has some pure Python modules for helper functions, with the main algorithm in the C-only package `exact_cover_impl`.\n\nHow to develop\n--------------\n\nThe package uses poetry and most of the setup for development uses that tool.\n\nTo install locally (as an editable package):\n`poetry install`\n\nTo build:\n`poetry build`\n\nTo run tests:\n`poetry run test` or `poetry run doctest`\n\nTo open a Python shell with the package available:\n`poetry run python`\n\nThe exception is running the C unit tests:\n`make c_tests`\n\nRepository\n----------\n\n- build/ The location where files are built.\n- dist/ The location for fully prepared files.\n- exact_cover/ The Python code.\n- obj/ Where the compiled C code is going to be output.\n- src/ The C sources.\n- tests/ Tests for both the Python package and the C code.\n- tools/ Code used in analysing and working with the library. This is not distributed with the package.\n\nAcknowledgements\n----------------\n\nThanks very much to Moy Easwaran (https://github.com/moygit) for his inspiring work!\n\nMunit aka \u00b5nit (https://nemequ.github.io/munit/) is a wonderful unit testing framework for C code.\n",
"bugtrack_url": null,
"license": "GPL-2.0-only",
"summary": "Solve exact cover problems",
"version": "1.4.0",
"project_urls": {
"Homepage": "https://github.com/jwg4/exact_cover",
"Repository": "https://github.com/jwg4/exact_cover"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "ec6c6a5d3097651345d151cdc74382d7f9df485de41593f7121d370ed3278d6a",
"md5": "388e625e3044aceea7dc1956d55b90f9",
"sha256": "5c3f409f7c2b1260578345d707ddf6504597d0885a4edba75586f0bfb74176c4"
},
"downloads": -1,
"filename": "exact_cover-1.4.0-cp310-cp310-macosx_12_0_x86_64.whl",
"has_sig": false,
"md5_digest": "388e625e3044aceea7dc1956d55b90f9",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": "<4.0,>=3.7",
"size": 20880,
"upload_time": "2024-03-31T11:51:15",
"upload_time_iso_8601": "2024-03-31T11:51:15.610596Z",
"url": "https://files.pythonhosted.org/packages/ec/6c/6a5d3097651345d151cdc74382d7f9df485de41593f7121d370ed3278d6a/exact_cover-1.4.0-cp310-cp310-macosx_12_0_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ecac196474d45b9e97f4990a15e67af89c73f47145b5009c9baa30e30d3eb2e0",
"md5": "05700edd2eb3558fded9b63d8bad3af0",
"sha256": "8dde4fb1e4878667f7a58555f3e295997167c36bd3c72db5c5d981cea7611d04"
},
"downloads": -1,
"filename": "exact_cover-1.4.0-cp310-cp310-manylinux_2_31_x86_64.whl",
"has_sig": false,
"md5_digest": "05700edd2eb3558fded9b63d8bad3af0",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": "<4.0,>=3.7",
"size": 49804,
"upload_time": "2024-03-31T11:49:28",
"upload_time_iso_8601": "2024-03-31T11:49:28.280230Z",
"url": "https://files.pythonhosted.org/packages/ec/ac/196474d45b9e97f4990a15e67af89c73f47145b5009c9baa30e30d3eb2e0/exact_cover-1.4.0-cp310-cp310-manylinux_2_31_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "5c35a21ea1a81127e2c1ca4894b1fbeb48575a8cd17abaaae22839372acf105f",
"md5": "48df978668a68aad41ffd57fc44b72e0",
"sha256": "db4d8c17891a1b3e369415fb7392f2b0fb3065e3115026e92b1466458ff92461"
},
"downloads": -1,
"filename": "exact_cover-1.4.0-cp310-cp310-win_amd64.whl",
"has_sig": false,
"md5_digest": "48df978668a68aad41ffd57fc44b72e0",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": "<4.0,>=3.7",
"size": 22081,
"upload_time": "2024-03-31T11:51:08",
"upload_time_iso_8601": "2024-03-31T11:51:08.359704Z",
"url": "https://files.pythonhosted.org/packages/5c/35/a21ea1a81127e2c1ca4894b1fbeb48575a8cd17abaaae22839372acf105f/exact_cover-1.4.0-cp310-cp310-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "0087e533b858c364f893efc9bbfaf58621f5263b06aeae0aa828870582654f5d",
"md5": "417ed96a3998969b513fc17990a765aa",
"sha256": "859d9545ddc5b7792f93478533d93c3acad4d7b858f6936fcae7d664ecdeada8"
},
"downloads": -1,
"filename": "exact_cover-1.4.0-cp311-cp311-macosx_12_0_x86_64.whl",
"has_sig": false,
"md5_digest": "417ed96a3998969b513fc17990a765aa",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": "<4.0,>=3.7",
"size": 28429,
"upload_time": "2024-03-31T11:54:35",
"upload_time_iso_8601": "2024-03-31T11:54:35.793158Z",
"url": "https://files.pythonhosted.org/packages/00/87/e533b858c364f893efc9bbfaf58621f5263b06aeae0aa828870582654f5d/exact_cover-1.4.0-cp311-cp311-macosx_12_0_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "5814de4605f96c36db51bceb469ef22f97dc30bc591bd562dd8e71a49bf6df80",
"md5": "b0adf20017920eeff76ea8feae0736fd",
"sha256": "d5cbc366ce1daf3519aafd2fb6d2ebc421dc71b352dd22baa5453f4524d67160"
},
"downloads": -1,
"filename": "exact_cover-1.4.0-cp311-cp311-manylinux_2_31_x86_64.whl",
"has_sig": false,
"md5_digest": "b0adf20017920eeff76ea8feae0736fd",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": "<4.0,>=3.7",
"size": 50860,
"upload_time": "2024-03-31T11:49:32",
"upload_time_iso_8601": "2024-03-31T11:49:32.177440Z",
"url": "https://files.pythonhosted.org/packages/58/14/de4605f96c36db51bceb469ef22f97dc30bc591bd562dd8e71a49bf6df80/exact_cover-1.4.0-cp311-cp311-manylinux_2_31_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "4ed8339cf330759550c634c2e07b8e3553b5a46b6ea175480b363fb375ade70f",
"md5": "fd82f802ce4d1f3c4d3677eefc6aab90",
"sha256": "b41cd1395325eb208161a362387b06cce61dd414e871751e7a3feb94235ad602"
},
"downloads": -1,
"filename": "exact_cover-1.4.0-cp311-cp311-win_amd64.whl",
"has_sig": false,
"md5_digest": "fd82f802ce4d1f3c4d3677eefc6aab90",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": "<4.0,>=3.7",
"size": 22080,
"upload_time": "2024-03-31T11:51:18",
"upload_time_iso_8601": "2024-03-31T11:51:18.012698Z",
"url": "https://files.pythonhosted.org/packages/4e/d8/339cf330759550c634c2e07b8e3553b5a46b6ea175480b363fb375ade70f/exact_cover-1.4.0-cp311-cp311-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ce1ed35de5dd2e4d2476fc05a24246d21e2135a26c03da03ca139c8cc0146bbb",
"md5": "3dec63838b122101c24f2a3d85afd5b9",
"sha256": "e2945d951b6ac8c4873451d0c6f4957af9480829b517a68b429d2f1edf61c549"
},
"downloads": -1,
"filename": "exact_cover-1.4.0-cp37-cp37m-macosx_12_0_x86_64.whl",
"has_sig": false,
"md5_digest": "3dec63838b122101c24f2a3d85afd5b9",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": "<4.0,>=3.7",
"size": 20849,
"upload_time": "2024-03-31T11:56:50",
"upload_time_iso_8601": "2024-03-31T11:56:50.292539Z",
"url": "https://files.pythonhosted.org/packages/ce/1e/d35de5dd2e4d2476fc05a24246d21e2135a26c03da03ca139c8cc0146bbb/exact_cover-1.4.0-cp37-cp37m-macosx_12_0_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ec401bada59c653ea49c11012e44f08717d5543d0ea12dfedde889a18bcdb9a8",
"md5": "3fe9b1074ec11fa374ce9cad4760e45d",
"sha256": "9da08df0167d36f88eb03be1d4fb04870d416273ab361c7059af0c9fd34abf3e"
},
"downloads": -1,
"filename": "exact_cover-1.4.0-cp37-cp37m-manylinux_2_31_x86_64.whl",
"has_sig": false,
"md5_digest": "3fe9b1074ec11fa374ce9cad4760e45d",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": "<4.0,>=3.7",
"size": 50702,
"upload_time": "2024-03-31T11:53:54",
"upload_time_iso_8601": "2024-03-31T11:53:54.567828Z",
"url": "https://files.pythonhosted.org/packages/ec/40/1bada59c653ea49c11012e44f08717d5543d0ea12dfedde889a18bcdb9a8/exact_cover-1.4.0-cp37-cp37m-manylinux_2_31_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "41fb53d0765315f4de56581c3f314b9885f905b1df3784861a5ca6e87c461589",
"md5": "46985126e7e02f2233b46b80f8775f70",
"sha256": "ea77e068696fb9507c6b98ed5f2eb0e5ad1422ed2abf5a9ffc81c39c0980780d"
},
"downloads": -1,
"filename": "exact_cover-1.4.0-cp37-cp37m-win_amd64.whl",
"has_sig": false,
"md5_digest": "46985126e7e02f2233b46b80f8775f70",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": "<4.0,>=3.7",
"size": 22061,
"upload_time": "2024-03-31T11:54:54",
"upload_time_iso_8601": "2024-03-31T11:54:54.291213Z",
"url": "https://files.pythonhosted.org/packages/41/fb/53d0765315f4de56581c3f314b9885f905b1df3784861a5ca6e87c461589/exact_cover-1.4.0-cp37-cp37m-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "d26cd9dbbad4ef8f19a57545c8e69a16578e5de3cb4d636458a3d1cf136b6f66",
"md5": "d18d0444d8d5bdac1ccbad2e9fdc5d36",
"sha256": "a05e0ed3f2a9d66487a34ef17fe6f4f743a753769a26940523c87c7bcf10c2fc"
},
"downloads": -1,
"filename": "exact_cover-1.4.0-cp38-cp38-macosx_12_0_x86_64.whl",
"has_sig": false,
"md5_digest": "d18d0444d8d5bdac1ccbad2e9fdc5d36",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": "<4.0,>=3.7",
"size": 20873,
"upload_time": "2024-03-31T11:52:32",
"upload_time_iso_8601": "2024-03-31T11:52:32.026901Z",
"url": "https://files.pythonhosted.org/packages/d2/6c/d9dbbad4ef8f19a57545c8e69a16578e5de3cb4d636458a3d1cf136b6f66/exact_cover-1.4.0-cp38-cp38-macosx_12_0_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "0d049bd737074ea95a34f6cce418b4d574f52bb229d2e2e50048bb79e97f4374",
"md5": "7afceff70951efc65069f5ca01d255a9",
"sha256": "c6b55675205ce6f8a13ea48127046fc6fa04de6d7f535dc46eb6c020002dc2b1"
},
"downloads": -1,
"filename": "exact_cover-1.4.0-cp38-cp38-manylinux_2_31_x86_64.whl",
"has_sig": false,
"md5_digest": "7afceff70951efc65069f5ca01d255a9",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": "<4.0,>=3.7",
"size": 50105,
"upload_time": "2024-03-31T11:50:45",
"upload_time_iso_8601": "2024-03-31T11:50:45.767757Z",
"url": "https://files.pythonhosted.org/packages/0d/04/9bd737074ea95a34f6cce418b4d574f52bb229d2e2e50048bb79e97f4374/exact_cover-1.4.0-cp38-cp38-manylinux_2_31_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "9c045cd538914e6f79883e70716aef566decdee59087b6ba1ee6b0f3a492a723",
"md5": "f9d601a341101102560aafc51a472fa7",
"sha256": "867397e767e24aca133386a711b42a2a7dfecc561fa496c30628cb2c68b1b478"
},
"downloads": -1,
"filename": "exact_cover-1.4.0-cp38-cp38-win_amd64.whl",
"has_sig": false,
"md5_digest": "f9d601a341101102560aafc51a472fa7",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": "<4.0,>=3.7",
"size": 22077,
"upload_time": "2024-03-31T11:52:24",
"upload_time_iso_8601": "2024-03-31T11:52:24.319761Z",
"url": "https://files.pythonhosted.org/packages/9c/04/5cd538914e6f79883e70716aef566decdee59087b6ba1ee6b0f3a492a723/exact_cover-1.4.0-cp38-cp38-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "f07130656230a8cee647ef5ff83dc1850956c73123839d3a8fdc05597016fc72",
"md5": "81b503e3688dced5f4a418af42631879",
"sha256": "9d9dccb4be8beb132fd98ac904e5d42769edbe8090bc6c8c91b6eb5795e1cd28"
},
"downloads": -1,
"filename": "exact_cover-1.4.0-cp39-cp39-macosx_12_0_x86_64.whl",
"has_sig": false,
"md5_digest": "81b503e3688dced5f4a418af42631879",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": "<4.0,>=3.7",
"size": 20871,
"upload_time": "2024-03-31T11:55:07",
"upload_time_iso_8601": "2024-03-31T11:55:07.590261Z",
"url": "https://files.pythonhosted.org/packages/f0/71/30656230a8cee647ef5ff83dc1850956c73123839d3a8fdc05597016fc72/exact_cover-1.4.0-cp39-cp39-macosx_12_0_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "26b3a9e53a8a93b162f09b5b607fa838039a04641a420996682e063db7e4b746",
"md5": "3a9a720f51c26df5a5c74ccfe956e097",
"sha256": "7680dffff5e69f5ec431dc1f65f9badb9cf3d22d1ace22c5b4d248c86d3e469a"
},
"downloads": -1,
"filename": "exact_cover-1.4.0-cp39-cp39-manylinux_2_31_x86_64.whl",
"has_sig": false,
"md5_digest": "3a9a720f51c26df5a5c74ccfe956e097",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": "<4.0,>=3.7",
"size": 49642,
"upload_time": "2024-03-31T11:51:10",
"upload_time_iso_8601": "2024-03-31T11:51:10.558272Z",
"url": "https://files.pythonhosted.org/packages/26/b3/a9e53a8a93b162f09b5b607fa838039a04641a420996682e063db7e4b746/exact_cover-1.4.0-cp39-cp39-manylinux_2_31_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "2438be7304ded969410d1f2b531b234014c95cc241bb9774ee4300935401792b",
"md5": "f1c0a4fe3fca2ffc20ba73baa16dcb75",
"sha256": "091254a47753001f2f3821c098655e638301c3221b37826590e61528078fd3ee"
},
"downloads": -1,
"filename": "exact_cover-1.4.0-cp39-cp39-win_amd64.whl",
"has_sig": false,
"md5_digest": "f1c0a4fe3fca2ffc20ba73baa16dcb75",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": "<4.0,>=3.7",
"size": 22082,
"upload_time": "2024-03-31T11:52:05",
"upload_time_iso_8601": "2024-03-31T11:52:05.900013Z",
"url": "https://files.pythonhosted.org/packages/24/38/be7304ded969410d1f2b531b234014c95cc241bb9774ee4300935401792b/exact_cover-1.4.0-cp39-cp39-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3495956415fa886ccd74c86cc8de35a97cec3e2e6890be5d90f730c08a8fcc40",
"md5": "f3d841a956d26f13c1b08d79b2aa18ee",
"sha256": "6eae7fec29ea5569ba1006b55f68a87656e43582a6e3cb5016499e902180c2d5"
},
"downloads": -1,
"filename": "exact_cover-1.4.0.tar.gz",
"has_sig": false,
"md5_digest": "f3d841a956d26f13c1b08d79b2aa18ee",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.7",
"size": 20412,
"upload_time": "2024-03-31T11:52:32",
"upload_time_iso_8601": "2024-03-31T11:52:32.798999Z",
"url": "https://files.pythonhosted.org/packages/34/95/956415fa886ccd74c86cc8de35a97cec3e2e6890be5d90f730c08a8fcc40/exact_cover-1.4.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-03-31 11:52:32",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "jwg4",
"github_project": "exact_cover",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "exact-cover"
}