mapFolding 0.17.0__py3-none-any.whl → 0.18.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- easyRun/NOTcountingFolds.py +16 -10
- easyRun/__init__.py +1 -0
- easyRun/countFolds.py +17 -9
- easyRun/meanders.py +6 -8
- mapFolding/__init__.py +24 -35
- mapFolding/_e/Z0Z_analysisPython/SORTZ0Z_hypothesis.py +189 -0
- mapFolding/_e/Z0Z_analysisPython/SORTZ0Z_p2d6.py +143 -0
- mapFolding/_e/Z0Z_analysisPython/__init__.py +4 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/__init__.py +0 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200.py +369 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/2001.py +694 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/270/211.py +514 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/270/2111.py +480 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/272/214.py +511 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/272/2141.py +515 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/272/214/344/270/211.py +485 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/200/344/272/214/344/270/2111.py +442 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/211.py +313 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/270/2111.py +343 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/272/214.py +400 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/272/2141.py +497 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/272/214/344/270/211.py +463 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/344/272/214/344/270/2111.py +441 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266.py +35 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/2661.py +35 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200.py +382 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/2001.py +630 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/270/211.py +488 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/270/2111.py +475 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/272/214.py +473 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/272/2141.py +500 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/272/214/344/270/211.py +465 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/200/344/272/214/344/270/2111.py +439 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/211.py +599 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/270/2111.py +536 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/272/214.py +506 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/272/2141.py +533 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/272/214/344/270/211.py +489 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/aggregated/351/246/226/351/233/266/344/272/214/344/270/2111.py +474 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/2001.py +2158 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/2001Negative.py +2158 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200Negative.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/270/211.py +1397 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/270/2111.py +1291 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/270/2111Negative.py +1291 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/270/211Negative.py +1397 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214.py +1240 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/2141.py +1420 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/2141Negative.py +1420 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214Negative.py +1240 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214/344/270/211.py +1366 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214/344/270/2111.py +1274 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214/344/270/2111Negative.py +1274 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/200/344/272/214/344/270/211Negative.py +1366 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/211.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/2111.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/2111Negative.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/270/211Negative.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214.py +1102 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/2141.py +1422 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/2141Negative.py +1422 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214Negative.py +1102 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214/344/270/211.py +1240 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214/344/270/2111.py +1228 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214/344/270/2111Negative.py +1228 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/344/272/214/344/270/211Negative.py +1240 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266.py +32 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/2661.py +1162 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/2661Negative.py +1162 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266Negative.py +32 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/2001.py +1926 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/2001Negative.py +1926 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200Negative.py +1186 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/270/211.py +1291 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/270/2111.py +1176 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/270/2111Negative.py +1176 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/270/211Negative.py +1291 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214.py +1228 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/2141.py +1324 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/2141Negative.py +1324 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214Negative.py +1228 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214/344/270/211.py +1274 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214/344/270/2111.py +1038 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214/344/270/2111Negative.py +1038 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/200/344/272/214/344/270/211Negative.py +1274 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/211.py +2158 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/2111.py +1926 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/2111Negative.py +1926 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/270/211Negative.py +2158 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214.py +1422 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/2141.py +1364 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/2141Negative.py +1364 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214Negative.py +1422 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214/344/270/211.py +1420 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214/344/270/2111.py +1324 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214/344/270/2111Negative.py +1324 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d5/351/246/226/351/233/266/344/272/214/344/270/211Negative.py +1420 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200.py +3133 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/2001.py +6039 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/2001Negative.py +6039 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200Negative.py +3133 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/270/211.py +3527 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/270/2111.py +2300 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/270/2111Negative.py +2300 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/270/211Negative.py +3527 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214.py +3597 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/2141.py +3317 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/2141Negative.py +3317 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214Negative.py +3597 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214/344/270/211.py +3161 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214/344/270/2111.py +2877 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214/344/270/2111Negative.py +2877 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/200/344/272/214/344/270/211Negative.py +3161 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/211.py +2981 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/2111.py +3055 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/2111Negative.py +3055 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/270/211Negative.py +2981 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214.py +3221 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/2141.py +3988 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/2141Negative.py +3988 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214Negative.py +3221 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214/344/270/211.py +3652 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214/344/270/2111.py +2863 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214/344/270/2111Negative.py +2863 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/344/272/214/344/270/211Negative.py +3652 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200.py +2485 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/2001.py +4566 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/2001Negative.py +4566 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200Negative.py +2485 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/270/211.py +3006 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/270/2111.py +2485 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/270/2111Negative.py +2485 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/270/211Negative.py +3006 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214.py +3304 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/2141.py +3015 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/2141Negative.py +3015 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214Negative.py +3304 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214/344/270/211.py +2939 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214/344/270/2111.py +2589 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214/344/270/2111Negative.py +2589 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/200/344/272/214/344/270/211Negative.py +2939 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/211.py +3899 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/2111.py +2996 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/2111Negative.py +2996 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/270/211Negative.py +3899 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214.py +3223 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/2141.py +3020 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/2141Negative.py +3020 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214Negative.py +3223 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214/344/270/211.py +3250 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214/344/270/2111.py +2667 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214/344/270/2111Negative.py +2667 -0
- mapFolding/_e/Z0Z_analysisPython/exclusionData/collatedp2d6/351/246/226/351/233/266/344/272/214/344/270/211Negative.py +3250 -0
- mapFolding/_e/Z0Z_analysisPython/measure.py +162 -0
- mapFolding/_e/Z0Z_analysisPython/positionAnalysis.py +403 -0
- mapFolding/_e/Z0Z_analysisPython/positionAnalysisPileRanges2d6.py +110 -0
- mapFolding/_e/Z0Z_analysisPython/theExcluderBeast.py +640 -0
- mapFolding/_e/Z0Z_analysisPython/toolkit.py +166 -0
- mapFolding/_e/Z0Z_analysisPython/toolkitCSVsequences.py +188 -0
- mapFolding/_e/Z0Z_analysisPython/workBenchPatternFinder.py +284 -0
- mapFolding/_e/Z0Z_notes/__init__.py +0 -0
- mapFolding/_e/Z0Z_notes/knowledgeDump.py +214 -0
- mapFolding/_e/__init__.py +45 -0
- mapFolding/_e/_beDRY.py +547 -0
- mapFolding/_e/_dataDynamic.py +1164 -0
- mapFolding/_e/_measure.py +579 -0
- mapFolding/_e/_semiotics.py +363 -0
- mapFolding/_e/_theTypes.py +31 -0
- mapFolding/_e/algorithms/__init__.py +1 -0
- mapFolding/_e/algorithms/constraintPropagation.py +158 -0
- mapFolding/_e/algorithms/elimination.py +118 -0
- mapFolding/_e/algorithms/eliminationCrease.py +66 -0
- mapFolding/_e/algorithms/iff.py +584 -0
- mapFolding/_e/basecamp.py +89 -0
- mapFolding/_e/dataBaskets.py +123 -0
- mapFolding/_e/dataRaw/__init__.py +0 -0
- mapFolding/_e/easyRun/__init__.py +0 -0
- mapFolding/_e/easyRun/eliminateFolds.py +72 -0
- mapFolding/_e/easyRun/pinning.py +62 -0
- mapFolding/_e/filters.py +384 -0
- mapFolding/_e/pin2/344/270/212nDimensions.py +882 -0
- mapFolding/_e/pin2/344/270/212nDimensionsAnnex.py +551 -0
- mapFolding/_e/pin2/344/270/212nDimensionsByCrease.py +190 -0
- mapFolding/_e/pin2/344/270/212nDimensionsByDomain.py +459 -0
- mapFolding/_e/pinIt.py +436 -0
- mapFolding/_semiotics.py +42 -0
- mapFolding/_theSSOT.py +11 -56
- mapFolding/_theTypes.py +52 -68
- mapFolding/algorithms/A086345.py +8 -3
- mapFolding/algorithms/__init__.py +1 -1
- mapFolding/algorithms/matrixMeandersNumPyndas.py +18 -18
- mapFolding/algorithms/oeisIDbyFormula.py +4 -4
- mapFolding/algorithms/zCuzDocStoopidoeisIDbyFormula.py +3 -3
- mapFolding/basecamp.py +13 -28
- mapFolding/beDRY.py +108 -99
- mapFolding/filesystemToolkit.py +15 -11
- mapFolding/oeis.py +17 -16
- mapFolding/reference/matrixMeandersAnalysis/prefixNotationNotes.py +2 -2
- mapFolding/reference/meandersDumpingGround/matrixMeandersBaselineV2.py +0 -1
- mapFolding/reference/meandersDumpingGround/matrixMeandersNumPyV1finalForm.py +8 -10
- mapFolding/someAssemblyRequired/RecipeJob.py +5 -5
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +5 -2
- mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +9 -11
- mapFolding/someAssemblyRequired/mapFoldingModules/makeMapFoldingModules.py +2 -1
- mapFolding/someAssemblyRequired/transformationTools.py +2 -2
- mapFolding/tests/Z0Z_test_e_excluder.py +155 -0
- mapFolding/tests/conftest.py +193 -314
- mapFolding/tests/dataSamples/A001417.py +455 -0
- mapFolding/tests/dataSamples/__init__.py +1 -0
- mapFolding/tests/dataSamples/measurementData.py +1818 -0
- mapFolding/tests/dataSamples/p2DnDomain3_2_/351/246/226/344/270/200_/351/246/226/351/233/266/344/270/200.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain3_/351/246/226/344/270/200.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain5_4.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain6_5.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain6_7_5_4.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain7_6.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain/351/246/226/344/272/214_/351/246/226/351/233/266/344/270/200/344/272/214.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain/351/246/226/344/272/214_/351/246/226/351/233/266/344/272/214_/351/246/226/351/233/266/344/270/200/344/272/214_/351/246/226/344/270/200/344/272/214.py +17 -0
- mapFolding/tests/dataSamples/p2DnDomain/351/246/226/351/233/266/344/270/200/344/272/214_/351/246/226/344/270/200/344/272/214.py +15 -0
- mapFolding/tests/dataSamples/p2DnDomain/351/246/226/351/233/266/344/272/214_/351/246/226/344/272/214.py +15 -0
- mapFolding/tests/dataSamples/semioticsData.py +135 -0
- mapFolding/tests/test_computations.py +133 -88
- mapFolding/tests/test_e_computations.py +42 -0
- mapFolding/tests/test_e_dataDynamic.py +189 -0
- mapFolding/tests/test_e_measurements.py +257 -0
- mapFolding/tests/test_e_pinning.py +61 -0
- mapFolding/tests/test_e_semiotics.py +128 -0
- mapFolding/tests/test_filesystem.py +39 -17
- mapFolding/tests/{test_other.py → test_parameterValidation.py} +3 -3
- mapFolding/tests/{test_tasks.py → test_taskDivisions.py} +42 -23
- mapFolding/zCuzDocStoopid/makeDocstrings.py +3 -2
- {mapfolding-0.17.0.dist-info → mapfolding-0.18.0.dist-info}/METADATA +15 -9
- mapfolding-0.18.0.dist-info/RECORD +305 -0
- {mapfolding-0.17.0.dist-info → mapfolding-0.18.0.dist-info}/WHEEL +1 -1
- easyRun/A000682.py +0 -25
- easyRun/A005316.py +0 -20
- mapFolding/algorithms/A000136constraintPropagation.py +0 -95
- mapFolding/algorithms/A000136elimination.py +0 -163
- mapFolding/algorithms/A000136eliminationParallel.py +0 -77
- mapfolding-0.17.0.dist-info/RECORD +0 -107
- {mapfolding-0.17.0.dist-info → mapfolding-0.18.0.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.17.0.dist-info → mapfolding-0.18.0.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.17.0.dist-info → mapfolding-0.18.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,1164 @@
|
|
|
1
|
+
from bisect import bisect_right
|
|
2
|
+
from collections import defaultdict
|
|
3
|
+
from collections.abc import Callable, Iterable, Iterator, Sequence
|
|
4
|
+
from cytoolz.dicttoolz import merge
|
|
5
|
+
from cytoolz.functoolz import curry as syntacticCurry
|
|
6
|
+
from functools import cache
|
|
7
|
+
from gmpy2 import bit_flip, bit_mask, is_even, is_odd
|
|
8
|
+
from hunterMakesPy import raiseIfNone
|
|
9
|
+
from hunterMakesPy.filesystemToolkit import writePython
|
|
10
|
+
from mapFolding import ansiColorReset, ansiColors, decreasing, inclusive, packageSettings
|
|
11
|
+
from mapFolding._e import (
|
|
12
|
+
dimensionFourthNearest首, dimensionIndex, dimensionNearestTail, dimensionNearest首, dimensionSecondNearest首,
|
|
13
|
+
dimensionThirdNearest首, getPileRangeOfLeaves, getSumsOfProductsOfDimensionsNearest首, howManyDimensionsHaveOddParity,
|
|
14
|
+
JeanValjean, Leaf, leafInSubHyperplane, leafOrigin, mapShapeIs2上nDimensions, PermutationSpace, Pile, pileOrigin,
|
|
15
|
+
reverseLookup, 一, 三, 二, 四, 零, 首一, 首一二, 首三, 首二, 首零, 首零一, 首零一二, 首零二)
|
|
16
|
+
from mapFolding._e.dataBaskets import EliminationState
|
|
17
|
+
from mapFolding._e.filters import between, consecutive, exclude, leafIsPinned
|
|
18
|
+
from more_itertools import all_unique, loops
|
|
19
|
+
from operator import add, neg, sub
|
|
20
|
+
from pathlib import Path, PurePath
|
|
21
|
+
from typing import Any
|
|
22
|
+
import pandas
|
|
23
|
+
import sys
|
|
24
|
+
|
|
25
|
+
#======== Creases =================================
|
|
26
|
+
|
|
27
|
+
def getLeavesCreaseAnte(state: EliminationState, leaf: Leaf) -> Iterator[Leaf]:
|
|
28
|
+
"""1) `leaf` has at most `dimensionsTotal - 1` many creases.
|
|
29
|
+
|
|
30
|
+
2) The list is ordered by increasing dimension number, which corresponds to an increasing absolute magnitude of _change_ in `leaf` number.
|
|
31
|
+
|
|
32
|
+
3) The list of creases *might* be a list of Gray codes.
|
|
33
|
+
"""
|
|
34
|
+
return iter(_getCreases(state, leaf, increase=False))
|
|
35
|
+
|
|
36
|
+
def getLeavesCreasePost(state: EliminationState, leaf: Leaf) -> Iterator[Leaf]:
|
|
37
|
+
"""1) `leaf` has at most `dimensionsTotal - 1` many creases.
|
|
38
|
+
|
|
39
|
+
2) The list is ordered by increasing dimension number, which corresponds to an increasing absolute magnitude of _change_ in `leaf` number.
|
|
40
|
+
|
|
41
|
+
3) The list of creases *might* be a list of Gray codes.
|
|
42
|
+
"""
|
|
43
|
+
return iter(_getCreases(state, leaf, increase=True))
|
|
44
|
+
|
|
45
|
+
def _getCreases(state: EliminationState, leaf: Leaf, *, increase: bool = True) -> tuple[Leaf, ...]:
|
|
46
|
+
return _makeCreases(leaf, state.dimensionsTotal)[increase]
|
|
47
|
+
@cache
|
|
48
|
+
def _makeCreases(leaf: Leaf, dimensionsTotal: int) -> tuple[tuple[Leaf, ...], tuple[Leaf, ...]]:
|
|
49
|
+
listLeavesCrease: list[Leaf] = [int(bit_flip(leaf, dimensionIndex)) for dimensionIndex in range(dimensionsTotal)]
|
|
50
|
+
|
|
51
|
+
if leaf == leafOrigin: # A special case I've been unable to figure out how to incorporate in the formula.
|
|
52
|
+
listLeavesCreasePost: list[Leaf] = [1]
|
|
53
|
+
listLeavesCreaseAnte: list[Leaf] = []
|
|
54
|
+
else:
|
|
55
|
+
slicingIndices: int = is_odd(howManyDimensionsHaveOddParity(leaf))
|
|
56
|
+
|
|
57
|
+
slicerAnte: slice = slice(slicingIndices, dimensionNearest首(leaf) * bit_flip(slicingIndices, 0) or None)
|
|
58
|
+
slicerPost: slice = slice(bit_flip(slicingIndices, 0), dimensionNearest首(leaf) * slicingIndices or None)
|
|
59
|
+
|
|
60
|
+
if is_even(leaf):
|
|
61
|
+
if slicerAnte.start == 1:
|
|
62
|
+
slicerAnte = slice(slicerAnte.start + dimensionNearestTail(leaf), slicerAnte.stop)
|
|
63
|
+
if slicerPost.start == 1:
|
|
64
|
+
slicerPost = slice(slicerPost.start + dimensionNearestTail(leaf), slicerPost.stop)
|
|
65
|
+
listLeavesCreaseAnte: list[Leaf] = listLeavesCrease[slicerAnte]
|
|
66
|
+
listLeavesCreasePost: list[Leaf] = listLeavesCrease[slicerPost]
|
|
67
|
+
|
|
68
|
+
if leaf == 1: # A special case I've been unable to figure out how to incorporate in the formula.
|
|
69
|
+
listLeavesCreaseAnte = [0]
|
|
70
|
+
return (tuple(listLeavesCreaseAnte), tuple(listLeavesCreasePost))
|
|
71
|
+
|
|
72
|
+
#======== (mathematical) ranges of piles ====================
|
|
73
|
+
# TODO Ideally, figure out the formula for pile ranges instead of deconstructing leaf domains. Second best, DRYer code.
|
|
74
|
+
|
|
75
|
+
#-------- Boolean filters for (mathematical) ranges of piles -----------------------------------
|
|
76
|
+
|
|
77
|
+
@syntacticCurry
|
|
78
|
+
def filterCeiling(pile: Pile, dimensionsTotal: int, leaf: Leaf) -> bool:
|
|
79
|
+
return pile < int(bit_mask(dimensionsTotal) ^ bit_mask(dimensionsTotal - dimensionNearest首(leaf))) - howManyDimensionsHaveOddParity(leaf) + 2 - (leaf == leafOrigin)
|
|
80
|
+
|
|
81
|
+
@syntacticCurry
|
|
82
|
+
def filterFloor(pile: Pile, leaf: Leaf) -> bool:
|
|
83
|
+
return int(bit_flip(0, dimensionNearestTail(leaf) + 1)) + howManyDimensionsHaveOddParity(leaf) - 1 - (leaf == leafOrigin) <= pile
|
|
84
|
+
|
|
85
|
+
@syntacticCurry
|
|
86
|
+
def filterParity(pile: Pile, leaf: Leaf) -> bool:
|
|
87
|
+
return (pile & 1) == ((int(bit_flip(0, dimensionNearestTail(leaf) + 1)) + howManyDimensionsHaveOddParity(leaf) - 1 - (leaf == leafOrigin)) & 1)
|
|
88
|
+
|
|
89
|
+
@syntacticCurry
|
|
90
|
+
def filterDoubleParity(pile: Pile, dimensionsTotal: int, leaf: Leaf) -> bool:
|
|
91
|
+
if leaf != 首零(dimensionsTotal)+零:
|
|
92
|
+
return True
|
|
93
|
+
return (pile >> 1 & 1) == ((int(bit_flip(0, dimensionNearestTail(leaf) + 1)) + howManyDimensionsHaveOddParity(leaf) - 1 - (leaf == leafOrigin)) >> 1 & 1)
|
|
94
|
+
|
|
95
|
+
def getPileRange(state: EliminationState, pile: Pile) -> Iterator[Leaf]:
|
|
96
|
+
return iter(_getPileRange(pile, state.dimensionsTotal, state.mapShape, state.leavesTotal))
|
|
97
|
+
@cache
|
|
98
|
+
def _getPileRange(pile: Pile, dimensionsTotal: int, mapShape: tuple[int, ...], leavesTotal: int) -> tuple[Leaf, ...]:
|
|
99
|
+
if mapShapeIs2上nDimensions(mapShape):
|
|
100
|
+
parityMatch: Callable[[Leaf], bool] = filterParity(pile)
|
|
101
|
+
pileAboveFloor: Callable[[Leaf], bool] = filterFloor(pile)
|
|
102
|
+
pileBelowCeiling: Callable[[Leaf], bool] = filterCeiling(pile, dimensionsTotal)
|
|
103
|
+
matchLargerStep: Callable[[Leaf], bool] = filterDoubleParity(pile, dimensionsTotal)
|
|
104
|
+
|
|
105
|
+
pileRange: Iterable[Leaf] = range(leavesTotal)
|
|
106
|
+
pileRange = filter(parityMatch, pileRange)
|
|
107
|
+
pileRange = filter(pileAboveFloor, pileRange)
|
|
108
|
+
pileRange = filter(pileBelowCeiling, pileRange)
|
|
109
|
+
return tuple(filter(matchLargerStep, pileRange))
|
|
110
|
+
|
|
111
|
+
return tuple(range(leavesTotal))
|
|
112
|
+
|
|
113
|
+
def getDictionaryPileRanges(state: EliminationState) -> dict[Pile, tuple[Leaf, ...]]:
|
|
114
|
+
"""At `pile`, which `leaf` values may be found in a `folding`: the mathematical range, not a Python `range` object."""
|
|
115
|
+
return {pile: tuple(getPileRange(state, pile)) for pile in range(state.leavesTotal)}
|
|
116
|
+
|
|
117
|
+
#======== Leaf domains ====================================
|
|
118
|
+
|
|
119
|
+
def getLeafDomain(state: EliminationState, leaf: Leaf) -> range:
|
|
120
|
+
return _getLeafDomain(leaf, state.dimensionsTotal, state.mapShape, state.leavesTotal)
|
|
121
|
+
@cache
|
|
122
|
+
def _getLeafDomain(leaf: Leaf, dimensionsTotal: int, mapShape: tuple[int, ...], leavesTotal: int) -> range:
|
|
123
|
+
"""The subroutines assume `dimensionLength == 2`, but I think the concept could be extended to other `mapShape`."""
|
|
124
|
+
state: EliminationState = EliminationState(mapShape)
|
|
125
|
+
if mapShapeIs2上nDimensions(state.mapShape):
|
|
126
|
+
originPinned: bool = leaf == leafOrigin
|
|
127
|
+
return range(
|
|
128
|
+
state.sumsOfProductsOfDimensions[dimensionNearestTail(leaf) + inclusive] # `start`, first value included in the `range`.
|
|
129
|
+
+ howManyDimensionsHaveOddParity(leaf)
|
|
130
|
+
- originPinned
|
|
131
|
+
|
|
132
|
+
, state.sumsOfProductsOfDimensionsNearest首[dimensionNearest首(leaf)] # `stop`, first value excluded from the `range`.
|
|
133
|
+
+ 2
|
|
134
|
+
- howManyDimensionsHaveOddParity(leaf)
|
|
135
|
+
- originPinned
|
|
136
|
+
|
|
137
|
+
, 2 + (2 * (leaf == 首零(dimensionsTotal)+零)) # `step`
|
|
138
|
+
)
|
|
139
|
+
return range(leavesTotal)
|
|
140
|
+
|
|
141
|
+
"""leaf domains are directly tied to sumsOfProductsOfDimensions and sumsOfProductsOfDimensionsNearest首
|
|
142
|
+
|
|
143
|
+
2d6
|
|
144
|
+
(0, 32, 48, 56, 60, 62, 63) = sumsOfProductsOfDimensionsNearest首
|
|
145
|
+
(0, 1, 3, 7, 15, 31, 63, 127) = sumsOfProductsOfDimensions
|
|
146
|
+
|
|
147
|
+
leaf descends from 63 in sumsOfProductsOfDimensionsNearest首
|
|
148
|
+
first pile is dimensionsTotal and ascends by addends in sumsOfProductsOfDimensions
|
|
149
|
+
|
|
150
|
+
leaf63 starts at pile6 = 6+0
|
|
151
|
+
leaf62 starts at pile7 = 6+1
|
|
152
|
+
leaf60 starts at pile10 = 7+3
|
|
153
|
+
leaf56 starts at pile17 = 10+7
|
|
154
|
+
leaf48 starts at pile32 = 17+15
|
|
155
|
+
leaf32 starts at pile63 = 32+31
|
|
156
|
+
|
|
157
|
+
2d5
|
|
158
|
+
sumsOfProductsOfDimensionsNearest首
|
|
159
|
+
(0, 16, 24, 28, 30, 31)
|
|
160
|
+
|
|
161
|
+
31, 5+0
|
|
162
|
+
30, 5+1
|
|
163
|
+
28, 6+3
|
|
164
|
+
24, 9+7
|
|
165
|
+
16, 16+15
|
|
166
|
+
|
|
167
|
+
sumsOfProductsOfDimensions
|
|
168
|
+
(0, 1, 3, 7, 15, 31, 63)
|
|
169
|
+
|
|
170
|
+
{0: [0],
|
|
171
|
+
1: [1],
|
|
172
|
+
2: [3, 5, 9, 17],
|
|
173
|
+
3: [2, 7, 11, 13, 19, 21, 25],
|
|
174
|
+
4: [3, 5, 6, 9, 10, 15, 18, 23, 27, 29],
|
|
175
|
+
5: [2, 7, 11, 13, 14, 19, 21, 22, 25, 26, 31],
|
|
176
|
+
6: [3, 5, 6, 9, 10, 15, 17, 18, 23, 27, 29, 30],
|
|
177
|
+
7: [2, 4, 7, 11, 13, 14, 19, 21, 22, 25, 26, 31],
|
|
178
|
+
8: [3, 5, 6, 9, 10, 12, 15, 18, 20, 23, 27, 29, 30],
|
|
179
|
+
9: [2, 4, 7, 11, 13, 14, 19, 21, 22, 25, 26, 28, 31],
|
|
180
|
+
10: [3, 5, 6, 9, 10, 12, 15, 17, 18, 20, 23, 27, 29, 30],
|
|
181
|
+
11: [2, 4, 7, 11, 13, 14, 19, 21, 22, 25, 26, 28, 31],
|
|
182
|
+
12: [3, 5, 6, 9, 10, 12, 15, 18, 20, 23, 27, 29, 30],
|
|
183
|
+
13: [2, 4, 7, 11, 13, 14, 19, 21, 22, 25, 26, 28, 31],
|
|
184
|
+
14: [3, 5, 6, 9, 10, 12, 15, 17, 18, 20, 23, 27, 29, 30],
|
|
185
|
+
15: [2, 4, 7, 8, 11, 13, 14, 19, 21, 22, 25, 26, 28, 31],
|
|
186
|
+
16: [3, 5, 6, 9, 10, 12, 15, 18, 20, 23, 24, 27, 29, 30],
|
|
187
|
+
17: [2, 4, 7, 8, 11, 13, 14, 19, 21, 22, 25, 26, 28, 31],
|
|
188
|
+
18: [5, 6, 9, 10, 12, 15, 17, 18, 20, 23, 24, 27, 29, 30],
|
|
189
|
+
19: [4, 7, 8, 11, 13, 14, 19, 21, 22, 25, 26, 28, 31],
|
|
190
|
+
20: [5, 6, 9, 10, 12, 15, 18, 20, 23, 24, 27, 29, 30],
|
|
191
|
+
21: [4, 7, 8, 11, 13, 14, 19, 21, 22, 25, 26, 28, 31],
|
|
192
|
+
22: [5, 6, 9, 10, 12, 15, 17, 18, 20, 23, 24, 27, 29, 30],
|
|
193
|
+
23: [4, 7, 8, 11, 13, 14, 19, 21, 22, 25, 26, 28, 31],
|
|
194
|
+
24: [5, 6, 9, 10, 12, 15, 18, 20, 23, 24, 27, 29, 30],
|
|
195
|
+
25: [4, 8, 11, 13, 14, 19, 21, 22, 25, 26, 28, 31],
|
|
196
|
+
26: [9, 10, 12, 15, 17, 18, 20, 23, 24, 27, 29, 30],
|
|
197
|
+
27: [8, 11, 13, 14, 19, 21, 22, 25, 26, 28, 31],
|
|
198
|
+
28: [9, 10, 12, 18, 20, 23, 24, 27, 29, 30],
|
|
199
|
+
29: [8, 19, 21, 22, 25, 26, 28],
|
|
200
|
+
30: [17, 18, 20, 24],
|
|
201
|
+
31: [16]}
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
"""products of dimensions and sums of products emerge from the formulas in `getLeafDomain`.
|
|
205
|
+
state = EliminationState((2,) * 6)
|
|
206
|
+
domainsOfDimensionOrigins = tuple(getLeafDomain(state, leaf) for leaf in state.productsOfDimensions)[0:-1]
|
|
207
|
+
sumsOfDimensionOrigins = tuple(accumulate(state.productsOfDimensions))[0:-1]
|
|
208
|
+
sumsOfDimensionOriginsReversed = tuple(accumulate(state.productsOfDimensions[::-1], initial=-state.leavesTotal))[1:None]
|
|
209
|
+
for dimensionOrigin, domain, sumOrigins, sumReversed in zip(state.productsOfDimensions, domainsOfDimensionOrigins, sumsOfDimensionOrigins, sumsOfDimensionOriginsReversed, strict=False):
|
|
210
|
+
print(f"{dimensionOrigin:<2}\t{domain.start == sumOrigins = }\t{sumOrigins}\t{sumReversed+2}\t{domain.stop == sumReversed+2 = }")
|
|
211
|
+
1 domain.start == sumOrigins = True 1 2 domain.stop == sumReversed+2 = True
|
|
212
|
+
2 domain.start == sumOrigins = True 3 34 domain.stop == sumReversed+2 = True
|
|
213
|
+
4 domain.start == sumOrigins = True 7 50 domain.stop == sumReversed+2 = True
|
|
214
|
+
8 domain.start == sumOrigins = True 15 58 domain.stop == sumReversed+2 = True
|
|
215
|
+
16 domain.start == sumOrigins = True 31 62 domain.stop == sumReversed+2 = True
|
|
216
|
+
32 domain.start == sumOrigins = True 63 64 domain.stop == sumReversed+2 = True
|
|
217
|
+
|
|
218
|
+
(Note to self: in `sumReversed+2`, consider if this is better explained by `sumReversed - descending + inclusive` or something similar.)
|
|
219
|
+
|
|
220
|
+
The piles of dimension origins (sums of products of dimensions) emerge from the following formulas!
|
|
221
|
+
|
|
222
|
+
(Note: the function below is included to capture the function as it existed at this point in development. I hope the package has improved/evolved by the time you read this.)
|
|
223
|
+
def getLeafDomain(state: EliminationState, leaf: int) -> range:
|
|
224
|
+
def workhorse(leaf: int, dimensionsTotal: int, mapShape: tuple[int, ...], leavesTotal: int) -> range:
|
|
225
|
+
originPinned = leaf == leafOrigin
|
|
226
|
+
return range(
|
|
227
|
+
int(bit_flip(0, howMany0coordinatesAtTail(leaf) + 1)) # `start`, first value included in the `range`.
|
|
228
|
+
+ howManyDimensionsHaveOddParity(leaf)
|
|
229
|
+
- 1 - originPinned
|
|
230
|
+
, int(bit_mask(dimensionsTotal) ^ bit_mask(dimensionsTotal - dimensionNearest首(leaf))) # `stop`, first value excluded from the `range`.
|
|
231
|
+
- howManyDimensionsHaveOddParity(leaf)
|
|
232
|
+
+ 2 - originPinned
|
|
233
|
+
, 2 + (2 * (leaf == 首零(dimensionsTotal)+零)) # `step`
|
|
234
|
+
)
|
|
235
|
+
return workhorse(leaf, state.dimensionsTotal, state.mapShape, state.leavesTotal)
|
|
236
|
+
"""
|
|
237
|
+
|
|
238
|
+
def getDomainDimension一(state: EliminationState) -> tuple[tuple[int, int, int, int], ...]:
|
|
239
|
+
"""The beans and cornbread and beans and cornbread dimension.
|
|
240
|
+
|
|
241
|
+
(leaf一零, leaf一, leaf首一, leaf首零一)
|
|
242
|
+
^^^ Can you see the symmetry? ^^^
|
|
243
|
+
|
|
244
|
+
Accurate in at least six dimensions.
|
|
245
|
+
"""
|
|
246
|
+
domain一零: tuple[int, ...] = tuple(getLeafDomain(state, 一+零))
|
|
247
|
+
domain首一: tuple[int, ...] = tuple(getLeafDomain(state, 首一(state.dimensionsTotal)))
|
|
248
|
+
return _getDomainDimension一(domain一零, domain首一, state.dimensionsTotal)
|
|
249
|
+
@cache
|
|
250
|
+
def _getDomainDimension一(domain一零: tuple[int, ...], domain首一: tuple[int, ...], dimensionsTotal: int) -> tuple[tuple[int, int, int, int], ...]:
|
|
251
|
+
domainCombined: list[tuple[int, int, int, int]] = []
|
|
252
|
+
|
|
253
|
+
for pileOfLeaf一零 in domain一零:
|
|
254
|
+
domainOfLeaf首一: tuple[int, ...] = domain首一
|
|
255
|
+
pilesTotal: int = len(domainOfLeaf首一)
|
|
256
|
+
|
|
257
|
+
listIndicesPilesExcluded: list[int] = []
|
|
258
|
+
|
|
259
|
+
if pileOfLeaf一零 <= 首二(dimensionsTotal):
|
|
260
|
+
pass
|
|
261
|
+
|
|
262
|
+
elif 首二(dimensionsTotal) < pileOfLeaf一零 < 首一(dimensionsTotal):
|
|
263
|
+
listIndicesPilesExcluded.extend([*range(1, pilesTotal // 2), *range(1 + pilesTotal // 2, 3 * pilesTotal // 4)])
|
|
264
|
+
|
|
265
|
+
elif pileOfLeaf一零 == 首一(dimensionsTotal):
|
|
266
|
+
listIndicesPilesExcluded.extend([*range(1, pilesTotal // 2)])
|
|
267
|
+
|
|
268
|
+
elif 首一(dimensionsTotal) < pileOfLeaf一零 < 首零(dimensionsTotal)-一:
|
|
269
|
+
listIndicesPilesExcluded.extend([*range(3 * pilesTotal // 4)])
|
|
270
|
+
|
|
271
|
+
elif pileOfLeaf一零 == 首零(dimensionsTotal)-一:
|
|
272
|
+
listIndicesPilesExcluded.extend([*range(1, 3 * pilesTotal // 4)])
|
|
273
|
+
|
|
274
|
+
elif pileOfLeaf一零 == 首零(dimensionsTotal):
|
|
275
|
+
listIndicesPilesExcluded.extend([*range(2, pilesTotal // 2)])
|
|
276
|
+
|
|
277
|
+
domainOfLeaf首一 = tuple(exclude(domainOfLeaf首一, listIndicesPilesExcluded))
|
|
278
|
+
|
|
279
|
+
domainCombined.extend([(pileOfLeaf一零, pileOfLeaf一零 + 1, pileOfLeaf首一, pileOfLeaf首一 + 1) for pileOfLeaf首一 in domainOfLeaf首一])
|
|
280
|
+
|
|
281
|
+
return tuple(filter(all_unique, domainCombined))
|
|
282
|
+
|
|
283
|
+
def getDomainDimension二(state: EliminationState) -> tuple[tuple[int, int, int, int], ...]:
|
|
284
|
+
"""(leaf二一, leaf二一零, leaf二零, leaf二)."""
|
|
285
|
+
domain二零and二: tuple[tuple[int, int], ...] = getDomain二零and二(state)
|
|
286
|
+
domain二一零and二一: tuple[tuple[int, int], ...] = getDomain二一零and二一(state)
|
|
287
|
+
return _getDomainDimension二(domain二零and二, domain二一零and二一, state.dimensionsTotal)
|
|
288
|
+
@cache
|
|
289
|
+
def _getDomainDimension二(domain二零and二: tuple[tuple[int, int], ...], domain二一零and二一: tuple[tuple[int, int], ...], dimensionsTotal: int) -> tuple[tuple[int, int, int, int], ...]:
|
|
290
|
+
domain0corners: tuple[tuple[int, int], ...] = tuple(filter(consecutive, domain二零and二))
|
|
291
|
+
domain一corners: tuple[tuple[int, int], ...] = tuple(filter(consecutive, domain二一零and二一))
|
|
292
|
+
pilesTotal: int = len(domain一corners)
|
|
293
|
+
|
|
294
|
+
domainCombined: list[tuple[int, int, int, int]] = []
|
|
295
|
+
|
|
296
|
+
productsOfDimensions: tuple[int, ...] = tuple(int(bit_flip(0, dimension)) for dimension in range(dimensionsTotal + 1))
|
|
297
|
+
|
|
298
|
+
#======== By exclusion of the indices, add pairs of corners (160 tuples) ====================
|
|
299
|
+
for index, (pileOfLeaf二一零, pileOfLeaf二一) in enumerate(domain一corners):
|
|
300
|
+
listIndicesPilesExcluded: list[int] = []
|
|
301
|
+
|
|
302
|
+
dimensionTail: int = dimensionNearestTail(pileOfLeaf二一)
|
|
303
|
+
|
|
304
|
+
#-------- `excludeBelow` `index` ---------------------------------
|
|
305
|
+
excludeBelow: int = index
|
|
306
|
+
listIndicesPilesExcluded.extend(range(excludeBelow))
|
|
307
|
+
|
|
308
|
+
#-------- `excludeAbove` `index` ---------------------------------
|
|
309
|
+
excludeAbove: int = pilesTotal
|
|
310
|
+
if pileOfLeaf二一 <= 首一(dimensionsTotal):
|
|
311
|
+
if dimensionTail == 1:
|
|
312
|
+
excludeAbove = pilesTotal // 2 + index
|
|
313
|
+
if howManyDimensionsHaveOddParity(pileOfLeaf二一) == 2:
|
|
314
|
+
excludeAbove -= 1
|
|
315
|
+
|
|
316
|
+
if (howManyDimensionsHaveOddParity(pileOfLeaf二一) == 1 and (2 < dimensionNearest首(pileOfLeaf二一))):
|
|
317
|
+
excludeAbove += 2
|
|
318
|
+
|
|
319
|
+
if (howManyDimensionsHaveOddParity(pileOfLeaf二一) == 1
|
|
320
|
+
and (dimensionNearest首(pileOfLeaf二一) - raiseIfNone(dimensionSecondNearest首(pileOfLeaf二一)) < 2)
|
|
321
|
+
):
|
|
322
|
+
addend: int = productsOfDimensions[dimensionsTotal-2] + 4
|
|
323
|
+
excludeAbove = domain0corners.index((pileOfLeaf二一 + addend, pileOfLeaf二一零 + addend))
|
|
324
|
+
|
|
325
|
+
else:
|
|
326
|
+
excludeAbove = 3 * pilesTotal // 4 + 2
|
|
327
|
+
if index == 0:
|
|
328
|
+
excludeAbove = 1
|
|
329
|
+
elif index <= 2:
|
|
330
|
+
addend = 三 + sum(productsOfDimensions[1:dimensionsTotal-2])
|
|
331
|
+
excludeAbove = domain0corners.index((pileOfLeaf二一 + addend, pileOfLeaf二一零 + addend))
|
|
332
|
+
listIndicesPilesExcluded.extend(range(excludeAbove, pilesTotal))
|
|
333
|
+
|
|
334
|
+
#-------- Exclude "knock-out" indices ---------------------------------
|
|
335
|
+
if pileOfLeaf二一 < 首一二(dimensionsTotal):
|
|
336
|
+
if dimensionTail == 4:
|
|
337
|
+
addend = int(bit_flip(0, dimensionTail))
|
|
338
|
+
start: int = domain0corners.index((pileOfLeaf二一 + addend, pileOfLeaf二一零 + addend))
|
|
339
|
+
listIndicesPilesExcluded.extend([*range(start, start + dimensionTail)])
|
|
340
|
+
if dimensionTail == 3:
|
|
341
|
+
addend = int(bit_flip(0, dimensionTail))
|
|
342
|
+
start = domain0corners.index((pileOfLeaf二一 + addend, pileOfLeaf二一零 + addend))
|
|
343
|
+
listIndicesPilesExcluded.extend([*range(start, start + dimensionTail - 1)])
|
|
344
|
+
start = domain0corners.index((pileOfLeaf二一 + addend * 2, pileOfLeaf二一零 + addend * 2))
|
|
345
|
+
listIndicesPilesExcluded.extend([*range(start - 1, start + dimensionTail - 1)])
|
|
346
|
+
if (dimensionTail < 3) and (2 < dimensionNearest首(pileOfLeaf二一)):
|
|
347
|
+
if 5 < dimensionsTotal:
|
|
348
|
+
addend = 四
|
|
349
|
+
start = domain0corners.index((pileOfLeaf二一 + addend, pileOfLeaf二一零 + addend))
|
|
350
|
+
stop: int = start + addend
|
|
351
|
+
step: int = 2
|
|
352
|
+
if (dimensionTail == 1) and (dimensionNearest首(pileOfLeaf二一) == 4):
|
|
353
|
+
start += 2
|
|
354
|
+
stop = start + 1
|
|
355
|
+
if dimensionTail == 2:
|
|
356
|
+
start += 3
|
|
357
|
+
if dimensionNearest首(pileOfLeaf二一) == 4:
|
|
358
|
+
start -= 2
|
|
359
|
+
stop = start + dimensionTail + inclusive
|
|
360
|
+
if howManyDimensionsHaveOddParity(pileOfLeaf二一) == 2:
|
|
361
|
+
stop = start + 1
|
|
362
|
+
listIndicesPilesExcluded.extend([*range(start, stop, step)])
|
|
363
|
+
if (((dimensionNearest首(pileOfLeaf二一) == 3) and (howManyDimensionsHaveOddParity(pileOfLeaf二一) == 1))
|
|
364
|
+
or (dimensionNearest首(pileOfLeaf二一) - raiseIfNone(dimensionSecondNearest首(pileOfLeaf二一)) == 3)):
|
|
365
|
+
addend = pileOfLeaf二一
|
|
366
|
+
start = domain0corners.index((pileOfLeaf二一 + addend, pileOfLeaf二一零 + addend))
|
|
367
|
+
stop = start + 2
|
|
368
|
+
if dimensionTail == 2:
|
|
369
|
+
start += 1
|
|
370
|
+
stop += 1
|
|
371
|
+
if dimensionNearest首(pileOfLeaf二一) == 4:
|
|
372
|
+
start += 3
|
|
373
|
+
stop += 4
|
|
374
|
+
step = 1
|
|
375
|
+
listIndicesPilesExcluded.extend([*range(start, stop, step)])
|
|
376
|
+
if dimensionNearest首(pileOfLeaf二一) == 2:
|
|
377
|
+
addend = 三
|
|
378
|
+
start = domain0corners.index((pileOfLeaf二一 + addend, pileOfLeaf二一零 + addend))
|
|
379
|
+
listIndicesPilesExcluded.extend([*range(start, start + addend, 2)])
|
|
380
|
+
|
|
381
|
+
domainCombined.extend([(pileOfLeaf二一, pileOfLeaf二一零, pileOfLeaf二零, pileOfLeaf二) for pileOfLeaf二零, pileOfLeaf二 in exclude(domain0corners, listIndicesPilesExcluded)])
|
|
382
|
+
|
|
383
|
+
#======== By inclusion of the piles, add non-corners (52 tuples) ====================
|
|
384
|
+
domain一nonCorners: tuple[tuple[int, int], ...] = tuple(set(domain二一零and二一).difference(set(domain一corners)))
|
|
385
|
+
domainCombined.extend([(pileOfLeaf一二, pileOfLeaf二一零, pileOfLeaf二一零 - 1, pileOfLeaf一二 + 1) for pileOfLeaf二一零, pileOfLeaf一二 in domain一nonCorners])
|
|
386
|
+
|
|
387
|
+
return tuple(sorted(filter(all_unique, set(domainCombined))))
|
|
388
|
+
|
|
389
|
+
def getDomainDimension首二(state: EliminationState) -> tuple[tuple[int, int, int, int], ...]:
|
|
390
|
+
"""(leaf首二, leaf首零二, leaf首零一二, leaf首一二)."""
|
|
391
|
+
domain首零二and首二: tuple[tuple[int, int], ...] = getDomain首零二and首二(state)
|
|
392
|
+
domain首零一二and首一二: tuple[tuple[int, int], ...] = getDomain首零一二and首一二(state)
|
|
393
|
+
return _getDomainDimension首二(state.dimensionsTotal, domain首零二and首二, domain首零一二and首一二)
|
|
394
|
+
@cache
|
|
395
|
+
def _getDomainDimension首二(dimensionsTotal: int, domain首零二and首二: tuple[tuple[int, int], ...], domain首零一二and首一二: tuple[tuple[int, int], ...]) -> tuple[tuple[int, int, int, int], ...]:
|
|
396
|
+
domain0corners: tuple[tuple[int, int], ...] = tuple(filter(consecutive, domain首零二and首二))
|
|
397
|
+
domain一corners: tuple[tuple[int, int], ...] = tuple(filter(consecutive, domain首零一二and首一二))
|
|
398
|
+
pilesTotal: Leaf = len(domain一corners)
|
|
399
|
+
|
|
400
|
+
domainCombined: list[tuple[int, int, int, int]] = []
|
|
401
|
+
|
|
402
|
+
#======== By exclusion of the indices, add pairs of corners (160 tuples) ====================
|
|
403
|
+
for index, (pileOfLeaf首零二, pileOfLeaf首二) in enumerate(domain0corners):
|
|
404
|
+
listIndicesPilesExcluded: list[int] = []
|
|
405
|
+
|
|
406
|
+
dimensionTail: int = dimensionNearestTail(pileOfLeaf首零二)
|
|
407
|
+
|
|
408
|
+
#-------- `excludeBelow` `index` ---------------------------------
|
|
409
|
+
excludeBelow: int = index - 1
|
|
410
|
+
listIndicesPilesExcluded.extend(range(excludeBelow))
|
|
411
|
+
|
|
412
|
+
#-------- `excludeAbove` `index` ---------------------------------
|
|
413
|
+
excludeAbove: int = pilesTotal
|
|
414
|
+
if dimensionTail == 1:
|
|
415
|
+
excludeAbove = (pilesTotal - (int((pileOfLeaf首二) ^ bit_mask(dimensionsTotal)) // 4 - 1))
|
|
416
|
+
|
|
417
|
+
if howManyDimensionsHaveOddParity(pileOfLeaf首二) == 3 and (dimensionsTotal - dimensionNearest首(pileOfLeaf首二) >= 2):
|
|
418
|
+
excludeAbove += 2
|
|
419
|
+
|
|
420
|
+
if (howManyDimensionsHaveOddParity(pileOfLeaf首二) == 1
|
|
421
|
+
and (dimensionsTotal - dimensionNearest首(pileOfLeaf首二) >= 2)
|
|
422
|
+
and (dimensionNearest首(pileOfLeaf首二) - raiseIfNone(dimensionSecondNearest首(pileOfLeaf首二)) > 3)
|
|
423
|
+
):
|
|
424
|
+
excludeAbove += 2
|
|
425
|
+
|
|
426
|
+
if (howManyDimensionsHaveOddParity(pileOfLeaf首二) == 1
|
|
427
|
+
and (dimensionNearest首(pileOfLeaf首二) - raiseIfNone(dimensionSecondNearest首(pileOfLeaf首二)) > 4)
|
|
428
|
+
):
|
|
429
|
+
excludeAbove += 2
|
|
430
|
+
|
|
431
|
+
if ((howManyDimensionsHaveOddParity(pileOfLeaf首二) == dimensionsTotal - dimensionNearest首(pileOfLeaf首二))
|
|
432
|
+
and (dimensionNearest首(pileOfLeaf首二) >= 4)
|
|
433
|
+
and (howManyDimensionsHaveOddParity(pileOfLeaf首二) > 1)
|
|
434
|
+
):
|
|
435
|
+
excludeAbove -= 1
|
|
436
|
+
|
|
437
|
+
else:
|
|
438
|
+
if 首零二(dimensionsTotal) <= pileOfLeaf首零二:
|
|
439
|
+
excludeAbove = pilesTotal - 1
|
|
440
|
+
if 首零(dimensionsTotal) < pileOfLeaf首零二 < 首零二(dimensionsTotal):
|
|
441
|
+
excludeAbove = pilesTotal - (int(pileOfLeaf首零二 ^ bit_mask(dimensionsTotal)) // 8 - 1)
|
|
442
|
+
if 首一二(dimensionsTotal) < pileOfLeaf首零二 <= 首零(dimensionsTotal):
|
|
443
|
+
excludeAbove = pilesTotal - int(bit_mask(dimensionsTotal - 4))
|
|
444
|
+
|
|
445
|
+
if pileOfLeaf首零二 == 首一二(dimensionsTotal):
|
|
446
|
+
excludeAbove = pilesTotal - int(bit_mask(dimensionsTotal - 4)) - 1
|
|
447
|
+
if pileOfLeaf首零二 < 首一二(dimensionsTotal):
|
|
448
|
+
excludeAbove = pilesTotal - int(bit_mask(dimensionsTotal - 3)) - (dimensionTail == 2)
|
|
449
|
+
listIndicesPilesExcluded.extend(range(excludeAbove, pilesTotal))
|
|
450
|
+
|
|
451
|
+
#-------- Exclude "knock-out" indices ---------------------------------
|
|
452
|
+
if dimensionTail == 1 and (abs(pileOfLeaf首零二 - 首零(dimensionsTotal)) == 2) and is_even(dimensionsTotal):
|
|
453
|
+
listIndicesPilesExcluded.extend([excludeAbove - 2])
|
|
454
|
+
if dimensionTail != 1 and 首一二(dimensionsTotal) <= pileOfLeaf首零二 <= 首零一(dimensionsTotal):
|
|
455
|
+
if (dimensionTail == 2) and (howManyDimensionsHaveOddParity(pileOfLeaf首零二) + 1 != dimensionNearest首(pileOfLeaf首零二) - raiseIfNone(dimensionSecondNearest首(pileOfLeaf首零二))):
|
|
456
|
+
listIndicesPilesExcluded.extend([pilesTotal - (int(pileOfLeaf首零二 ^ bit_mask(dimensionsTotal)) // 8 + 2)])
|
|
457
|
+
if (pileOfLeaf首零二 <= 首零(dimensionsTotal)) and is_even(dimensionsTotal):
|
|
458
|
+
listIndicesPilesExcluded.extend([pilesTotal - (int(pileOfLeaf首零二 ^ bit_mask(dimensionsTotal)) // 4 - 1)])
|
|
459
|
+
if dimensionTail == 3:
|
|
460
|
+
listIndicesPilesExcluded.extend([excludeAbove - 2])
|
|
461
|
+
if 3 < dimensionTail:
|
|
462
|
+
listIndicesPilesExcluded.extend([pilesTotal - (int(pileOfLeaf首零二 ^ bit_mask(dimensionsTotal)) // 4)])
|
|
463
|
+
|
|
464
|
+
domainCombined.extend([(pileOfLeaf首二, pileOfLeaf首零二, pileOfLeaf首零一二, pileOfLeaf首一二) for pileOfLeaf首零一二, pileOfLeaf首一二 in exclude(domain一corners, listIndicesPilesExcluded)])
|
|
465
|
+
|
|
466
|
+
#======== By inclusion of the piles, add non-corners (52 tuples) ====================
|
|
467
|
+
domain0nonCorners: tuple[tuple[int, int], ...] = tuple(set(domain首零二and首二).difference(set(domain0corners)))
|
|
468
|
+
domainCombined.extend([(pileOfLeaf首二, pileOfLeaf首零二, pileOfLeaf首零二 - 1, pileOfLeaf首二 + 1) for pileOfLeaf首零二, pileOfLeaf首二 in domain0nonCorners])
|
|
469
|
+
|
|
470
|
+
return tuple(sorted(filter(all_unique, set(domainCombined))))
|
|
471
|
+
|
|
472
|
+
def getDomain二零and二(state: EliminationState) -> tuple[tuple[int, int], ...]:
|
|
473
|
+
"""Combined domain of leaf二零 and leaf二."""
|
|
474
|
+
domain二零: tuple[int, ...] = tuple(getLeafDomain(state, 二+零))
|
|
475
|
+
domain二: tuple[int, ...] = tuple(getLeafDomain(state, 二))
|
|
476
|
+
direction: Callable[[int, int], int] = add
|
|
477
|
+
return _getDomains二Or二一(domain二零, domain二, direction, state.dimensionsTotal, state.sumsOfProductsOfDimensions)
|
|
478
|
+
|
|
479
|
+
def getDomain二一零and二一(state: EliminationState) -> tuple[tuple[int, int], ...]:
|
|
480
|
+
"""Combined domain of leaf二一零 and leaf二一."""
|
|
481
|
+
domain二一零: tuple[int, ...] = tuple(getLeafDomain(state, 二+一+零))
|
|
482
|
+
domain二一: tuple[int, ...] = tuple(getLeafDomain(state, 二+一))
|
|
483
|
+
direction: Callable[[int, int], int] = sub
|
|
484
|
+
return _getDomains二Or二一(domain二一零, domain二一, direction, state.dimensionsTotal, state.sumsOfProductsOfDimensions)
|
|
485
|
+
|
|
486
|
+
@cache
|
|
487
|
+
def _getDomains二Or二一(domain零: tuple[int, ...], domain0: tuple[int, ...], direction: Callable[[int, int], int], dimensionsTotal: int, sumsOfProductsOfDimensions: tuple[int, ...]) -> tuple[tuple[int, int], ...]:
|
|
488
|
+
if direction(0, 6009) == 6009:
|
|
489
|
+
ImaDomain二零and二: bool = True
|
|
490
|
+
ImaDomain二一零and二一: bool = False
|
|
491
|
+
else:
|
|
492
|
+
ImaDomain二零and二 = False
|
|
493
|
+
ImaDomain二一零and二一 = True
|
|
494
|
+
|
|
495
|
+
domainCombined: list[tuple[int, int]] = []
|
|
496
|
+
|
|
497
|
+
#======== By exclusion of the indices, add non-consecutive piles (54 pairs) ====================
|
|
498
|
+
pilesTotal: int = len(domain零)
|
|
499
|
+
pilesFewerDomain0: int = pilesTotal - len(domain0)
|
|
500
|
+
|
|
501
|
+
for indexDomain零, pileOfLeaf零 in enumerate(filter(between(pileOrigin, 首零(dimensionsTotal)-零), domain零)):
|
|
502
|
+
indicesDomain0ToExclude: list[int] = []
|
|
503
|
+
|
|
504
|
+
dimensionTail: int = dimensionNearestTail(pileOfLeaf零 - is_odd(pileOfLeaf零))
|
|
505
|
+
|
|
506
|
+
# ******* (Almost) All differences between `_getDomain二零and二` and `_getDomain二一零and二一` *******
|
|
507
|
+
#-------- Two identifiers with different values -------------------
|
|
508
|
+
# One default value from each option is a type of defensive coding, and the type checkers won't complain about possibly unbound values.
|
|
509
|
+
excludeBelowAddend: int = 0
|
|
510
|
+
steppingBasisForUnknownReasons: int = indexDomain零
|
|
511
|
+
if ImaDomain二零and二:
|
|
512
|
+
excludeBelowAddend = 0
|
|
513
|
+
steppingBasisForUnknownReasons = int(bit_mask(dimensionTail - 1).bit_flip(0)) # How the hell did I figure out this bizarre formula?
|
|
514
|
+
elif ImaDomain二一零and二一:
|
|
515
|
+
excludeBelowAddend = int(is_even(indexDomain零) or dimensionTail)
|
|
516
|
+
steppingBasisForUnknownReasons = indexDomain零
|
|
517
|
+
|
|
518
|
+
# - - - - Two special cases that 1) might be inherent, such as the differences in `pilesFewerDomain0`, or 2) might be because the formulas could be better. I'd bet on number 2.
|
|
519
|
+
if ImaDomain二零and二:
|
|
520
|
+
if pileOfLeaf零 == 二:
|
|
521
|
+
indicesDomain0ToExclude.extend([*range(indexDomain零 + 1)])
|
|
522
|
+
if pileOfLeaf零 == (首一(dimensionsTotal) + 首二(dimensionsTotal) + 首三(dimensionsTotal)):
|
|
523
|
+
indexDomain0: int = int(7 * pilesTotal / 8)
|
|
524
|
+
indexDomain0 -= pilesFewerDomain0
|
|
525
|
+
indicesDomain0ToExclude.extend([indexDomain0])
|
|
526
|
+
# ******* end *******
|
|
527
|
+
|
|
528
|
+
#-------- `excludeBelow` `index` ---------------------------------
|
|
529
|
+
excludeBelow: int = indexDomain零 + excludeBelowAddend
|
|
530
|
+
excludeBelow -= pilesFewerDomain0
|
|
531
|
+
indicesDomain0ToExclude.extend(range(excludeBelow))
|
|
532
|
+
|
|
533
|
+
#-------- `excludeAbove` `index` ---------------------------------
|
|
534
|
+
if pileOfLeaf零 <= 首一(dimensionsTotal):
|
|
535
|
+
excludeAbove: int = indexDomain零 + (3 * pilesTotal // 4)
|
|
536
|
+
excludeAbove -= pilesFewerDomain0
|
|
537
|
+
indicesDomain0ToExclude.extend(range(excludeAbove, pilesTotal))
|
|
538
|
+
if 首一(dimensionsTotal) < pileOfLeaf零 < 首零(dimensionsTotal):
|
|
539
|
+
excludeAbove = int(pileOfLeaf零 ^ bit_mask(dimensionsTotal)) // 2
|
|
540
|
+
indicesDomain0ToExclude.extend(range(excludeAbove, pilesTotal))
|
|
541
|
+
|
|
542
|
+
#-------- Exclude by stepping: exclude ((2^dimensionTail - 1) / (2^dimensionTail))-many indices, e.g., 1/2, 3/4, 15/16, after `index` -----------------
|
|
543
|
+
for dimension in range(dimensionTail):
|
|
544
|
+
indicesDomain0ToExclude.extend(range(steppingBasisForUnknownReasons + int(bit_mask(dimension)), pilesTotal, int(bit_flip(0, dimension + 1))))
|
|
545
|
+
|
|
546
|
+
#-------- Exclude "knock-out" indices ---------------------------------
|
|
547
|
+
if dimensionTail == 1:
|
|
548
|
+
if (首二(dimensionsTotal) < pileOfLeaf零 < 首零(dimensionsTotal)-零) and (2 < dimensionNearest首(pileOfLeaf零)):
|
|
549
|
+
if dimensionSecondNearest首(pileOfLeaf零) == 零:
|
|
550
|
+
indexDomain0: int = pilesTotal // 2
|
|
551
|
+
indexDomain0 -= pilesFewerDomain0
|
|
552
|
+
if 4 < domain0[indexDomain0].bit_length():
|
|
553
|
+
indicesDomain0ToExclude.extend([indexDomain0])
|
|
554
|
+
if 首一(dimensionsTotal) < pileOfLeaf零:
|
|
555
|
+
indexDomain0 = -(pilesTotal // 4 - is_odd(pileOfLeaf零))
|
|
556
|
+
indexDomain0 -= -(pilesFewerDomain0)
|
|
557
|
+
indicesDomain0ToExclude.extend([indexDomain0])
|
|
558
|
+
if dimensionSecondNearest首(pileOfLeaf零) == 一:
|
|
559
|
+
indexDomain0 = pilesTotal // 2 + 2
|
|
560
|
+
indexDomain0 -= pilesFewerDomain0
|
|
561
|
+
if domain0[indexDomain0] < 首零(dimensionsTotal):
|
|
562
|
+
indicesDomain0ToExclude.extend([indexDomain0])
|
|
563
|
+
indexDomain0 = -(pilesTotal // 4 - 2)
|
|
564
|
+
indexDomain0 -= -(pilesFewerDomain0)
|
|
565
|
+
if 首一(dimensionsTotal) < pileOfLeaf零:
|
|
566
|
+
indicesDomain0ToExclude.extend([indexDomain0])
|
|
567
|
+
|
|
568
|
+
if dimensionSecondNearest首(pileOfLeaf零) == 一+零:
|
|
569
|
+
indexDomain0 = -(pilesTotal // 4)
|
|
570
|
+
indexDomain0 -= -(pilesFewerDomain0)
|
|
571
|
+
indicesDomain0ToExclude.extend([indexDomain0])
|
|
572
|
+
|
|
573
|
+
indexDomain0 = 3 * pilesTotal // 4
|
|
574
|
+
indexDomain0 -= pilesFewerDomain0
|
|
575
|
+
if pileOfLeaf零 < 首一二(dimensionsTotal):
|
|
576
|
+
# NOTE My thinking: because 首一二(dimensionsTotal)
|
|
577
|
+
dimensionIndexPart首: int = dimensionsTotal
|
|
578
|
+
dimensionIndexPart一: int = dimensionIndex(一)
|
|
579
|
+
dimensionIndexPart二: int = dimensionIndex(二)
|
|
580
|
+
|
|
581
|
+
# Compute the index from the head `首`
|
|
582
|
+
indexSumsOfProductsOfDimensions: int = dimensionIndexPart首 - (dimensionIndexPart一 + dimensionIndexPart二)
|
|
583
|
+
|
|
584
|
+
addend: int = sumsOfProductsOfDimensions[indexSumsOfProductsOfDimensions]
|
|
585
|
+
if ImaDomain二一零and二一:
|
|
586
|
+
addend -= 1 # decreasing?
|
|
587
|
+
pileOfLeaf0: int = addend + 首零(dimensionsTotal)
|
|
588
|
+
indexDomain0 = domain0.index(pileOfLeaf0)
|
|
589
|
+
|
|
590
|
+
indicesDomain0ToExclude.extend([indexDomain0])
|
|
591
|
+
|
|
592
|
+
if dimensionThirdNearest首(pileOfLeaf零) == 零:
|
|
593
|
+
if dimensionSecondNearest首(pileOfLeaf零) == 一+零:
|
|
594
|
+
indicesDomain0ToExclude.extend([indexDomain0 - 2])
|
|
595
|
+
if dimensionNearest首(pileOfLeaf零) == 一+零:
|
|
596
|
+
indicesDomain0ToExclude.extend([indexDomain0 - 2])
|
|
597
|
+
|
|
598
|
+
elif 首一(dimensionsTotal) + 首三(dimensionsTotal) + is_odd(pileOfLeaf零) == pileOfLeaf零:
|
|
599
|
+
indexDomain0 = (3 * pilesTotal // 4) - 1
|
|
600
|
+
indexDomain0 -= pilesFewerDomain0
|
|
601
|
+
indicesDomain0ToExclude.extend([indexDomain0])
|
|
602
|
+
|
|
603
|
+
domainCombined.extend([(pileOfLeaf零, pileOfLeaf0) for pileOfLeaf0 in exclude(domain0, indicesDomain0ToExclude)])
|
|
604
|
+
|
|
605
|
+
#======== By inclusion of the piles, add consecutive piles (22 pairs) ====================
|
|
606
|
+
domainCombined.extend([(pile, direction(pile, 零)) for pile in domain零 if direction(pile, 零) in domain0])
|
|
607
|
+
|
|
608
|
+
return tuple(sorted(set(domainCombined)))
|
|
609
|
+
|
|
610
|
+
def getDomain首零二and首二(state: EliminationState) -> tuple[tuple[int, int], ...]:
|
|
611
|
+
"""Combined domain of leaf首零二 and leaf首二."""
|
|
612
|
+
domain首零二: tuple[int, ...] = tuple(getLeafDomain(state, 首零二(state.dimensionsTotal)))
|
|
613
|
+
domain首二: tuple[int, ...] = tuple(getLeafDomain(state, 首二(state.dimensionsTotal)))
|
|
614
|
+
return _getDomain首零二and首二(domain首零二, domain首二, state.dimensionsTotal)
|
|
615
|
+
@cache
|
|
616
|
+
def _getDomain首零二and首二(domain首零二: tuple[int, ...], domain首二: tuple[int, ...], dimensionsTotal: int) -> tuple[tuple[int, int], ...]:
|
|
617
|
+
domainCombined: list[tuple[int, int]] = []
|
|
618
|
+
|
|
619
|
+
domain零: tuple[int, ...] = domain首零二
|
|
620
|
+
domain0: tuple[int, ...] = domain首二
|
|
621
|
+
|
|
622
|
+
#======== By inclusion of the piles, add consecutive piles (22 pairs) ====================
|
|
623
|
+
direction: Callable[[int, int], int] = sub
|
|
624
|
+
domainCombined.extend([(pile, direction(pile, 零)) for pile in domain零 if direction(pile, 零) in domain0])
|
|
625
|
+
|
|
626
|
+
#======== By exclusion of the indices, add non-consecutive piles (54 pairs) ====================
|
|
627
|
+
pilesTotal: int = len(domain零)
|
|
628
|
+
pilesFewerDomain0: int = pilesTotal - len(domain0)
|
|
629
|
+
|
|
630
|
+
for index, pileOfLeaf零 in enumerate(domain零):
|
|
631
|
+
if pileOfLeaf零 < 首零(dimensionsTotal)+零:
|
|
632
|
+
continue
|
|
633
|
+
listIndicesPilesExcluded: list[int] = []
|
|
634
|
+
|
|
635
|
+
dimensionTail: int = dimensionNearestTail(direction(pileOfLeaf零, is_odd(pileOfLeaf零)))
|
|
636
|
+
|
|
637
|
+
#-------- `excludeBelow` `index` ---------------------------------
|
|
638
|
+
if 首零一(dimensionsTotal) < pileOfLeaf零:
|
|
639
|
+
excludeBelow: int = index + 3 - (3 * pilesTotal // 4)
|
|
640
|
+
else:
|
|
641
|
+
excludeBelow = 2 + (首零一(dimensionsTotal) - direction(pileOfLeaf零, is_odd(pileOfLeaf零))) // 2
|
|
642
|
+
excludeBelow -= pilesFewerDomain0
|
|
643
|
+
listIndicesPilesExcluded.extend(range(excludeBelow))
|
|
644
|
+
|
|
645
|
+
#-------- `excludeAbove` `index` ---------------------------------
|
|
646
|
+
excludeAbove: int = index + 2 - int(bit_mask(dimensionTail))
|
|
647
|
+
excludeAbove -= pilesFewerDomain0
|
|
648
|
+
listIndicesPilesExcluded.extend(range(excludeAbove, pilesTotal))
|
|
649
|
+
|
|
650
|
+
#-------- Exclude by stepping: exclude ((2^dimensionTail - 1) / (2^dimensionTail))-many indices, e.g., 1/2, 3/4, 15/16, after `index` -----------------
|
|
651
|
+
countFromTheEnd: int = pilesTotal - 1
|
|
652
|
+
countFromTheEnd -= pilesFewerDomain0
|
|
653
|
+
steppingBasisForUnknownReasons: int = countFromTheEnd - int(bit_mask(dimensionTail - 1).bit_flip(0))
|
|
654
|
+
for dimension in range(dimensionTail):
|
|
655
|
+
listIndicesPilesExcluded.extend(range(steppingBasisForUnknownReasons - int(bit_mask(dimension)), decreasing, decreasing * int(bit_flip(0, dimension + 1))))
|
|
656
|
+
|
|
657
|
+
#-------- Exclude "knock-out" indices ---------------------------------
|
|
658
|
+
if dimensionTail == 1:
|
|
659
|
+
if (dimensionThirdNearest首(pileOfLeaf零) == 一) and (二+零 <= dimensionNearest首(pileOfLeaf零)):
|
|
660
|
+
indexDomain0: int = (pilesTotal // 2) + 1
|
|
661
|
+
indexDomain0 -= pilesFewerDomain0
|
|
662
|
+
listIndicesPilesExcluded.extend([indexDomain0])
|
|
663
|
+
indexDomain0: int = (pilesTotal // 4) + 1
|
|
664
|
+
indexDomain0 -= pilesFewerDomain0
|
|
665
|
+
listIndicesPilesExcluded.extend([indexDomain0])
|
|
666
|
+
if pileOfLeaf零 < 首零一(dimensionsTotal):
|
|
667
|
+
listIndicesPilesExcluded.extend([indexDomain0 - 2])
|
|
668
|
+
|
|
669
|
+
if howManyDimensionsHaveOddParity(pileOfLeaf零) == 一:
|
|
670
|
+
indexDomain0 = (pilesTotal // 4) + 3
|
|
671
|
+
indexDomain0 -= pilesFewerDomain0
|
|
672
|
+
if dimensionSecondNearest首(pileOfLeaf零) == 一:
|
|
673
|
+
listIndicesPilesExcluded.extend([indexDomain0])
|
|
674
|
+
if dimensionSecondNearest首(pileOfLeaf零) == 二:
|
|
675
|
+
listIndicesPilesExcluded.extend([indexDomain0])
|
|
676
|
+
if (((dimensionNearest首(pileOfLeaf零) == dimensionsTotal - 1) and (dimensionSecondNearest首(pileOfLeaf零) == dimensionsTotal - 3))
|
|
677
|
+
or (dimensionSecondNearest首(pileOfLeaf零) == 二)):
|
|
678
|
+
listIndicesPilesExcluded.extend([indexDomain0 - 2])
|
|
679
|
+
indexDomain0 = (pilesTotal // 2) - 1
|
|
680
|
+
indexDomain0 -= pilesFewerDomain0
|
|
681
|
+
listIndicesPilesExcluded.extend([indexDomain0])
|
|
682
|
+
|
|
683
|
+
elif (首零一(dimensionsTotal) - direction(首三(dimensionsTotal), is_odd(pileOfLeaf零))) == pileOfLeaf零:
|
|
684
|
+
indexDomain0 = (pilesTotal // 4) + 2
|
|
685
|
+
indexDomain0 -= pilesFewerDomain0
|
|
686
|
+
listIndicesPilesExcluded.extend([indexDomain0])
|
|
687
|
+
|
|
688
|
+
domainCombined.extend([(pileOfLeaf零, pileOfLeaf0) for pileOfLeaf0 in exclude(domain0, listIndicesPilesExcluded)])
|
|
689
|
+
|
|
690
|
+
return tuple(sorted(set(domainCombined)))
|
|
691
|
+
|
|
692
|
+
def getDomain首零一二and首一二(state: EliminationState) -> tuple[tuple[int, int], ...]:
|
|
693
|
+
"""Combined domain of leaf首零一二 and leaf首一二."""
|
|
694
|
+
domain首零一二: tuple[int, ...] = tuple(getLeafDomain(state, 首零一二(state.dimensionsTotal)))
|
|
695
|
+
domain首一二: tuple[int, ...] = tuple(getLeafDomain(state, 首一二(state.dimensionsTotal)))
|
|
696
|
+
direction: Callable[[int, int], int] = add
|
|
697
|
+
return _getDomain首零一二and首一二(domain首零一二, domain首一二, direction, state.dimensionsTotal)
|
|
698
|
+
@cache
|
|
699
|
+
def _getDomain首零一二and首一二(domain零: tuple[int, ...], domain0: tuple[int, ...], direction: Callable[[int, int], int], dimensionsTotal: int) -> tuple[tuple[int, int], ...]:
|
|
700
|
+
domainCombined: list[tuple[int, int]] = []
|
|
701
|
+
|
|
702
|
+
#======== By exclusion of the indices, add non-consecutive piles (54 pairs) ====================
|
|
703
|
+
pilesTotal: int = len(domain零)
|
|
704
|
+
pilesFewerDomain0: int = pilesTotal - len(domain0)
|
|
705
|
+
|
|
706
|
+
for indexDomain零, pileOfLeaf零 in enumerate(domain零):
|
|
707
|
+
if pileOfLeaf零 < 首零(dimensionsTotal):
|
|
708
|
+
continue
|
|
709
|
+
indicesDomain0ToExclude: list[int] = []
|
|
710
|
+
|
|
711
|
+
dimensionTail: int = dimensionNearestTail(direction(pileOfLeaf零, is_odd(pileOfLeaf零)))
|
|
712
|
+
|
|
713
|
+
#-------- `excludeBelow` `index` ---------------------------------
|
|
714
|
+
if 首零一(dimensionsTotal) < pileOfLeaf零:
|
|
715
|
+
excludeBelow: int = indexDomain零 + 1 - (3 * pilesTotal // 4)
|
|
716
|
+
else:
|
|
717
|
+
excludeBelow = (首零一(dimensionsTotal) - direction(pileOfLeaf零, is_odd(pileOfLeaf零))) // 2
|
|
718
|
+
excludeBelow -= pilesFewerDomain0
|
|
719
|
+
indicesDomain0ToExclude.extend(range(excludeBelow))
|
|
720
|
+
|
|
721
|
+
#-------- `excludeAbove` `index` ---------------------------------
|
|
722
|
+
excludeAbove: int = indexDomain零 + 1 - int(bit_mask(dimensionTail))
|
|
723
|
+
excludeAbove -= pilesFewerDomain0
|
|
724
|
+
indicesDomain0ToExclude.extend(range(excludeAbove, pilesTotal))
|
|
725
|
+
|
|
726
|
+
#-------- Exclude by stepping: exclude ((2^dimensionTail - 1) / (2^dimensionTail))-many indices, e.g., 1/2, 3/4, 15/16, after `index` -----------------
|
|
727
|
+
steppingBasisForUnknownReasons: int = indexDomain零
|
|
728
|
+
for dimension in range(dimensionTail):
|
|
729
|
+
indicesDomain0ToExclude.extend(range(steppingBasisForUnknownReasons - int(bit_mask(dimension)), decreasing, decreasing * int(bit_flip(0, dimension + 1))))
|
|
730
|
+
|
|
731
|
+
#-------- Exclude "knock-out" indices ---------------------------------
|
|
732
|
+
if dimensionTail == 1:
|
|
733
|
+
if (dimensionThirdNearest首(pileOfLeaf零) == 一) and (二+零 <= dimensionNearest首(pileOfLeaf零)):
|
|
734
|
+
indexDomain0: int = pilesTotal // 2
|
|
735
|
+
indexDomain0 -= pilesFewerDomain0
|
|
736
|
+
indicesDomain0ToExclude.extend([indexDomain0])
|
|
737
|
+
indexDomain0: int = pilesTotal // 4
|
|
738
|
+
indexDomain0 -= pilesFewerDomain0
|
|
739
|
+
indicesDomain0ToExclude.extend([indexDomain0])
|
|
740
|
+
if pileOfLeaf零 < 首零一(dimensionsTotal):
|
|
741
|
+
indicesDomain0ToExclude.extend([indexDomain0 - 2])
|
|
742
|
+
if dimensionThirdNearest首(pileOfLeaf零) == 一+零:
|
|
743
|
+
indexDomain0 = pilesTotal // 4
|
|
744
|
+
indexDomain0 -= pilesFewerDomain0
|
|
745
|
+
if dimensionFourthNearest首(pileOfLeaf零) == 一:
|
|
746
|
+
indicesDomain0ToExclude.extend([indexDomain0])
|
|
747
|
+
if howManyDimensionsHaveOddParity(pileOfLeaf零) == 一:
|
|
748
|
+
indexDomain0 = (pilesTotal // 4) + 2
|
|
749
|
+
indexDomain0 -= pilesFewerDomain0
|
|
750
|
+
if dimensionSecondNearest首(pileOfLeaf零) == 一:
|
|
751
|
+
indexDomain0 = domain0.index(首零(dimensionsTotal) - 一)
|
|
752
|
+
indicesDomain0ToExclude.extend([indexDomain0])
|
|
753
|
+
if dimensionSecondNearest首(pileOfLeaf零) == 二:
|
|
754
|
+
indicesDomain0ToExclude.extend([indexDomain0])
|
|
755
|
+
if (首零二(dimensionsTotal) < pileOfLeaf零) and (二+零 <= dimensionNearest首(pileOfLeaf零)):
|
|
756
|
+
indicesDomain0ToExclude.extend([indexDomain0 - 2])
|
|
757
|
+
indexDomain0 = (pilesTotal // 2) - 2
|
|
758
|
+
indexDomain0 -= pilesFewerDomain0
|
|
759
|
+
indicesDomain0ToExclude.extend([indexDomain0])
|
|
760
|
+
|
|
761
|
+
elif (首零一(dimensionsTotal) - direction(首三(dimensionsTotal), is_odd(pileOfLeaf零))) == pileOfLeaf零:
|
|
762
|
+
indexDomain0 = (pilesTotal // 4) + 1
|
|
763
|
+
indexDomain0 -= pilesFewerDomain0
|
|
764
|
+
indicesDomain0ToExclude.extend([indexDomain0])
|
|
765
|
+
|
|
766
|
+
domainCombined.extend([(pileOfLeaf零, pileOfLeaf0) for pileOfLeaf0 in exclude(domain0, indicesDomain0ToExclude)])
|
|
767
|
+
|
|
768
|
+
#======== By inclusion of the piles, add consecutive piles (22 pairs) ====================
|
|
769
|
+
domainCombined.extend([(pile, direction(pile, 零)) for pile in domain零 if direction(pile, 零) in domain0])
|
|
770
|
+
|
|
771
|
+
return tuple(sorted(set(domainCombined)))
|
|
772
|
+
|
|
773
|
+
def getLeaf首零Plus零Domain(state: EliminationState, leaf: Leaf | None = None) -> tuple[Pile, ...]:
|
|
774
|
+
"""Get the full domain of `leaf首零Plus零` that is valid in all cases, or if `leaf一零` and `leaf首零一` are pinned in `state.permutationSpace`, get a domain of `leaf首零Plus零` customized to `pileOfLeaf一零` and `pileOfLeaf首零一`."""
|
|
775
|
+
if leaf is None:
|
|
776
|
+
leaf = (零)+首零(state.dimensionsTotal)
|
|
777
|
+
domain首零Plus零: tuple[Pile, ...] = tuple(getLeafDomain(state, leaf))
|
|
778
|
+
leaf一零: Leaf = 一+零
|
|
779
|
+
leaf首零一: Leaf = 首零一(state.dimensionsTotal)
|
|
780
|
+
if leafIsPinned(state.permutationSpace, leaf一零) and leafIsPinned(state.permutationSpace, leaf首零一):
|
|
781
|
+
pileOfLeaf一零: Pile = raiseIfNone(reverseLookup(state.permutationSpace, leaf一零))
|
|
782
|
+
pileOfLeaf首零一: Pile = raiseIfNone(reverseLookup(state.permutationSpace, leaf首零一))
|
|
783
|
+
domain首零Plus零 = _getLeaf首零Plus零Domain(domain首零Plus零, pileOfLeaf一零, pileOfLeaf首零一, state.dimensionsTotal, state.leavesTotal)
|
|
784
|
+
return domain首零Plus零
|
|
785
|
+
@cache
|
|
786
|
+
def _getLeaf首零Plus零Domain(domain首零Plus零: tuple[Pile, ...], pileOfLeaf一零: Pile, pileOfLeaf首零一: Pile, dimensionsTotal: int, leavesTotal: int) -> tuple[Pile, ...]:
|
|
787
|
+
pilesTotal: int = 首一(dimensionsTotal)
|
|
788
|
+
|
|
789
|
+
bump: int = 1 - int(pileOfLeaf一零.bit_count() == 1)
|
|
790
|
+
howMany: int = dimensionsTotal - (pileOfLeaf一零.bit_length() + bump)
|
|
791
|
+
onesInBinary: int = int(bit_mask(howMany))
|
|
792
|
+
ImaPattern: int = pilesTotal - onesInBinary
|
|
793
|
+
|
|
794
|
+
listIndicesPilesExcluded: list[int] = []
|
|
795
|
+
if pileOfLeaf一零 == 二:
|
|
796
|
+
listIndicesPilesExcluded.extend([零, 一, 二]) # These symbols make this pattern jump out.
|
|
797
|
+
|
|
798
|
+
if 二 < pileOfLeaf一零 <= 首二(dimensionsTotal):
|
|
799
|
+
stop: int = pilesTotal // 2 - 1
|
|
800
|
+
listIndicesPilesExcluded.extend(range(1, stop))
|
|
801
|
+
|
|
802
|
+
aDimensionPropertyNotFullyUnderstood: int = 5
|
|
803
|
+
for _dimension in loops(dimensionsTotal - aDimensionPropertyNotFullyUnderstood):
|
|
804
|
+
start: int = 1 + stop
|
|
805
|
+
stop += (stop+1) // 2
|
|
806
|
+
listIndicesPilesExcluded.extend([*range(start, stop)])
|
|
807
|
+
|
|
808
|
+
listIndicesPilesExcluded.extend([*range(1 + stop, ImaPattern)])
|
|
809
|
+
|
|
810
|
+
if 首二(dimensionsTotal) < pileOfLeaf一零:
|
|
811
|
+
listIndicesPilesExcluded.extend([*range(1, ImaPattern)])
|
|
812
|
+
|
|
813
|
+
bump = 1 - int((leavesTotal - pileOfLeaf首零一).bit_count() == 1)
|
|
814
|
+
howMany = dimensionsTotal - ((leavesTotal - pileOfLeaf首零一).bit_length() + bump)
|
|
815
|
+
onesInBinary = int(bit_mask(howMany))
|
|
816
|
+
ImaPattern = pilesTotal - onesInBinary
|
|
817
|
+
|
|
818
|
+
aDimensionPropertyNotFullyUnderstood = 5
|
|
819
|
+
|
|
820
|
+
if pileOfLeaf首零一 == leavesTotal-二:
|
|
821
|
+
listIndicesPilesExcluded.extend([-零 -1, -(一) -1])
|
|
822
|
+
if aDimensionPropertyNotFullyUnderstood <= dimensionsTotal:
|
|
823
|
+
listIndicesPilesExcluded.extend([-二 -1])
|
|
824
|
+
|
|
825
|
+
if ((首零一二(dimensionsTotal) < pileOfLeaf首零一 < leavesTotal-二)
|
|
826
|
+
and (首二(dimensionsTotal) < pileOfLeaf一零 <= 首零(dimensionsTotal))):
|
|
827
|
+
listIndicesPilesExcluded.extend([-1])
|
|
828
|
+
|
|
829
|
+
if 首零一二(dimensionsTotal) <= pileOfLeaf首零一 < leavesTotal-二:
|
|
830
|
+
stop: int = pilesTotal // 2 - 1
|
|
831
|
+
listIndicesPilesExcluded.extend(range((1 + inclusive) * decreasing, (stop + inclusive) * decreasing, decreasing))
|
|
832
|
+
|
|
833
|
+
for _dimension in loops(dimensionsTotal - aDimensionPropertyNotFullyUnderstood):
|
|
834
|
+
start: int = 1 + stop
|
|
835
|
+
stop += (stop+1) // 2
|
|
836
|
+
listIndicesPilesExcluded.extend([*range((start + inclusive) * decreasing, (stop + inclusive) * decreasing, decreasing)])
|
|
837
|
+
|
|
838
|
+
listIndicesPilesExcluded.extend([*range((1 + stop + inclusive) * decreasing, (ImaPattern + inclusive) * decreasing, decreasing)])
|
|
839
|
+
|
|
840
|
+
if 二 <= pileOfLeaf一零 <= 首零(dimensionsTotal):
|
|
841
|
+
listIndicesPilesExcluded.extend([零, 一, 二, pilesTotal//2])
|
|
842
|
+
|
|
843
|
+
if ((pileOfLeaf首零一 == 首零一二(dimensionsTotal))
|
|
844
|
+
and (首一(dimensionsTotal) < pileOfLeaf一零 <= 首零(dimensionsTotal))):
|
|
845
|
+
listIndicesPilesExcluded.extend([-1])
|
|
846
|
+
|
|
847
|
+
if 首零一(dimensionsTotal) < pileOfLeaf首零一 < 首零一二(dimensionsTotal):
|
|
848
|
+
if pileOfLeaf一零 in [首一(dimensionsTotal), 首零(dimensionsTotal)]:
|
|
849
|
+
listIndicesPilesExcluded.extend([-1])
|
|
850
|
+
elif 二 < pileOfLeaf一零 < 首二(dimensionsTotal):
|
|
851
|
+
listIndicesPilesExcluded.extend([0])
|
|
852
|
+
|
|
853
|
+
if pileOfLeaf首零一 < 首零一二(dimensionsTotal):
|
|
854
|
+
listIndicesPilesExcluded.extend([*range((1 + inclusive) * decreasing, (ImaPattern + inclusive) * decreasing, decreasing)])
|
|
855
|
+
|
|
856
|
+
pileOfLeaf一零ARCHETYPICAL: int = 首一(dimensionsTotal)
|
|
857
|
+
bump = 1 - int(pileOfLeaf一零ARCHETYPICAL.bit_count() == 1)
|
|
858
|
+
howMany = dimensionsTotal - (pileOfLeaf一零ARCHETYPICAL.bit_length() + bump)
|
|
859
|
+
onesInBinary = int(bit_mask(howMany))
|
|
860
|
+
ImaPattern = pilesTotal - onesInBinary
|
|
861
|
+
|
|
862
|
+
if pileOfLeaf首零一 == leavesTotal-二:
|
|
863
|
+
if pileOfLeaf一零 == 二:
|
|
864
|
+
listIndicesPilesExcluded.extend([零, 一, 二, pilesTotal//2 -1, pilesTotal//2])
|
|
865
|
+
if 二 < pileOfLeaf一零 <= 首零(dimensionsTotal):
|
|
866
|
+
IDK: int = ImaPattern - 1
|
|
867
|
+
listIndicesPilesExcluded.extend([*range(1, 3 * pilesTotal // 4), *range(1 + 3 * pilesTotal // 4, IDK)])
|
|
868
|
+
if 首一(dimensionsTotal) < pileOfLeaf一零 <= 首零(dimensionsTotal):
|
|
869
|
+
listIndicesPilesExcluded.extend([-1])
|
|
870
|
+
|
|
871
|
+
if pileOfLeaf首零一 == 首零一(dimensionsTotal):
|
|
872
|
+
if pileOfLeaf一零 == 首零(dimensionsTotal):
|
|
873
|
+
listIndicesPilesExcluded.extend([-1])
|
|
874
|
+
elif (二 < pileOfLeaf一零 < 首二(dimensionsTotal)) or (首二(dimensionsTotal) < pileOfLeaf一零 < 首一(dimensionsTotal)):
|
|
875
|
+
listIndicesPilesExcluded.extend([0])
|
|
876
|
+
|
|
877
|
+
return tuple(exclude(domain首零Plus零, listIndicesPilesExcluded))
|
|
878
|
+
|
|
879
|
+
def getDictionaryLeafDomains(state: EliminationState) -> dict[int, range]:
|
|
880
|
+
"""For each `leaf`, the associated Python `range` defines the mathematical domain:
|
|
881
|
+
1. every `pile` at which `leaf` may be found in a `folding` and
|
|
882
|
+
2. in the set of all valid foldings, every `pile` at which `leaf` must be found.
|
|
883
|
+
""" # noqa: D205
|
|
884
|
+
return {leaf: getLeafDomain(state, leaf) for leaf in range(state.leavesTotal)}
|
|
885
|
+
|
|
886
|
+
#======== Specialized tools ===============================
|
|
887
|
+
|
|
888
|
+
def getDataFrameFoldings(state: EliminationState) -> pandas.DataFrame | None:
|
|
889
|
+
pathFilename: Path = Path(f'{packageSettings.pathPackage}/tests/dataSamples/arrayFoldingsP2d{state.dimensionsTotal}.pkl')
|
|
890
|
+
dataframeFoldings: pandas.DataFrame | None = None
|
|
891
|
+
if pathFilename.exists():
|
|
892
|
+
dataframeFoldings = pandas.DataFrame(pandas.read_pickle(pathFilename)) # noqa: S301
|
|
893
|
+
else:
|
|
894
|
+
message: str = f"{ansiColors.YellowOnBlack}I received {state.dimensionsTotal = }, but I could not find the data at:\n\t{pathFilename!r}.{ansiColorReset}"
|
|
895
|
+
sys.stderr.write(message + '\n')
|
|
896
|
+
return dataframeFoldings
|
|
897
|
+
|
|
898
|
+
def makeVerificationDataLeavesDomain(listDimensions: Sequence[int], listLeaves: Sequence[int | Callable[[int], int]], pathFilename: PurePath | None = None, settings: dict[str, dict[str, Any]] | None = None) -> PurePath:
|
|
899
|
+
"""Create a Python module containing combined domain data for multiple leaves across multiple mapShapes.
|
|
900
|
+
|
|
901
|
+
This function extracts the actual combined domain (the set of valid pile position tuples) for a group of leaves from pickled
|
|
902
|
+
folding data. The data is used for verification in pytest tests comparing computed domains against empirical data.
|
|
903
|
+
|
|
904
|
+
The combined domain is a set of tuples where each tuple represents the pile positions for the specified leaves in a valid
|
|
905
|
+
folding. For example, if `listLeaves` is `[4, 5, 6, 7]`, each tuple has 4 elements representing the pile where each of those
|
|
906
|
+
leaves appears in a folding.
|
|
907
|
+
|
|
908
|
+
Parameters
|
|
909
|
+
----------
|
|
910
|
+
listDimensions : Sequence[int]
|
|
911
|
+
The dimension counts to process (e.g., `[4, 5, 6]` for 2^4, 2^5, 2^6 leaf maps).
|
|
912
|
+
listLeaves : Sequence[int | Callable[[int], int]]
|
|
913
|
+
The leaves whose combined domain to extract. Elements can be:
|
|
914
|
+
- Integers for absolute leaf indices (e.g., `4`, `5`, `6`, `7`)
|
|
915
|
+
- Callables that take `dimensionsTotal` and return a leaf index (e.g., `首二`, `首零二`)
|
|
916
|
+
pathFilename : PurePath | None = None
|
|
917
|
+
The output file path. If `None`, defaults to `tests/dataSamples/p2DnDomain{leafNames}.py`.
|
|
918
|
+
settings : dict[str, dict[str, Any]] | None = None
|
|
919
|
+
Settings for `writePython` formatter. If `None`, uses defaults.
|
|
920
|
+
|
|
921
|
+
Returns
|
|
922
|
+
-------
|
|
923
|
+
pathFilename : PurePath
|
|
924
|
+
The path where the module was written.
|
|
925
|
+
|
|
926
|
+
"""
|
|
927
|
+
def resolveLeaf(leafSpec: int | Callable[[int], int], dimensionsTotal: int) -> int:
|
|
928
|
+
return leafSpec(dimensionsTotal) if callable(leafSpec) else leafSpec
|
|
929
|
+
|
|
930
|
+
def getLeafName(leafSpec: int | Callable[[int], int]) -> str:
|
|
931
|
+
leafSpecName: str = str(leafSpec)
|
|
932
|
+
if callable(leafSpec):
|
|
933
|
+
leafSpecName = getattr(leafSpec, "__name__", leafSpecName)
|
|
934
|
+
return leafSpecName
|
|
935
|
+
|
|
936
|
+
listLeafNames: list[str] = [getLeafName(leafSpec) for leafSpec in listLeaves]
|
|
937
|
+
filenameLeafPart: str = '_'.join(listLeafNames)
|
|
938
|
+
|
|
939
|
+
if pathFilename is None:
|
|
940
|
+
pathFilename = Path(f"{packageSettings.pathPackage}/tests/dataSamples/p2DnDomain{filenameLeafPart}.py")
|
|
941
|
+
else:
|
|
942
|
+
pathFilename = Path(pathFilename)
|
|
943
|
+
|
|
944
|
+
dictionaryDomainsByDimensions: dict[int, list[tuple[int, ...]]] = {}
|
|
945
|
+
|
|
946
|
+
for dimensionsTotal in listDimensions:
|
|
947
|
+
mapShape: tuple[int, ...] = (2,) * dimensionsTotal
|
|
948
|
+
state: EliminationState = EliminationState(mapShape)
|
|
949
|
+
dataframeFoldings: pandas.DataFrame = raiseIfNone(getDataFrameFoldings(state))
|
|
950
|
+
|
|
951
|
+
listResolvedLeaves: list[int] = [resolveLeaf(leafSpec, dimensionsTotal) for leafSpec in listLeaves]
|
|
952
|
+
|
|
953
|
+
listCombinedTuples: list[tuple[int, ...]] = []
|
|
954
|
+
for indexRow in range(len(dataframeFoldings)):
|
|
955
|
+
rowFolding: pandas.Series = dataframeFoldings.iloc[indexRow]
|
|
956
|
+
tuplePiles: tuple[int, ...] = tuple(int(rowFolding[rowFolding == leaf].index[0]) for leaf in listResolvedLeaves)
|
|
957
|
+
listCombinedTuples.append(tuplePiles)
|
|
958
|
+
|
|
959
|
+
listUniqueTuples: list[tuple[int, ...]] = sorted(set(listCombinedTuples))
|
|
960
|
+
dictionaryDomainsByDimensions[dimensionsTotal] = listUniqueTuples
|
|
961
|
+
|
|
962
|
+
listPythonSource: list[str] = [
|
|
963
|
+
'"""Verification data for combined leaf domains.',
|
|
964
|
+
'',
|
|
965
|
+
'This module contains empirically extracted combined domain data for leaves',
|
|
966
|
+
f'{listLeafNames} across multiple mapShape configurations.',
|
|
967
|
+
'',
|
|
968
|
+
'Each list is named `listDomain2D{dimensionsTotal}` where `dimensionsTotal`',
|
|
969
|
+
'is the exponent in the 2^dimensionsTotal mapShape, and it contains tuples representing',
|
|
970
|
+
'valid pile positions for the specified leaves. The tuple order follows the original',
|
|
971
|
+
'leaf argument order.',
|
|
972
|
+
'"""',
|
|
973
|
+
'',
|
|
974
|
+
]
|
|
975
|
+
|
|
976
|
+
for dimensionsTotal in sorted(dictionaryDomainsByDimensions):
|
|
977
|
+
variableName: str = f"listDomain2D{dimensionsTotal}"
|
|
978
|
+
listPythonSource.append(f'{variableName}: list[tuple[int, ...]] = {dictionaryDomainsByDimensions[dimensionsTotal]!r}')
|
|
979
|
+
listPythonSource.append('')
|
|
980
|
+
|
|
981
|
+
pythonSource: str = '\n'.join(listPythonSource)
|
|
982
|
+
writePython(pythonSource, pathFilename, settings)
|
|
983
|
+
|
|
984
|
+
return pathFilename
|
|
985
|
+
|
|
986
|
+
#======== In development ========================
|
|
987
|
+
# ruff: noqa: SIM102
|
|
988
|
+
# I am developing in this module because of Python's effing namespace and "circular import" issues.
|
|
989
|
+
|
|
990
|
+
# TODO Continue developing getDictionaryConditionalLeafPredecessors
|
|
991
|
+
def getDictionaryConditionalLeafPredecessors(state: EliminationState) -> dict[Leaf, dict[Pile, list[Leaf]]]:
|
|
992
|
+
"""leaf: pile: [conditional `leafPredecessor`].
|
|
993
|
+
|
|
994
|
+
Some leaves are always preceded by one or more leaves. Most leaves, however, are preceded by one or more other leaves only if
|
|
995
|
+
the leaf is in a specific pile.
|
|
996
|
+
"""
|
|
997
|
+
dictionaryConditionalLeafPredecessors: dict[Leaf, dict[Pile, list[Leaf]]] = {}
|
|
998
|
+
if mapShapeIs2上nDimensions(state.mapShape, youMustBeDimensionsTallToPinThis=6):
|
|
999
|
+
dictionaryConditionalLeafPredecessors = _getDictionaryConditionalLeafPredecessors(state.mapShape)
|
|
1000
|
+
return dictionaryConditionalLeafPredecessors
|
|
1001
|
+
@cache
|
|
1002
|
+
def _getDictionaryConditionalLeafPredecessors(mapShape: tuple[int, ...]) -> dict[Leaf, dict[Pile, list[Leaf]]]:
|
|
1003
|
+
"""Prototype."""
|
|
1004
|
+
state = EliminationState(mapShape)
|
|
1005
|
+
dictionaryDomains: dict[Leaf, range] = getDictionaryLeafDomains(state)
|
|
1006
|
+
|
|
1007
|
+
dictionaryPrecedence: dict[Leaf, dict[Pile, list[Leaf]]] = {}
|
|
1008
|
+
|
|
1009
|
+
#======== piles at the beginning of the leaf's domain ================
|
|
1010
|
+
for dimension in range(3, state.dimensionsTotal + inclusive):
|
|
1011
|
+
for countDown in range(dimension - 2 + decreasing, decreasing, decreasing):
|
|
1012
|
+
for leaf in range(state.productsOfDimensions[dimension] - sum(state.productsOfDimensions[countDown:dimension - 2]), state.leavesTotal, state.productsOfDimensions[dimension - 1]):
|
|
1013
|
+
dictionaryPrecedence[leaf] = {aPile: [state.productsOfDimensions[dimensionNearest首(leaf)] + state.productsOfDimensions[dimensionNearestTail(leaf)]]
|
|
1014
|
+
for aPile in list(dictionaryDomains[leaf])[0: getSumsOfProductsOfDimensionsNearest首(state.productsOfDimensions, dimensionFrom首=dimension - 1)[dimension - 2 - countDown] // 2]}
|
|
1015
|
+
|
|
1016
|
+
#-------- The beginning of domain首一Plus零 --------------------------------
|
|
1017
|
+
leaf = (零)+首一(state.dimensionsTotal)
|
|
1018
|
+
dictionaryPrecedence[leaf] = {aPile: [2 * state.productsOfDimensions[dimensionNearest首(leaf)] + state.productsOfDimensions[dimensionNearestTail(leaf)]
|
|
1019
|
+
, 3 * state.productsOfDimensions[dimensionNearest首(leaf)] + state.productsOfDimensions[dimensionNearestTail(leaf)]]
|
|
1020
|
+
for aPile in list(dictionaryDomains[leaf])[1:2]}
|
|
1021
|
+
del leaf
|
|
1022
|
+
|
|
1023
|
+
#======== leaf首零一Plus零: conditional `leafPredecessor` in all piles of its domain ===========
|
|
1024
|
+
leaf: Leaf = (零)+首零一(state.dimensionsTotal)
|
|
1025
|
+
listOfPiles = list(dictionaryDomains[leaf])
|
|
1026
|
+
dictionaryPrecedence[leaf] = {aPile: [] for aPile in list(dictionaryDomains[leaf])}
|
|
1027
|
+
sumsOfProductsOfDimensionsNearest首: tuple[int, ...] = getSumsOfProductsOfDimensionsNearest首(state.productsOfDimensions)
|
|
1028
|
+
sumsOfProductsOfDimensionsNearest首InSubHyperplane: tuple[int, ...] = getSumsOfProductsOfDimensionsNearest首(state.productsOfDimensions, dimensionFrom首=state.dimensionsTotal - 1)
|
|
1029
|
+
pileStepAbsolute = 2
|
|
1030
|
+
|
|
1031
|
+
for aPile in listOfPiles[listOfPiles.index(一+零): listOfPiles.index(neg(零)+首零(state.dimensionsTotal)) + inclusive]:
|
|
1032
|
+
dictionaryPrecedence[leaf][aPile].append((零)+首零(state.dimensionsTotal))
|
|
1033
|
+
|
|
1034
|
+
for indexUniversal in range(state.dimensionsTotal - 2):
|
|
1035
|
+
leafPredecessorTheFirst: int = state.sumsOfProductsOfDimensions[indexUniversal + 2]
|
|
1036
|
+
leavesPredecessorInThisSeries: int = state.productsOfDimensions[howManyDimensionsHaveOddParity(leafPredecessorTheFirst)]
|
|
1037
|
+
for addend in range(leavesPredecessorInThisSeries):
|
|
1038
|
+
leafPredecessor = leafPredecessorTheFirst + (addend * decreasing)
|
|
1039
|
+
pileFirst: int = (
|
|
1040
|
+
sumsOfProductsOfDimensionsNearest首[indexUniversal]
|
|
1041
|
+
+ state.sumsOfProductsOfDimensions[2]
|
|
1042
|
+
+ state.productsOfDimensions[state.dimensionsTotal - (indexUniversal + 2)]
|
|
1043
|
+
- ((pileStepAbsolute * 2 * (howManyDimensionsHaveOddParity(leafPredecessor) - 1 + is_even(leafPredecessor)))
|
|
1044
|
+
* (1 + (2 == (howManyDimensionsHaveOddParity(leafPredecessor) + is_even(leafPredecessor)) == dimensionNearest首(leafPredecessor)))
|
|
1045
|
+
)
|
|
1046
|
+
)
|
|
1047
|
+
for aPile in listOfPiles[listOfPiles.index(pileFirst): None]:
|
|
1048
|
+
dictionaryPrecedence[leaf][aPile].append(leafPredecessor)
|
|
1049
|
+
|
|
1050
|
+
leafPredecessor首零: int = leafPredecessor + 首零(state.dimensionsTotal)
|
|
1051
|
+
if (leafInSubHyperplane(leafPredecessor) == 0) and is_odd(dimensionNearestTail(leafPredecessor)):
|
|
1052
|
+
dictionaryPrecedence[leaf][pileFirst].append(leafPredecessor首零)
|
|
1053
|
+
if leafPredecessor首零 == leaf:
|
|
1054
|
+
continue
|
|
1055
|
+
pileFirst = listOfPiles[-1] - (
|
|
1056
|
+
pileStepAbsolute * (
|
|
1057
|
+
howManyDimensionsHaveOddParity(leafPredecessor首零)
|
|
1058
|
+
- 1
|
|
1059
|
+
+ is_even(leafPredecessor首零)
|
|
1060
|
+
- is_odd(leafPredecessor首零)
|
|
1061
|
+
- int(dimensionNearestTail(leafPredecessor首零) == state.dimensionsTotal - 2)
|
|
1062
|
+
- int(leaf < leafPredecessor首零)
|
|
1063
|
+
))
|
|
1064
|
+
for aPile in listOfPiles[listOfPiles.index(pileFirst): None]:
|
|
1065
|
+
dictionaryPrecedence[leaf][aPile].append(leafPredecessor首零)
|
|
1066
|
+
|
|
1067
|
+
if indexUniversal < state.dimensionsTotal - 4:
|
|
1068
|
+
if is_odd(dimensionNearestTail(leafPredecessor - is_odd(leafPredecessor))):
|
|
1069
|
+
pileFirst = (
|
|
1070
|
+
sumsOfProductsOfDimensionsNearest首InSubHyperplane[indexUniversal]
|
|
1071
|
+
+ state.sumsOfProductsOfDimensions[2 + 1 + indexUniversal]
|
|
1072
|
+
- (pileStepAbsolute
|
|
1073
|
+
* 2
|
|
1074
|
+
* (howManyDimensionsHaveOddParity(leafPredecessor首零) - 1
|
|
1075
|
+
+ is_even(leafPredecessor首零) * indexUniversal
|
|
1076
|
+
- is_even(leafPredecessor首零) * (int(not(bool(indexUniversal))))
|
|
1077
|
+
)
|
|
1078
|
+
)
|
|
1079
|
+
+ state.productsOfDimensions[state.dimensionsTotal - 1
|
|
1080
|
+
+ addend * (int(not(bool(indexUniversal))))
|
|
1081
|
+
- (indexUniversal + 2)]
|
|
1082
|
+
)
|
|
1083
|
+
for aPile in listOfPiles[listOfPiles.index(pileFirst) + indexUniversal: listOfPiles.index(neg(零)+首零(state.dimensionsTotal)) - indexUniversal + inclusive]:
|
|
1084
|
+
dictionaryPrecedence[leaf][aPile].append(leafPredecessor首零)
|
|
1085
|
+
|
|
1086
|
+
del leaf, listOfPiles, sumsOfProductsOfDimensionsNearest首, pileStepAbsolute, sumsOfProductsOfDimensionsNearest首InSubHyperplane
|
|
1087
|
+
|
|
1088
|
+
#======== leaf首零Plus零: Separate logic because the distance between absolute piles is 4, not 2 ==============
|
|
1089
|
+
# leaf has conditional `leafPredecessor` in all but the first pile of its domain
|
|
1090
|
+
# Reminder: has UNconditional `leafPredecessor` in the first pile: leaf零
|
|
1091
|
+
leaf: Leaf = (零)+首零(state.dimensionsTotal)
|
|
1092
|
+
listOfPiles: list[Pile] = list(dictionaryDomains[leaf])[1: None]
|
|
1093
|
+
dictionaryPrecedence[leaf] = {aPile: [] for aPile in listOfPiles}
|
|
1094
|
+
sumsOfProductsOfDimensionsNearest首: tuple[int, ...] = getSumsOfProductsOfDimensionsNearest首(state.productsOfDimensions)
|
|
1095
|
+
pileStepAbsolute = 4
|
|
1096
|
+
for indexUniversal in range(state.dimensionsTotal - 2):
|
|
1097
|
+
leafPredecessorTheFirst: int = state.sumsOfProductsOfDimensions[indexUniversal + 2]
|
|
1098
|
+
leavesPredecessorInThisSeries = state.productsOfDimensions[howManyDimensionsHaveOddParity(leafPredecessorTheFirst)]
|
|
1099
|
+
for addend in range(leavesPredecessorInThisSeries):
|
|
1100
|
+
leafPredecessor: int = leafPredecessorTheFirst + (addend * decreasing)
|
|
1101
|
+
leafPredecessor首零: int = leafPredecessor + 首零(state.dimensionsTotal)
|
|
1102
|
+
pileFirst = sumsOfProductsOfDimensionsNearest首[indexUniversal] + 6 - (pileStepAbsolute * (howManyDimensionsHaveOddParity(leafPredecessor) - 1 + is_even(leafPredecessor)))
|
|
1103
|
+
for aPile in listOfPiles[listOfPiles.index(pileFirst): None]:
|
|
1104
|
+
dictionaryPrecedence[leaf][aPile].append(leafPredecessor)
|
|
1105
|
+
dictionaryPrecedence[leaf][aPile].append(leafPredecessor首零)
|
|
1106
|
+
|
|
1107
|
+
del leaf, listOfPiles, sumsOfProductsOfDimensionsNearest首, pileStepAbsolute
|
|
1108
|
+
|
|
1109
|
+
#======== piles at the end of the leaf's domain ================
|
|
1110
|
+
#-------- Example of special case: has conditional `leafPredecessor` two steps before the end of the domain --------------------------
|
|
1111
|
+
if state.dimensionsTotal == 6:
|
|
1112
|
+
leaf = 22
|
|
1113
|
+
sliceOfPiles = slice(0, None)
|
|
1114
|
+
listOfPiles = list(dictionaryDomains[leaf])[sliceOfPiles]
|
|
1115
|
+
leafPredecessorPileFirstPileLast = [(15, 43, 43)]
|
|
1116
|
+
for leafPredecessor, pileFirst, pileLast in leafPredecessorPileFirstPileLast:
|
|
1117
|
+
for pile in listOfPiles[listOfPiles.index(pileFirst): listOfPiles.index(pileLast) + inclusive]:
|
|
1118
|
+
dictionaryPrecedence[leaf].setdefault(pile, []).append(leafPredecessor)
|
|
1119
|
+
|
|
1120
|
+
# NOTE Some leaves, such as 16,48, have `leafPredecessor`, such as leaves 40 and 56, with a larger step size.
|
|
1121
|
+
# NOTE There may be "knock-out" leaves, such as within the domain functions, above. Or I might have to find complex formulas, such
|
|
1122
|
+
# as in `pinPile二Crease`. Or, more likely, "knock-out" leaves might be complex formulas that I have not yet discovered.
|
|
1123
|
+
|
|
1124
|
+
return dictionaryPrecedence
|
|
1125
|
+
|
|
1126
|
+
# TODO Implement and use getDictionaryConditionalLeafSuccessors
|
|
1127
|
+
def getDictionaryConditionalLeafSuccessors(state: EliminationState) -> dict[Leaf, dict[Pile, list[Leaf]]]:
|
|
1128
|
+
"""leaf: pile: [conditional `leafSuccessor`]."""
|
|
1129
|
+
return _getDictionaryConditionalLeafSuccessors(state.mapShape)
|
|
1130
|
+
@cache
|
|
1131
|
+
def _getDictionaryConditionalLeafSuccessors(mapShape: tuple[int, ...]) -> dict[Leaf, dict[Pile, list[Leaf]]]:
|
|
1132
|
+
state = EliminationState(mapShape)
|
|
1133
|
+
dictionaryDomains: dict[Leaf, range] = getDictionaryLeafDomains(state)
|
|
1134
|
+
|
|
1135
|
+
dictionarySuccessor: dict[Leaf, dict[Pile, list[Leaf]]] = {}
|
|
1136
|
+
|
|
1137
|
+
dictionaryPrecedence: dict[Leaf, dict[Pile, list[Leaf]]] = getDictionaryConditionalLeafPredecessors(state)
|
|
1138
|
+
|
|
1139
|
+
for leafLater, dictionaryPiles in dictionaryPrecedence.items():
|
|
1140
|
+
tupleDomainLater: tuple[Pile, ...] = tuple(dictionaryDomains[leafLater])
|
|
1141
|
+
dictionaryPilesByPredecessor: defaultdict[Leaf, set[Pile]] = defaultdict(set)
|
|
1142
|
+
for pileLater, listLeafPredecessors in dictionaryPiles.items():
|
|
1143
|
+
for leafEarlier in listLeafPredecessors:
|
|
1144
|
+
dictionaryPilesByPredecessor[leafEarlier].add(pileLater)
|
|
1145
|
+
|
|
1146
|
+
for leafEarlier, setPilesRequiring in dictionaryPilesByPredecessor.items():
|
|
1147
|
+
tupleDomainEarlier: tuple[Pile, ...] = tuple(dictionaryDomains[leafEarlier])
|
|
1148
|
+
listOptionalPiles: list[Pile] = sorted(pile for pile in tupleDomainLater if pile not in setPilesRequiring)
|
|
1149
|
+
for pileEarlier in tupleDomainEarlier:
|
|
1150
|
+
optionalLessEqualCount: int = bisect_right(listOptionalPiles, pileEarlier)
|
|
1151
|
+
if optionalLessEqualCount == 0:
|
|
1152
|
+
listSuccessors: list[Leaf] = dictionarySuccessor.setdefault(leafEarlier, {}).setdefault(pileEarlier, [])
|
|
1153
|
+
if leafLater not in listSuccessors:
|
|
1154
|
+
listSuccessors.append(leafLater)
|
|
1155
|
+
|
|
1156
|
+
return dictionarySuccessor
|
|
1157
|
+
|
|
1158
|
+
# TODO Creation of `permutationSpace2上nDomainDefaults` could possibly be a function. To future proof the performance, I probably want to cache `permutationSpace2上nDomainDefaults`.
|
|
1159
|
+
def addPileRangesOfLeaves(state: EliminationState) -> EliminationState:
|
|
1160
|
+
permutationSpace2上nDomainDefaults: PermutationSpace = {pile: raiseIfNone(JeanValjean(getPileRangeOfLeaves(state.leavesTotal, pileRangeOfLeaves)))
|
|
1161
|
+
for pile, pileRangeOfLeaves in getDictionaryPileRanges(state).items()}
|
|
1162
|
+
state.permutationSpace = merge(permutationSpace2上nDomainDefaults, state.permutationSpace)
|
|
1163
|
+
return state
|
|
1164
|
+
|