Hackity hax
This commit is contained in:
3
.envrc
Normal file
3
.envrc
Normal file
@@ -0,0 +1,3 @@
|
||||
source_url "https://raw.githubusercontent.com/cachix/devenv/d1f7b48e35e6dee421cfd0f51481d17f77586997/direnvrc" "sha256-YBzqskFZxmNb3kYVoKD9ZixoPXJh1C9ZvTLGFRkauZ0="
|
||||
|
||||
use devenv
|
||||
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
# Devenv
|
||||
.devenv*
|
||||
devenv.local.nix
|
||||
|
||||
# direnv
|
||||
.direnv
|
||||
|
||||
# pre-commit
|
||||
.pre-commit-config.yaml
|
||||
|
||||
|
||||
|
||||
# Added by cargo
|
||||
|
||||
/target
|
||||
657
Cargo.lock
generated
Normal file
657
Cargo.lock
generated
Normal file
@@ -0,0 +1,657 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anes"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "ciborium"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"ciborium-ll",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-io"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656"
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-ll"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"half",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||
|
||||
[[package]]
|
||||
name = "criterion"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
|
||||
dependencies = [
|
||||
"anes",
|
||||
"cast",
|
||||
"ciborium",
|
||||
"clap",
|
||||
"criterion-plot",
|
||||
"is-terminal",
|
||||
"itertools",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"oorandom",
|
||||
"plotters",
|
||||
"rayon",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"tinytemplate",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion-plot"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"itertools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.150"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"plotters-backend",
|
||||
"plotters-svg",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters-backend"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609"
|
||||
|
||||
[[package]]
|
||||
name = "plotters-svg"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab"
|
||||
dependencies = [
|
||||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "rubik"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"criterion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.193"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.193"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinytemplate"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
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.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
15
Cargo.toml
Normal file
15
Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "rubik"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.5.1"
|
||||
|
||||
[[bench]]
|
||||
name = "statepack"
|
||||
harness = false
|
||||
37
README.md
Normal file
37
README.md
Normal file
@@ -0,0 +1,37 @@
|
||||
Pyramix analysis
|
||||
================
|
||||
|
||||
This is a small rust program that evaluates every possible shape of the
|
||||
[Pyraminx](https://www.speedcube.nl/speedcube/pyraminx/qiyi-x-man-bell-v2-pyraminx-m/) in an attempt to solve it from
|
||||
scratch.
|
||||
|
||||
It requires around 250MB of memory to run successfully, and by default prints every possible position along with its
|
||||
solution.
|
||||
|
||||
Position naming
|
||||
===============
|
||||
|
||||
Every piece has a position and an orientation.
|
||||
|
||||
The four corners are in a fixed position. I've numbered them in the order top, back, right, left. Their orientations are
|
||||
named according to how many counterclockwise turns are necessary to bring them into the correct orientation.
|
||||
|
||||
The 6 edge pieces are named according to their correct positions. First, the bottom layer: left, right, front.
|
||||
Next, the upper layer: back, right, front.
|
||||
|
||||
The orientations are named somewhat arbitrarily in a way that makes computation easy. Specifically,
|
||||
each corner rotation has an associated edge position that flips as eges rotate through it: the top corner flips edge 4
|
||||
(upper right), the back edge flips edge (lower left), and the other two flip edge (lower front). This appears to produce
|
||||
a consistent naming, but this has not yet been proven.
|
||||
|
||||
Given this, cube positions are printed as follows: `[edges]/[corners]`
|
||||
The edges are given names from a-f according to where they belong, and they are printed in order based on what piece is
|
||||
actually there. The letter is capitalized if it is "flipped". The corners are printed in order, as `+` if it is rotated
|
||||
clockwise from its correct position, `-` if rotated counterclockwise, and `,` if it is rotated correctly.
|
||||
|
||||
Interesting facts
|
||||
=================
|
||||
|
||||
There are a total of 933,120 legal positions for the cube. There are a total of 3,732,480 possible configurations total,
|
||||
meaning that there are two different types of single-bit parity violations: these can be summarized as an ordering
|
||||
violation within the face. (e.g., `acbdef` is invalid), or an odd number of edges are flipped (e.g., `abCdef` is invalid)
|
||||
10
benches/statepack.rs
Normal file
10
benches/statepack.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
use rubik::state::State;
|
||||
|
||||
pub fn bench_pack(c: &mut Criterion) {
|
||||
c.bench_function("unpack", |b| b.iter(|| State::unpack(black_box(12345))));
|
||||
c.bench_function("pack", |b| b.iter(|| State::pack(black_box(State::default()))));
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_pack);
|
||||
criterion_main!(benches);
|
||||
156
devenv.lock
Normal file
156
devenv.lock
Normal file
@@ -0,0 +1,156 @@
|
||||
{
|
||||
"nodes": {
|
||||
"devenv": {
|
||||
"locked": {
|
||||
"dir": "src/modules",
|
||||
"lastModified": 1700140236,
|
||||
"narHash": "sha256-OpukFO0rRG2hJzD+pCQq+nSWuT9dBL6DSvADQaUlmFg=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"rev": "525d60c44de848a6b2dd468f6efddff078eb2af2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"dir": "src/modules",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1673956053,
|
||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1685518550,
|
||||
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"pre-commit-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1660459072,
|
||||
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1700108881,
|
||||
"narHash": "sha256-+Lqybl8kj0+nD/IlAWPPG/RDTa47gff9nbei0u7BntE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "7414e9ee0b3e9903c24d3379f577a417f0aae5f1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1685801374,
|
||||
"narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-23.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"pre-commit-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-utils": "flake-utils",
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1700064067,
|
||||
"narHash": "sha256-1ZWNDzhu8UlVCK7+DUN9dVQfiHX1bv6OQP9VxstY/gs=",
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"rev": "e558068cba67b23b4fbc5537173dbb43748a17e8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"devenv": "devenv",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"pre-commit-hooks": "pre-commit-hooks"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
29
devenv.nix
Normal file
29
devenv.nix
Normal file
@@ -0,0 +1,29 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
# https://devenv.sh/basics/
|
||||
env.GREET = "devenv";
|
||||
|
||||
# https://devenv.sh/packages/
|
||||
packages = [ pkgs.git ];
|
||||
|
||||
# https://devenv.sh/scripts/
|
||||
scripts.hello.exec = "echo hello from $GREET";
|
||||
|
||||
enterShell = ''
|
||||
hello
|
||||
git --version
|
||||
'';
|
||||
|
||||
# https://devenv.sh/languages/
|
||||
# languages.nix.enable = true;
|
||||
|
||||
# https://devenv.sh/pre-commit-hooks/
|
||||
# pre-commit.hooks.shellcheck.enable = true;
|
||||
languages.rust.enable = true;
|
||||
|
||||
# https://devenv.sh/processes/
|
||||
# processes.ping.exec = "ping example.com";
|
||||
|
||||
# See full reference at https://devenv.sh/reference/options/
|
||||
}
|
||||
3
devenv.yaml
Normal file
3
devenv.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
inputs:
|
||||
nixpkgs:
|
||||
url: github:NixOS/nixpkgs/nixpkgs-unstable
|
||||
2
src/lib.rs
Normal file
2
src/lib.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod state;
|
||||
pub mod search;
|
||||
300
src/search.rs
Normal file
300
src/search.rs
Normal file
@@ -0,0 +1,300 @@
|
||||
|
||||
use std::{io::Cursor, cmp::{Ordering, Reverse}, collections::{VecDeque, BinaryHeap, HashMap}, hash::Hash};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashSet};
|
||||
use crate::state::{M0N, M0P, M1N, M1P, M2N, M2P, M3N, M3P, State};
|
||||
|
||||
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct SearchNode {
|
||||
id: u32,
|
||||
last: u32,
|
||||
depth: u32,
|
||||
mov: &'static str,
|
||||
}
|
||||
|
||||
pub trait SearchState {
|
||||
type Id: Ord+Hash+Copy;
|
||||
fn id(&self) -> Self::Id;
|
||||
fn cost(&self) -> u32 {
|
||||
1
|
||||
}
|
||||
fn heuristic(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
// ordering tuned for BinaryHeap
|
||||
impl Ord for SearchNode {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.depth.cmp(&other.depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for SearchNode {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for SearchNode {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.depth == other.depth
|
||||
}
|
||||
}
|
||||
impl Eq for SearchNode {}
|
||||
|
||||
impl SearchState for SearchNode {
|
||||
type Id = u32;
|
||||
|
||||
fn id(&self) -> Self::Id {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn cost(&self) -> u32 {
|
||||
self.depth
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SearchQueue<T>: Default {
|
||||
fn q_next(&mut self) -> Option<T>;
|
||||
fn q_empty(&self) -> bool;
|
||||
fn q_push(&mut self, item: T);
|
||||
fn q_clear(&mut self);
|
||||
fn q_len(&self) -> usize;
|
||||
}
|
||||
|
||||
pub struct SearchEnv<Q> {
|
||||
pub seen: HashMap<u32, (u32, &'static str)>,
|
||||
queue: Q,
|
||||
visits: usize,
|
||||
pub last_pos: u32,
|
||||
}
|
||||
|
||||
impl<Q: SearchQueue<SearchNode>> Default for SearchEnv<Q> {
|
||||
fn default() -> Self {
|
||||
let mut res = Self {
|
||||
seen: HashMap::new(),
|
||||
queue: Q::default(),
|
||||
visits: 0,
|
||||
last_pos: 0,
|
||||
};
|
||||
res.reset();
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<Q: SearchQueue<SearchNode>> SearchEnv<Q> {
|
||||
pub fn reset(&mut self) {
|
||||
self.seen.clear();
|
||||
self.queue.q_clear();
|
||||
let init_node = SearchNode{
|
||||
id: State::default().pack(),
|
||||
depth: 0,
|
||||
last: 0,
|
||||
mov: "["
|
||||
};
|
||||
self.seen.insert(init_node.id, (init_node.id, "S"));
|
||||
self.queue.q_push(init_node);
|
||||
}
|
||||
|
||||
pub fn is_done(&self) -> bool {
|
||||
self.queue.q_empty()
|
||||
}
|
||||
pub fn search(&mut self) {
|
||||
self.reset();
|
||||
eprintln!();
|
||||
let mut last_pos = 0;
|
||||
while !self.is_done() {
|
||||
let node = self.queue.q_next().unwrap();
|
||||
// check whether node should be re-expanded
|
||||
self.visits += 1;
|
||||
if self.visits % 1000 == 0 {
|
||||
eprintln!("\x1b[1A\x1b[K{}k ({} in queue)", self.visits/100, self.queue.q_len());
|
||||
}
|
||||
// if self.seen.insert(node.id, (node.last, node.mov)).is_some() {
|
||||
// continue;
|
||||
// }
|
||||
last_pos = node.id;
|
||||
self.visit(node.id, node.depth);
|
||||
}
|
||||
self.last_pos = last_pos;
|
||||
|
||||
eprintln!("Max depth: {last_pos:x}")
|
||||
}
|
||||
|
||||
pub fn visit(&mut self, id: u32, depth: u32) {
|
||||
let cur = State::from(id);
|
||||
for (name, mov) in [
|
||||
("T-", M0P), ("T+", M0N), ("L-", M3P), ("L+", M3N),
|
||||
("R-", M2P), ("R+", M2N), ("B-", M1P), ("B+", M1N),
|
||||
] {
|
||||
let next = cur + mov;
|
||||
let node = SearchNode {
|
||||
id: next.into(),
|
||||
depth: depth+1,
|
||||
last: id,
|
||||
mov: name,
|
||||
};
|
||||
if self.seen.contains_key(&node.id) {
|
||||
continue
|
||||
} else {
|
||||
self.seen.insert(node.id, (node.last, node.mov))
|
||||
};
|
||||
self.queue.q_push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Unique priority queue
|
||||
/// This contains a list of items, each with an ID and a weight. Only the minimum weight for a given item is kept.
|
||||
pub struct UniquePQueue<Id, Weight, Data> {
|
||||
node_data: HashMap<Id, (Weight, Data)>,
|
||||
queue: BTreeSet<(Weight, Id)>,
|
||||
}
|
||||
impl<I,W,D> UniquePQueue<I,W,D>
|
||||
where I: Hash+Ord+Copy,
|
||||
W: Ord+Copy,
|
||||
D: Clone {
|
||||
pub fn insert(&mut self, id: I, weight: W, data: D) {
|
||||
if let Some((o_weight, o_data)) = self.node_data.get_mut(&id) {
|
||||
if *o_weight < weight {
|
||||
return;
|
||||
}
|
||||
self.queue.remove(&(*o_weight, id));
|
||||
*o_weight = weight;
|
||||
*o_data = data;
|
||||
} else {
|
||||
self.node_data.insert(id, (weight, data));
|
||||
}
|
||||
|
||||
self.queue.insert((weight, id));
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.node_data.clear();
|
||||
self.queue.clear();
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.queue.is_empty()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.queue.len()
|
||||
}
|
||||
pub fn pop_next(&mut self) -> Option<D> {
|
||||
self.queue.pop_first().map(|(_,d)| self.node_data[&d].1.clone())
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
node_data: HashMap::new(),
|
||||
queue: BTreeSet::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct TOf32(f32);
|
||||
|
||||
impl Ord for TOf32 {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.0.total_cmp(&other.0)
|
||||
}
|
||||
}
|
||||
impl PartialOrd for TOf32 {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for TOf32 {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.cmp(other) == Ordering::Equal
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for TOf32 {}
|
||||
|
||||
// BFS
|
||||
pub struct BFS<T>(VecDeque<T>);
|
||||
impl<T> SearchQueue<T> for BFS<T> {
|
||||
fn q_next(&mut self) -> Option<T> { self.0.pop_front() }
|
||||
fn q_empty(&self) -> bool { self.0.is_empty() }
|
||||
fn q_push(&mut self, item: T) { self.0.push_back(item); }
|
||||
fn q_clear(&mut self) { self.0.clear(); }
|
||||
fn q_len(&self) -> usize { self.0.len() }
|
||||
}
|
||||
impl<T> Default for BFS<T> {
|
||||
fn default() -> Self { BFS(VecDeque::new()) }
|
||||
}
|
||||
|
||||
struct CostCompare<T: SearchState>(T);
|
||||
impl<T: SearchState> Ord for CostCompare<T> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
u32::cmp(&self.0.cost(), &other.0.cost()).reverse()
|
||||
}
|
||||
}
|
||||
impl<T: SearchState> PartialOrd for CostCompare<T> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
impl<T: SearchState> Eq for CostCompare<T> {
|
||||
}
|
||||
impl<T: SearchState> PartialEq for CostCompare<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.cmp(other) == Ordering::Equal
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
pub struct BFS1<T: SearchState>{
|
||||
q: BinaryHeap<CostCompare<T>>,
|
||||
seen: HashMap<T::Id, u32>,
|
||||
}
|
||||
|
||||
impl<T: SearchState> SearchQueue<T> for BFS1<T> {
|
||||
fn q_next(&mut self) -> Option<T> { self.q.pop().map(|x| x.0) }
|
||||
fn q_empty(&self) -> bool { self.q.is_empty() }
|
||||
fn q_push(&mut self, item: T) {
|
||||
let id = item.id();
|
||||
if let Some(odist) = self.seen.get(&id) {
|
||||
if *odist < item.cost() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.seen.insert(id, item.cost());
|
||||
self.q.push(CostCompare(item));
|
||||
}
|
||||
fn q_clear(&mut self) {
|
||||
self.q.clear();
|
||||
self.seen.clear();
|
||||
}
|
||||
fn q_len(&self) -> usize { self.q.len() }
|
||||
}
|
||||
impl<T: SearchState> Default for BFS1<T> {
|
||||
fn default() -> Self {
|
||||
BFS1{
|
||||
q: BinaryHeap::new(),
|
||||
seen: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct DFS<T>(Vec<T>);
|
||||
impl<T> SearchQueue<T> for DFS<T> {
|
||||
fn q_next(&mut self) -> Option<T> { self.0.pop() }
|
||||
fn q_empty(&self) -> bool { self.0.is_empty() }
|
||||
fn q_push(&mut self, item: T) { self.0.push(item); }
|
||||
fn q_clear(&mut self) { self.0.clear(); }
|
||||
fn q_len(&self) -> usize { self.0.len() }
|
||||
}
|
||||
impl<T> Default for DFS<T> {
|
||||
fn default() -> Self { DFS(Vec::new()) }
|
||||
}
|
||||
|
||||
225
src/state.rs
Normal file
225
src/state.rs
Normal file
@@ -0,0 +1,225 @@
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::ops::Add;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
|
||||
pub struct State {
|
||||
pub edges: [(u8, bool); 6],
|
||||
pub corners: [u8; 4],
|
||||
}
|
||||
|
||||
impl Default for State {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
edges: [
|
||||
(0, false),
|
||||
(1, false),
|
||||
(2, false),
|
||||
(3, false),
|
||||
(4, false),
|
||||
(5, false)
|
||||
],
|
||||
corners: [0; 4],
|
||||
}
|
||||
}
|
||||
}
|
||||
impl State {
|
||||
pub fn pack(self) -> u32 {
|
||||
// edges first; each edge is numberd 0..=5 and a bool
|
||||
let edges = self.edges.iter().copied().map(|(n,f)| (((f as u32) << 3) | n as u32))
|
||||
.fold(0, |acc, new| acc << 4 | new);
|
||||
let corners = self.corners.iter().map(|c| *c as u32 % 3).fold(edges, |a,n| a << 2 | n);
|
||||
corners
|
||||
}
|
||||
|
||||
pub fn unpack(mut v: u32) -> Self {
|
||||
let mut res = Self::default();
|
||||
for i in 0..6 {
|
||||
let slot = v >> 28;
|
||||
let flip = slot & 8 != 0;
|
||||
let n = (slot & 7) as u8;
|
||||
res.edges[i] = (n, flip);
|
||||
v <<= 4;
|
||||
}
|
||||
for i in 0..4 {
|
||||
res.corners[i] = ((v >> 30) & 3) as u8;
|
||||
v <<= 2;
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
const fn mk_move(corner: usize, dir: bool) -> Self {
|
||||
let mut state = Self {
|
||||
edges: [
|
||||
(0, false),
|
||||
(1, false),
|
||||
(2, false),
|
||||
(3, false),
|
||||
(4, false),
|
||||
(5, false)
|
||||
],
|
||||
corners: [0; 4],
|
||||
}
|
||||
;
|
||||
let mut edges = match corner {
|
||||
0 => [4,5,3],
|
||||
1 => [0,1,3],
|
||||
2 => [2,4,1],
|
||||
3 => [2,0,5],
|
||||
_ => unimplemented!()
|
||||
};
|
||||
|
||||
if !dir {
|
||||
// counter-clockwise
|
||||
let e0 = edges[1];
|
||||
edges[1] = edges[2];
|
||||
edges[2] = e0;
|
||||
}
|
||||
|
||||
const fn mflip((n,f): (u8, bool), df: bool) -> (u8, bool) {
|
||||
(n, f ^ df)
|
||||
}
|
||||
|
||||
state.edges[edges[1]] = (edges[0] as u8, true);
|
||||
state.edges[edges[2]] = (edges[1] as u8, false);
|
||||
state.edges[edges[0]] = (edges[2] as u8, true);
|
||||
|
||||
state.corners[corner] = if dir {
|
||||
1
|
||||
} else {
|
||||
2
|
||||
};
|
||||
|
||||
state
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for State {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let mut res = String::with_capacity(11);
|
||||
for (n,flip) in self.edges {
|
||||
res.push(char::from(if flip { b'A'} else { b'a'} + n) );
|
||||
}
|
||||
res.push('/');
|
||||
for d in self.corners {
|
||||
res.push(match d {
|
||||
0 => ',',
|
||||
1 => '+',
|
||||
2 => '-',
|
||||
_ => '?',
|
||||
})
|
||||
}
|
||||
f.write_str(res.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for State {
|
||||
fn from(value: u32) -> Self {
|
||||
State::unpack(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<State> for u32 {
|
||||
fn from(value: State) -> Self {
|
||||
value.pack()
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for State {
|
||||
type Output = State;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
let mut result = self;
|
||||
for i in 0..6 {
|
||||
let (sn, sf) = rhs.edges[i];
|
||||
let (rn, rf) = self.edges[sn as usize];
|
||||
result.edges[i] = (rn, rf ^ sf);
|
||||
}
|
||||
for i in 0..4 {
|
||||
result.corners[i] = (self.corners[i] + rhs.corners[i]) % 3;
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
pub const M0P: State = State::mk_move(0, true);
|
||||
pub const M1P: State = State::mk_move(1, true);
|
||||
pub const M2P: State = State::mk_move(2, true);
|
||||
pub const M3P: State = State::mk_move(3, true);
|
||||
|
||||
pub const M0N: State = State::mk_move(0, false);
|
||||
pub const M1N: State = State::mk_move(1, false);
|
||||
pub const M2N: State = State::mk_move(2, false);
|
||||
pub const M3N: State = State::mk_move(3, false);
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
fn test_flipped(s: State, edge: usize) -> bool {
|
||||
s.edges[edge] == (edge as u8, true)
|
||||
}
|
||||
|
||||
macro_rules! test_flipped {
|
||||
($mov:expr, $edge:expr) => {{
|
||||
let mov = $mov;
|
||||
assert_eq!(mov.edges[$edge], ($edge, true));
|
||||
}}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_203_2() {
|
||||
test_flipped!(M2P + M0P + M3P, 2)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_312_2() {
|
||||
test_flipped!(M3P + M1P + M2P, 2)
|
||||
}
|
||||
#[test]
|
||||
fn test_102_1() {
|
||||
test_flipped!(M1P + M0P + M2P, 1)
|
||||
}
|
||||
#[test]
|
||||
fn test_231_1() {
|
||||
test_flipped!(M2P + M3P + M1P, 1)
|
||||
}
|
||||
#[test]
|
||||
fn test_301_0() {
|
||||
test_flipped!(M3P + M0P + M1P, 0)
|
||||
}
|
||||
#[test]
|
||||
fn test_123_0() {
|
||||
test_flipped!(M1P + M2P + M3P, 0)
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_210_4() {
|
||||
test_flipped!(M2P + M1P + M0P, 4)
|
||||
}
|
||||
#[test]
|
||||
fn test_032_4() {
|
||||
test_flipped!(M0P + M3P + M2P, 4)
|
||||
}
|
||||
#[test]
|
||||
fn test_130_3() {
|
||||
test_flipped!(M1P+M3P+M0P, 3)
|
||||
}
|
||||
#[test]
|
||||
fn test_021_3() {
|
||||
test_flipped!(M0P+M2P+M1P, 3)
|
||||
}
|
||||
#[test]
|
||||
fn test_320_5() {
|
||||
test_flipped!(M2P + M0P + M3P, 2)
|
||||
}
|
||||
#[test]
|
||||
fn test_013_5() {
|
||||
test_flipped!(M0P+M1P+M3P, 5)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pack() {
|
||||
let st = State::default();
|
||||
assert_eq!(st, State::unpack(st.into()))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user