Compare commits
1 commit
main
...
alternate-
Author | SHA1 | Date | |
---|---|---|---|
e69db652d4 |
5 changed files with 247 additions and 363 deletions
291
Cargo.lock
generated
291
Cargo.lock
generated
|
@ -8,6 +8,12 @@ version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "argparse"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f8ebf5827e4ac4fd5946560e6a99776ea73b596d80898f357007317a7141e47"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -20,12 +26,6 @@ version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1"
|
checksum = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bitflags"
|
|
||||||
version = "1.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bstr"
|
name = "bstr"
|
||||||
version = "0.2.13"
|
version = "0.2.13"
|
||||||
|
@ -50,12 +50,6 @@ version = "1.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cc"
|
|
||||||
version = "1.0.78"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
|
@ -68,43 +62,6 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "clap"
|
|
||||||
version = "4.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4ec7a4128863c188deefe750ac1d1dfe66c236909f845af04beed823638dc1b2"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"clap_derive",
|
|
||||||
"clap_lex",
|
|
||||||
"is-terminal",
|
|
||||||
"once_cell",
|
|
||||||
"strsim",
|
|
||||||
"termcolor",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "clap_derive"
|
|
||||||
version = "4.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8"
|
|
||||||
dependencies = [
|
|
||||||
"heck",
|
|
||||||
"proc-macro-error",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "clap_lex"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade"
|
|
||||||
dependencies = [
|
|
||||||
"os_str_bytes",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "const_fn"
|
name = "const_fn"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
@ -218,27 +175,6 @@ version = "0.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
|
checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "errno"
|
|
||||||
version = "0.2.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
|
|
||||||
dependencies = [
|
|
||||||
"errno-dragonfly",
|
|
||||||
"libc",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "errno-dragonfly"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.17"
|
version = "1.0.17"
|
||||||
|
@ -262,43 +198,6 @@ dependencies = [
|
||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "heck"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hermit-abi"
|
|
||||||
version = "0.2.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "io-lifetimes"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"windows-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "is-terminal"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi",
|
|
||||||
"io-lifetimes",
|
|
||||||
"rustix",
|
|
||||||
"windows-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
|
@ -322,9 +221,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.139"
|
version = "0.2.131"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linked-hash-map"
|
name = "linked-hash-map"
|
||||||
|
@ -332,12 +231,6 @@ version = "0.5.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
|
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "linux-raw-sys"
|
|
||||||
version = "0.1.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.11"
|
version = "0.4.11"
|
||||||
|
@ -381,28 +274,6 @@ dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num_cpus"
|
|
||||||
version = "1.15.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "once_cell"
|
|
||||||
version = "1.17.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "os_str_bytes"
|
|
||||||
version = "6.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "owned_ttf_parser"
|
name = "owned_ttf_parser"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
@ -436,30 +307,6 @@ dependencies = [
|
||||||
"time",
|
"time",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro-error"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro-error-attr",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro-error-attr"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-hack"
|
name = "proc-macro-hack"
|
||||||
version = "0.5.18"
|
version = "0.5.18"
|
||||||
|
@ -468,18 +315,18 @@ checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.50"
|
version = "1.0.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
|
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.23"
|
version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
@ -532,20 +379,6 @@ dependencies = [
|
||||||
"semver",
|
"semver",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustix"
|
|
||||||
version = "0.36.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"errno",
|
|
||||||
"io-lifetimes",
|
|
||||||
"libc",
|
|
||||||
"linux-raw-sys",
|
|
||||||
"windows-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
|
@ -659,41 +492,25 @@ version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
|
checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "strsim"
|
|
||||||
version = "0.10.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sudoku_solver"
|
name = "sudoku_solver"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"argparse",
|
||||||
"csv",
|
"csv",
|
||||||
"num_cpus",
|
|
||||||
"printpdf",
|
"printpdf",
|
||||||
"rand",
|
"rand",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.107"
|
version = "1.0.69"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"unicode-ident",
|
"unicode-xid",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "termcolor"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
|
|
||||||
dependencies = [
|
|
||||||
"winapi-util",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -741,10 +558,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ae2f58a822f08abdaf668897e96a5656fe72f5a9ce66422423e8849384872e6"
|
checksum = "7ae2f58a822f08abdaf668897e96a5656fe72f5a9ce66422423e8849384872e6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-xid"
|
||||||
version = "1.0.6"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
|
@ -834,74 +651,8 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-util"
|
|
||||||
version = "0.1.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
|
||||||
dependencies = [
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-sys"
|
|
||||||
version = "0.42.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
|
||||||
dependencies = [
|
|
||||||
"windows_aarch64_gnullvm",
|
|
||||||
"windows_aarch64_msvc",
|
|
||||||
"windows_i686_gnu",
|
|
||||||
"windows_i686_msvc",
|
|
||||||
"windows_x86_64_gnu",
|
|
||||||
"windows_x86_64_gnullvm",
|
|
||||||
"windows_x86_64_msvc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_gnullvm"
|
|
||||||
version = "0.42.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_msvc"
|
|
||||||
version = "0.42.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnu"
|
|
||||||
version = "0.42.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_msvc"
|
|
||||||
version = "0.42.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnu"
|
|
||||||
version = "0.42.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnullvm"
|
|
||||||
version = "0.42.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_msvc"
|
|
||||||
version = "0.42.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "sudoku_solver"
|
name = "sudoku_solver"
|
||||||
version = "0.3.0"
|
version = "0.2.0"
|
||||||
authors = ["Joel Therrien <joel@joeltherrien.ca>"]
|
authors = ["Joel Therrien <joel@joeltherrien.ca>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
@ -8,9 +8,8 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
csv = "1.1.3"
|
csv = "1.1.3"
|
||||||
clap = { version = "4.1.1", features = ['derive']}
|
argparse = "0.2.2"
|
||||||
printpdf = "0.5.2"
|
printpdf = "0.5.2"
|
||||||
num_cpus = "1.15.0"
|
|
||||||
|
|
||||||
[dependencies.rand]
|
[dependencies.rand]
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
|
|
|
@ -2,17 +2,15 @@ use rand::prelude::*;
|
||||||
use std::cmp::Ordering as ComparableOrdering;
|
use std::cmp::Ordering as ComparableOrdering;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use std::process::exit;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::atomic::{AtomicI64, Ordering};
|
use std::sync::atomic::{AtomicI64, Ordering};
|
||||||
use std::sync::{mpsc, Arc};
|
use std::sync::{mpsc, Arc};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use sudoku_solver::grid::{CellValue, Grid};
|
use sudoku_solver::grid::{CellValue, Grid};
|
||||||
use sudoku_solver::solver::{SolveController, SolveStatistics};
|
use sudoku_solver::solver::{SolveController, SolveStatistics};
|
||||||
use clap::{Parser, ValueEnum};
|
|
||||||
|
|
||||||
use num_cpus;
|
#[derive(Clone, Copy)] // Needed for argparse
|
||||||
|
|
||||||
#[derive(Clone, Copy, ValueEnum, Debug)]
|
|
||||||
enum Difficulty {
|
enum Difficulty {
|
||||||
Challenge,
|
Challenge,
|
||||||
Hard,
|
Hard,
|
||||||
|
@ -91,91 +89,136 @@ impl FromStr for Difficulty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate Sudoku Puzzles
|
|
||||||
#[derive(Parser, Debug)]
|
|
||||||
#[clap(author, version, about, long_about = None)]
|
|
||||||
struct RunParams {
|
|
||||||
|
|
||||||
/// Sets debug mode
|
|
||||||
#[arg(long, default_value_t=false)]
|
|
||||||
debug: bool,
|
|
||||||
|
|
||||||
/// Sets maximum allowed puzzle hints
|
|
||||||
#[arg(short, long, default_value_t=81)]
|
|
||||||
max_hints: u64,
|
|
||||||
|
|
||||||
/// Sets maximum puzzle attempts per generation
|
|
||||||
#[arg(long, default_value_t=100)]
|
|
||||||
attempts: usize,
|
|
||||||
|
|
||||||
/// Sets output filename; filename should end in CSV or PDF.
|
|
||||||
///
|
|
||||||
/// The type of file generated depends on the file extension used, so a PDF file will be generated for a .pdf file and
|
|
||||||
/// a CSV file will be generated for a .csv file.
|
|
||||||
#[arg(action)]
|
|
||||||
filename: String,
|
|
||||||
|
|
||||||
/// Sets number puzzles
|
|
||||||
#[arg(short, long, default_value_t=1)]
|
|
||||||
puzzles: usize,
|
|
||||||
|
|
||||||
/// Sets difficulty
|
|
||||||
#[arg(long, value_enum, default_value="hard")]
|
|
||||||
difficulty: Difficulty,
|
|
||||||
|
|
||||||
/// Sets whether to print notes
|
|
||||||
///
|
|
||||||
/// This parameter is only applicable for PDF outputs.
|
|
||||||
#[arg(short, long, default_value_t=false)]
|
|
||||||
notes: bool,
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let mut debug = false;
|
||||||
|
let mut max_hints = 81;
|
||||||
|
let mut max_attempts: Option<usize> = None;
|
||||||
|
let mut filename= String::new();
|
||||||
|
let mut number_puzzles: usize = 1;
|
||||||
|
let mut difficulty = Difficulty::Hard;
|
||||||
|
let mut threads = 1;
|
||||||
|
let mut print_possibilities = false;
|
||||||
|
let mut alternative_generation = false;
|
||||||
|
|
||||||
let run_params: RunParams = RunParams::parse();
|
{
|
||||||
|
// this block limits scope of borrows by ap.refer() method
|
||||||
|
let mut ap = argparse::ArgumentParser::new();
|
||||||
|
ap.set_description("Generate Sudoku puzzles");
|
||||||
|
ap.refer(&mut debug)
|
||||||
|
.add_option(&["--debug"], argparse::StoreTrue, "Run in debug mode");
|
||||||
|
|
||||||
let solve_controller = run_params.difficulty.map_to_solve_controller();
|
ap.refer(&mut max_hints).add_option(
|
||||||
let total_attempts = run_params.puzzles * run_params.attempts;
|
&["--hints"],
|
||||||
let threads = num_cpus::get();
|
argparse::Store,
|
||||||
|
"Only return a puzzle with less than or equal to this number of hints",
|
||||||
println!("Processing using {} threads", threads);
|
|
||||||
|
|
||||||
let mut generated_grids_vec = run_multi_threaded(
|
|
||||||
total_attempts,
|
|
||||||
run_params.puzzles,
|
|
||||||
run_params.max_hints,
|
|
||||||
threads,
|
|
||||||
run_params.debug,
|
|
||||||
solve_controller,
|
|
||||||
run_params.difficulty,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ap.refer(&mut max_attempts)
|
||||||
|
.add_option(&["--attempts"], argparse::StoreOption,
|
||||||
|
"Number of puzzles attempted to find the appropriate puzzles; default is 100*(num-puzzles)");
|
||||||
|
|
||||||
|
ap.refer(&mut filename).add_argument(
|
||||||
|
"filename",
|
||||||
|
argparse::Store,
|
||||||
|
"Filename to store puzzle(s) in as a CSV or pdf",
|
||||||
|
).required();
|
||||||
|
|
||||||
|
ap.refer(&mut number_puzzles).add_option(
|
||||||
|
&["--num-puzzles"],
|
||||||
|
argparse::Store,
|
||||||
|
"Number of puzzles to generate; default 1"
|
||||||
|
);
|
||||||
|
|
||||||
|
ap.refer(&mut difficulty).add_option(
|
||||||
|
&["-d", "--difficulty"],
|
||||||
|
argparse::Store,
|
||||||
|
"Max difficulty setting; values are EASY, MEDIUM, HARD, or CHALLENGE",
|
||||||
|
);
|
||||||
|
|
||||||
|
ap.refer(&mut threads).add_option(
|
||||||
|
&["--threads"],
|
||||||
|
argparse::Store,
|
||||||
|
"Number of threads to use when generating possible puzzles",
|
||||||
|
);
|
||||||
|
|
||||||
|
ap.refer(&mut print_possibilities).add_option(
|
||||||
|
&["-p", "--pencils"],
|
||||||
|
argparse::StoreTrue,
|
||||||
|
"Include each cell's pencil marks in the output; applies only to PDF output",
|
||||||
|
);
|
||||||
|
|
||||||
|
ap.refer(&mut alternative_generation).add_option(
|
||||||
|
&["--alt"],
|
||||||
|
argparse::StoreTrue,
|
||||||
|
"Generate using an alternative style of generation",
|
||||||
|
);
|
||||||
|
|
||||||
|
ap.parse_args_or_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
print_possibilities = print_possibilities | alternative_generation;
|
||||||
|
if alternative_generation {
|
||||||
|
max_hints = 81*9;
|
||||||
|
}
|
||||||
|
|
||||||
|
let max_attempts = max_attempts.unwrap_or(100 * number_puzzles);
|
||||||
|
|
||||||
|
let solve_controller = difficulty.map_to_solve_controller();
|
||||||
|
|
||||||
|
let mut generated_grids_vec = match threads.cmp(&1) {
|
||||||
|
ComparableOrdering::Less => {
|
||||||
|
eprintln!("--threads must be at least 1");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
ComparableOrdering::Equal => {
|
||||||
|
let mut rng = SmallRng::from_entropy();
|
||||||
|
get_puzzle_matching_conditions(
|
||||||
|
&mut rng,
|
||||||
|
&difficulty,
|
||||||
|
&solve_controller,
|
||||||
|
max_hints,
|
||||||
|
&AtomicI64::new(number_puzzles as i64),
|
||||||
|
&AtomicI64::new(max_attempts as i64),
|
||||||
|
debug,
|
||||||
|
alternative_generation,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ComparableOrdering::Greater => run_multi_threaded(
|
||||||
|
max_attempts,
|
||||||
|
number_puzzles,
|
||||||
|
max_hints,
|
||||||
|
threads,
|
||||||
|
debug,
|
||||||
|
solve_controller,
|
||||||
|
difficulty,
|
||||||
|
alternative_generation,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
if generated_grids_vec.len() < run_params.puzzles {
|
|
||||||
println!("Unable to find {} puzzles in {} tries; instead {} puzzles were found.", run_params.puzzles, total_attempts, generated_grids_vec.len());
|
if generated_grids_vec.len() < number_puzzles {
|
||||||
|
println!("Unable to find {} puzzles in {} tries; instead {} puzzles were found.", number_puzzles, max_attempts, generated_grids_vec.len());
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut grids_vec: Vec<Grid> = Vec::new();
|
let mut grids_vec: Vec<Grid> = Vec::new();
|
||||||
for _ in 0..run_params.puzzles {
|
for _ in 0..number_puzzles {
|
||||||
// It may happen that we generated more puzzles than we needed - that's okay, we'll just ignore those
|
// It may happen that we generated more puzzles than we needed - that's okay, we'll just ignore those
|
||||||
grids_vec.push(generated_grids_vec.pop().unwrap().grid);
|
grids_vec.push(generated_grids_vec.pop().unwrap().grid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// check if we save to a csv or a pdf
|
// check if we save to a csv or a pdf
|
||||||
if run_params.filename.ends_with(".pdf") {
|
if filename.ends_with(".pdf") {
|
||||||
sudoku_solver::pdf::draw_grids(&grids_vec, &run_params.filename, run_params.notes).unwrap();
|
sudoku_solver::pdf::draw_grids(&grids_vec, &filename, print_possibilities).unwrap();
|
||||||
println!("Grid saved as pdf to {}", run_params.filename);
|
println!("Grid saved as pdf to {}", filename);
|
||||||
} else {
|
} else {
|
||||||
save_grids_csv(&grids_vec, &run_params.filename).unwrap();
|
save_grids_csv(&grids_vec, &filename).unwrap();
|
||||||
println!("Grid saved as CSV to {}", run_params.filename);
|
println!("Grid saved as CSV to {}", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GeneratedGrid {
|
struct GeneratedGrid {
|
||||||
|
@ -197,10 +240,11 @@ fn run_multi_threaded(
|
||||||
max_attempts: usize,
|
max_attempts: usize,
|
||||||
number_puzzles: usize,
|
number_puzzles: usize,
|
||||||
max_hints: u64,
|
max_hints: u64,
|
||||||
threads: usize,
|
threads: u64,
|
||||||
debug: bool,
|
debug: bool,
|
||||||
solve_controller: SolveController,
|
solve_controller: SolveController,
|
||||||
difficulty: Difficulty,
|
difficulty: Difficulty,
|
||||||
|
alternative_generation: bool,
|
||||||
) -> Vec<GeneratedGrid> {
|
) -> Vec<GeneratedGrid> {
|
||||||
let mut thread_rng = thread_rng();
|
let mut thread_rng = thread_rng();
|
||||||
let (transmitter, receiver) = mpsc::channel();
|
let (transmitter, receiver) = mpsc::channel();
|
||||||
|
@ -230,6 +274,7 @@ fn run_multi_threaded(
|
||||||
&*puzzles_left,
|
&*puzzles_left,
|
||||||
&*attempts_left,
|
&*attempts_left,
|
||||||
debug,
|
debug,
|
||||||
|
alternative_generation,
|
||||||
);
|
);
|
||||||
|
|
||||||
let num_puzzles_found = found_puzzles.len();
|
let num_puzzles_found = found_puzzles.len();
|
||||||
|
@ -271,13 +316,16 @@ fn get_puzzle_matching_conditions<R: Rng>(
|
||||||
puzzles_left: &AtomicI64,
|
puzzles_left: &AtomicI64,
|
||||||
attempts_left: &AtomicI64,
|
attempts_left: &AtomicI64,
|
||||||
debug: bool,
|
debug: bool,
|
||||||
|
alternative_generation: bool,
|
||||||
) -> Vec<GeneratedGrid> {
|
) -> Vec<GeneratedGrid> {
|
||||||
|
|
||||||
let mut generated_grids: Vec<GeneratedGrid> = Vec::new();
|
let mut generated_grids: Vec<GeneratedGrid> = Vec::new();
|
||||||
|
|
||||||
while attempts_left.fetch_sub(1, Ordering::SeqCst) > 0 && puzzles_left.load(Ordering::SeqCst) > 0 {
|
while attempts_left.fetch_sub(1, Ordering::SeqCst) > 0 && puzzles_left.load(Ordering::SeqCst) > 0 {
|
||||||
let (grid, num_hints, statistics) =
|
let (grid, num_hints, statistics) = match alternative_generation {
|
||||||
sudoku_solver::generator::generate_grid(rng, &solve_controller);
|
true => {sudoku_solver::generator::generate_alternate_grid(rng, &solve_controller)}
|
||||||
|
false => {sudoku_solver::generator::generate_grid(rng, &solve_controller)}
|
||||||
|
};
|
||||||
|
|
||||||
if debug {
|
if debug {
|
||||||
println!("Found puzzle with {:#?}", statistics);
|
println!("Found puzzle with {:#?}", statistics);
|
||||||
|
|
|
@ -1,35 +1,35 @@
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use clap::Parser;
|
|
||||||
|
|
||||||
use sudoku_solver::grid::Grid;
|
use sudoku_solver::grid::Grid;
|
||||||
use sudoku_solver::solver::solve_grid;
|
use sudoku_solver::solver::solve_grid;
|
||||||
|
|
||||||
/// Test text here
|
fn main() {
|
||||||
///
|
let mut debug = false;
|
||||||
/// Second test text here setence;
|
let mut filename = String::new();
|
||||||
#[derive(Parser, Debug)]
|
{
|
||||||
#[clap(author, version, about, long_about = None)]
|
// this block limits scope of borrows by ap.refer() method
|
||||||
struct RunParams {
|
let mut ap = argparse::ArgumentParser::new();
|
||||||
/// Sets debug mode
|
ap.set_description("Solve Sudoku puzzles");
|
||||||
#[arg(long, default_value_t=false)]
|
ap.refer(&mut debug)
|
||||||
debug: bool,
|
.add_option(&["--debug"], argparse::StoreTrue, "Run in debug mode");
|
||||||
|
|
||||||
/// Path to puzzle CSV file to solve
|
ap.refer(&mut filename).required().add_argument(
|
||||||
#[arg(action)]
|
"filename",
|
||||||
filename: String,
|
argparse::Store,
|
||||||
|
"Path to puzzle CSV file",
|
||||||
|
);
|
||||||
|
|
||||||
|
ap.parse_args_or_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
if debug {
|
||||||
let params: RunParams = RunParams::parse();
|
|
||||||
|
|
||||||
if params.debug {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
sudoku_solver::grid::DEBUG = true;
|
sudoku_solver::grid::DEBUG = true;
|
||||||
sudoku_solver::solver::DEBUG = true;
|
sudoku_solver::solver::DEBUG = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut grid = match read_grid(¶ms.filename) {
|
let mut grid = match read_grid(&filename) {
|
||||||
Ok(grid) => grid,
|
Ok(grid) => grid,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error while reading grid: \"{}\"", e);
|
eprintln!("Error while reading grid: \"{}\"", e);
|
||||||
|
|
|
@ -178,6 +178,92 @@ pub fn generate_grid<R: Rng>(
|
||||||
(grid, num_hints, statistics_option.unwrap())
|
(grid, num_hints, statistics_option.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn generate_alternate_grid<R: Rng>(
|
||||||
|
rng: &mut R,
|
||||||
|
solve_controller: &SolveController,
|
||||||
|
) -> (Grid, u64, SolveStatistics) {
|
||||||
|
let mut grid = generate_completed_grid(rng);
|
||||||
|
|
||||||
|
|
||||||
|
let mut cell_order_vec = Vec::new();
|
||||||
|
// go through and replace every number with a pencil marking
|
||||||
|
for x in 0..9 {
|
||||||
|
for y in 0..9 {
|
||||||
|
let mut cell = grid.get(x, y).unwrap();
|
||||||
|
cell_order_vec.push(Rc::clone(&cell));
|
||||||
|
|
||||||
|
if let CellValue::Fixed(digit) = cell.get_value_copy() {
|
||||||
|
cell.set_value_exact(CellValue::Unknown(vec![digit]));
|
||||||
|
} else {
|
||||||
|
panic!("Unexpectedly found an incomplete cell in a completed puzzle");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to randomly reorder non_empty_cells
|
||||||
|
cell_order_vec.shuffle(rng);
|
||||||
|
|
||||||
|
fn invert_digits(digits: &[u8]) -> Vec<u8>{
|
||||||
|
let mut inverted = Vec::with_capacity(9);
|
||||||
|
|
||||||
|
for i in 1..=9 {
|
||||||
|
if !digits.contains(&i) {
|
||||||
|
inverted.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inverted
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut num_pencils = 81;
|
||||||
|
for cell in cell_order_vec {
|
||||||
|
let mut current_digits = match cell.get_value_copy() {
|
||||||
|
CellValue::Fixed(digit) => {vec![digit]}
|
||||||
|
CellValue::Unknown(digits) => {digits}
|
||||||
|
};
|
||||||
|
|
||||||
|
let to_try_add = invert_digits(¤t_digits);
|
||||||
|
for digit in to_try_add {
|
||||||
|
current_digits.push(digit);
|
||||||
|
cell.set_value_exact(CellValue::Unknown(current_digits.clone()));
|
||||||
|
|
||||||
|
let (status, _) =
|
||||||
|
evaluate_grid_with_solve_controller(&grid, solve_controller);
|
||||||
|
match status {
|
||||||
|
SolveStatus::Complete(uniqueness) => {
|
||||||
|
let uniqueness = uniqueness.unwrap();
|
||||||
|
match uniqueness {
|
||||||
|
Uniqueness::Unique => {
|
||||||
|
num_pencils += 1;
|
||||||
|
}
|
||||||
|
Uniqueness::NotUnique => {
|
||||||
|
// Too relaxed; can't add this pencil mark
|
||||||
|
current_digits.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SolveStatus::Unfinished => {
|
||||||
|
panic!("evaluate_grid_with_solve_controller should never return UNFINISHED")
|
||||||
|
}
|
||||||
|
SolveStatus::Invalid => {
|
||||||
|
println!("{}", grid);
|
||||||
|
panic!("Removing constraints should not have set the # of solutions to zero")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cell.set_value_exact(CellValue::Unknown(current_digits));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
let (_, statistics) =
|
||||||
|
evaluate_grid_with_solve_controller(&grid, solve_controller);
|
||||||
|
|
||||||
|
(grid, num_pencils, statistics)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// We generate a completed grid with no mind for difficulty; afterward generate_puzzle will take out as many fields as it can with regards to the difficulty
|
// We generate a completed grid with no mind for difficulty; afterward generate_puzzle will take out as many fields as it can with regards to the difficulty
|
||||||
fn generate_completed_grid<R: Rng>(rng: &mut R) -> Grid {
|
fn generate_completed_grid<R: Rng>(rng: &mut R) -> Grid {
|
||||||
let solve_controller = SolveController {
|
let solve_controller = SolveController {
|
||||||
|
|
Loading…
Reference in a new issue