From 219bce973c8cb4a4aa49be4b707552e8470639f3 Mon Sep 17 00:00:00 2001 From: raj-open Date: Sun, 4 May 2025 15:42:01 +0200 Subject: [PATCH 01/54] story-problems > staging: corrected linting setup --- .gitignore | 1 + Cargo.lock | 478 +++++++++++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 3 +- justfile | 7 +- rustfmt.toml | 18 ++ 5 files changed, 486 insertions(+), 21 deletions(-) create mode 100644 rustfmt.toml diff --git a/.gitignore b/.gitignore index 3706613..eb47120 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ !/LICENCE !/justfile !/Cargo.toml +!/rustfmt.toml !/pyproject.toml !/*.lock !/.github diff --git a/Cargo.lock b/Cargo.lock index 3c3e9f6..94bdbe8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +dependencies = [ + "memchr", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -67,12 +76,33 @@ version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +[[package]] +name = "autocfg" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.4.0", +] + [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "bitflags" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.9.0" @@ -135,9 +165,9 @@ dependencies = [ "fat-macho", "fs-err", "path-slash", - "rustc_version", + "rustc_version 0.4.1", "rustflags", - "semver", + "semver 1.0.26", "serde", "serde_json", "shlex", @@ -153,7 +183,7 @@ checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" dependencies = [ "camino", "cargo-platform", - "semver", + "semver 1.0.26", "serde", "serde_json", "thiserror 2.0.12", @@ -206,6 +236,15 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "code_challenges" version = "0.1.0" @@ -214,6 +253,7 @@ dependencies = [ "dedent", "dict_derive", "rstest", + "rustfmt", "serde", "serde_json", ] @@ -261,6 +301,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "dirs" version = "5.0.1" @@ -294,6 +340,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" +[[package]] +name = "env_logger" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" +dependencies = [ + "log 0.3.9", + "regex 0.2.11", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -310,6 +366,19 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "extprim" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b1a357c911c352439b460d7b375b5c85977b9db395b703dfee5a94dfb4d66a2" +dependencies = [ + "num-traits", + "rand", + "rustc_version 0.2.3", + "semver 0.9.0", + "serde", +] + [[package]] name = "fat-macho" version = "0.4.9" @@ -325,9 +394,15 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f89bda4c2a21204059a977ed3bfe746677dfd137b83c339e702b0ac91d482aa" dependencies = [ - "autocfg", + "autocfg 1.4.0", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "futures-core" version = "0.3.31" @@ -371,6 +446,15 @@ dependencies = [ "slab", ] +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + [[package]] name = "getrandom" version = "0.2.16" @@ -394,7 +478,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daa0a64d21a7eb230583b4c5f4e23b7e4e57974f96620f42a7e75e08ae66d745" dependencies = [ - "log", + "log 0.4.27", "plain", "scroll", ] @@ -433,6 +517,22 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.172" @@ -445,7 +545,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags", + "bitflags 2.9.0", "libc", ] @@ -455,6 +555,15 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +dependencies = [ + "log 0.4.27", +] + [[package]] name = "log" version = "0.4.27" @@ -467,6 +576,15 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg 1.4.0", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -530,6 +648,121 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.8", + "libc", + "rand_chacha", + "rand_core 0.4.2", + "rand_hc", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi 0.3.9", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.3.1", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi 0.3.9", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi 0.3.9", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_users" version = "0.4.6" @@ -541,16 +774,29 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "regex" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" +dependencies = [ + "aho-corasick 0.6.10", + "memchr", + "regex-syntax 0.5.6", + "thread_local", + "utf8-ranges", +] + [[package]] name = "regex" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ - "aho-corasick", + "aho-corasick 1.1.3", "memchr", "regex-automata", - "regex-syntax", + "regex-syntax 0.8.5", ] [[package]] @@ -559,9 +805,18 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ - "aho-corasick", + "aho-corasick 1.1.3", "memchr", - "regex-syntax", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" +dependencies = [ + "ucd-util", ] [[package]] @@ -585,7 +840,7 @@ dependencies = [ "futures-timer", "futures-util", "rstest_macros", - "rustc_version", + "rustc_version 0.4.1", ] [[package]] @@ -599,20 +854,29 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "regex", + "regex 1.11.1", "relative-path", - "rustc_version", + "rustc_version 0.4.1", "syn 2.0.101", "unicode-ident", ] +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver", + "semver 1.0.26", ] [[package]] @@ -621,13 +885,38 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a39e0e9135d7a7208ee80aa4e3e4b88f0f5ad7be92153ed70686c38a03db2e63" +[[package]] +name = "rustfmt" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec940eed814db0fb7ab928c5f5025f97dc55d1c0e345e39dda2ce9f945557500" +dependencies = [ + "diff", + "env_logger", + "getopts", + "kernel32-sys", + "libc", + "log 0.3.9", + "regex 0.2.11", + "serde", + "serde_derive", + "serde_json", + "strings", + "syntex_errors", + "syntex_syntax", + "term", + "toml", + "unicode-segmentation", + "winapi 0.2.8", +] + [[package]] name = "rustix" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ - "bitflags", + "bitflags 2.9.0", "errno", "libc", "linux-raw-sys", @@ -660,6 +949,15 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.26" @@ -669,6 +967,12 @@ dependencies = [ "serde", ] +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "serde" version = "1.0.219" @@ -722,7 +1026,16 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ - "autocfg", + "autocfg 1.4.0", +] + +[[package]] +name = "strings" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa481ee1bc42fc3df8195f91f7cb43cf8f2b71b48bac40bf5381cfaf7e481f3c" +dependencies = [ + "log 0.3.9", ] [[package]] @@ -753,12 +1066,63 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syntex_errors" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3133289179676c9f5c5b2845bf5a2e127769f4889fcbada43035ef6bd662605e" +dependencies = [ + "libc", + "serde", + "serde_derive", + "syntex_pos", + "term", + "unicode-xid", +] + +[[package]] +name = "syntex_pos" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ab669fa003d208c681f874bbc76d91cc3d32550d16b5d9d2087cf477316470" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "syntex_syntax" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03815b9f04d95828770d9c974aa39c6e1f6ef3114eb77a3ce09008a0d15dd142" +dependencies = [ + "bitflags 0.9.1", + "extprim", + "log 0.3.9", + "serde", + "serde_derive", + "serde_json", + "syntex_errors", + "syntex_pos", + "unicode-xid", +] + [[package]] name = "target-lexicon" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" +[[package]] +name = "term" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" +dependencies = [ + "kernel32-sys", + "winapi 0.2.8", +] + [[package]] name = "terminal_size" version = "0.4.2" @@ -809,6 +1173,24 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +dependencies = [ + "serde", +] + [[package]] name = "toml_datetime" version = "0.6.9" @@ -831,12 +1213,42 @@ dependencies = [ "winnow", ] +[[package]] +name = "ucd-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abd2fc5d32b590614af8b0a20d837f32eca055edd0bbead59a9cfe80858be003" + [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "utf8-ranges" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba" + [[package]] name = "utf8parse" version = "0.2.2" @@ -861,6 +1273,40 @@ dependencies = [ "winsafe", ] +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index d042c43..4894d3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,8 +57,7 @@ dedent = {version="^0.1.1"} [dev-dependencies] cargo-zigbuild = {version = "^0.20.0"} rstest = {version = "^0.25.0"} -# FIXME: currently fail to build on unix -# rustfmt = {version = "^0.10.0", features = []} +rustfmt = {version = "^0.10.0", features = []} # just = {version = "^1.40.0"} [[bin]] diff --git a/justfile b/justfile index 777a925..3affeef 100644 --- a/justfile +++ b/justfile @@ -197,10 +197,11 @@ tests-unit-optimised *args: # -------------------------------- prettify: - @cargo fmt --verbose + @cargo fmt --verbose -- --force prettify-dry: - @cargo fmt --verbose --check + @echo "Not yet implemented" + @# cargo fmt --verbose --check -- --force # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # TARGETS: clean @@ -280,5 +281,5 @@ check-system: check-system-requirements: @just _check-tool "cargo" "cargo" - @# just _check-tool "cargo fmt" "cargo fmt" + @just _check-tool "cargo fmt -- --force" "cargo fmt" @just _check-tool "cargo-zigbuild" "cargo-zigbuild" diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..420ed2d --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,18 @@ +combine_control_expr = false +comment_width = 80 +condense_wildcard_suffixes = false +disable_all_formatting = false +fn_args_layout = "Block" # "Visual", "Block" +fn_call_width = 60 +fn_single_line = false +hard_tabs = false +max_width = 100 +newline_style = "Unix" +normalize_comments = false +struct_lit_width = 40 +trailing_comma = "Vertical" +reorder_imports = false +force_explicit_abi = true +format_strings = false +wrap_comments = false +normalize_doc_attributes = false From 2679def38fb694677654d3140e65e2629ee69eca Mon Sep 17 00:00:00 2001 From: raj-open Date: Sun, 4 May 2025 15:42:18 +0200 Subject: [PATCH 02/54] story-problems > staging: linted code --- src/_core/errors.rs | 2 ++ src/_core/strings.rs | 2 +- src/lib.rs | 3 --- src/main.rs | 1 + src/models/tree/base.rs | 2 +- src/models/tree/model.rs | 10 +++---- src/models/tree/tests_model.rs | 26 +++++++------------ src/problems/hackerrank/mathematics/main.rs | 2 -- .../mathematics/scalar_products/approach1.rs | 21 +++++---------- .../mathematics/scalar_products/approach2.rs | 23 +++++++--------- .../scalar_products/tests_approach1.rs | 4 ++- .../scalar_products/tests_approach2.rs | 2 ++ 12 files changed, 40 insertions(+), 58 deletions(-) diff --git a/src/_core/errors.rs b/src/_core/errors.rs index 8449f35..d991c12 100644 --- a/src/_core/errors.rs +++ b/src/_core/errors.rs @@ -1,12 +1,14 @@ /// ---------------------------------------------------------------- /// IMPORTS /// ---------------------------------------------------------------- + use std::fmt::Debug; /// ---------------------------------------------------------------- /// METHODS /// ---------------------------------------------------------------- +/// Converts error-like entities to strings #[allow(unused)] pub fn err_to_string(err: E) -> String where diff --git a/src/_core/strings.rs b/src/_core/strings.rs index afd776c..b313a66 100644 --- a/src/_core/strings.rs +++ b/src/_core/strings.rs @@ -2,7 +2,7 @@ /// IMPORTS /// ---------------------------------------------------------------- -// +/// /// ---------------------------------------------------------------- /// METHODS diff --git a/src/lib.rs b/src/lib.rs index 5f8dab2..077fd81 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,3 @@ -/// ---------------------------------------------------------------- -/// IMPORTS -/// ---------------------------------------------------------------- pub mod _core; pub mod models; pub mod problems; diff --git a/src/main.rs b/src/main.rs index 1f306d2..7510e1c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ /// ---------------------------------------------------------------- /// IMPORTS /// ---------------------------------------------------------------- + mod _core; /// ---------------------------------------------------------------- diff --git a/src/models/tree/base.rs b/src/models/tree/base.rs index 15a199f..f5962b2 100644 --- a/src/models/tree/base.rs +++ b/src/models/tree/base.rs @@ -2,7 +2,7 @@ /// IMPORTS /// ---------------------------------------------------------------- -// +/// /// ---------------------------------------------------------------- /// TRAITS diff --git a/src/models/tree/model.rs b/src/models/tree/model.rs index ba0d397..b918e32 100644 --- a/src/models/tree/model.rs +++ b/src/models/tree/model.rs @@ -1,16 +1,17 @@ /// ---------------------------------------------------------------- /// IMPORTS /// ---------------------------------------------------------------- -use std::vec; +use std::vec; use super::base::GenericTree; -use super::base::GenericTreeLike; use super::base::GenericTreeOrRoot; +use super::base::GenericTreeLike; /// ---------------------------------------------------------------- /// BASIC IMPLEMENTATION FOR GenericTree /// ---------------------------------------------------------------- +/// Implementation of a tree #[allow(unused)] impl GenericTree where @@ -65,10 +66,7 @@ where fn add(&mut self, other: GenericTreeOrRoot) { match other { GenericTreeOrRoot::Root(u) => { - let t = GenericTree { - root: u, - children: vec![], - }; + let t = GenericTree { root: u, children: vec![] }; self.children.push(t); } GenericTreeOrRoot::Tree(t) => { diff --git a/src/models/tree/tests_model.rs b/src/models/tree/tests_model.rs index 59ca1b3..653efc8 100644 --- a/src/models/tree/tests_model.rs +++ b/src/models/tree/tests_model.rs @@ -53,8 +53,7 @@ mod tests { ├─── alice: 23 ╰─── bob: 24 "# - ) - .to_string(); + ).to_string(); assert_eq!(t.to_string(), expected); } @@ -78,10 +77,7 @@ mod tests { name: Some("bird".to_string()), value: Some(2), }; - let pet1b = DummyNode { - name: None, - value: Some(3), - }; + let pet1b = DummyNode { name: None, value: Some(3) }; child1.add(GenericTreeOrRoot::Root(pet1a)); child1.add(GenericTreeOrRoot::Root(pet1b)); let child2 = DummyNode { @@ -98,16 +94,16 @@ mod tests { │ ╰─── _: 3 ╰─── bob: 24 "# - ) - .to_string(); + ).to_string(); assert_eq!(t.to_string(), expected); } } -// ---------------------------------------------------------------- -// AUXILIARY -// ---------------------------------------------------------------- +/// ---------------------------------------------------------------- +/// AUXILIARY +/// ---------------------------------------------------------------- +/// A dummy node type for test purposes #[derive(Clone)] struct DummyNode { name: Option, @@ -117,13 +113,9 @@ struct DummyNode { impl ToString for DummyNode { fn to_string(&self) -> String { match (&self.name, &self.value) { - (Some(name), Some(value)) => { - format!("{}: {}", name, value) - } + (Some(name), Some(value)) => format!("{}: {}", name, value), (Some(name), None) => name.clone(), - (None, Some(value)) => { - format!("_: {}", value) - } + (None, Some(value)) => format!("_: {}", value), (None, None) => "-".to_string(), } } diff --git a/src/problems/hackerrank/mathematics/main.rs b/src/problems/hackerrank/mathematics/main.rs index e9898a2..c5196c2 100644 --- a/src/problems/hackerrank/mathematics/main.rs +++ b/src/problems/hackerrank/mathematics/main.rs @@ -2,8 +2,6 @@ /// IMPORTS /// ---------------------------------------------------------------- -// - /// ---------------------------------------------------------------- /// MAIN /// ---------------------------------------------------------------- diff --git a/src/problems/hackerrank/mathematics/scalar_products/approach1.rs b/src/problems/hackerrank/mathematics/scalar_products/approach1.rs index 2ac7b02..ea39348 100644 --- a/src/problems/hackerrank/mathematics/scalar_products/approach1.rs +++ b/src/problems/hackerrank/mathematics/scalar_products/approach1.rs @@ -1,5 +1,3 @@ -use core::iter::IntoIterator; -use core::iter::Iterator; /// # First approach # /// /// This approach is not mathematically optimised, @@ -10,6 +8,9 @@ use core::iter::Iterator; /// ---------------------------------------------------------------- /// IMPORTS /// ---------------------------------------------------------------- + +use core::iter::IntoIterator; +use core::iter::Iterator; // use core::convert::TryFrom; use std::collections::HashSet; use std::fmt::Debug; @@ -22,6 +23,7 @@ use std::str::FromStr; /// MAIN /// ---------------------------------------------------------------- +/// entry point when used as a script #[allow(unused)] fn main() { let line = read_input(); @@ -68,7 +70,6 @@ pub fn run(c: i32, m: i32, n: usize) -> usize { /// ---------------------------------------------------------------- /// SECONDARY /// ---------------------------------------------------------------- - #[derive(Clone, Debug)] struct SeqPair { modulus: i32, @@ -91,11 +92,7 @@ where impl SeqPair { fn new(modulus: i32, x: i32, y: i32) -> Self { - Self { - modulus, - current: x, - next: y, - } + Self { modulus, current: x, next: y } } } @@ -134,18 +131,14 @@ impl IntoIterator for SeqPair { type Item = SeqPair; type IntoIter = EntityIterator; - fn into_iter(self) -> EntityIterator { - EntityIterator { - index: 0, - entity: self.clone(), - } + fn into_iter(self) -> Self::IntoIter { + return EntityIterator { index: 0, entity: self.clone() }; } } /// ---------------------------------------------------------------- /// AUXILIARY /// ---------------------------------------------------------------- - #[allow(unused)] fn read_input() -> String { let stdin = io::stdin(); diff --git a/src/problems/hackerrank/mathematics/scalar_products/approach2.rs b/src/problems/hackerrank/mathematics/scalar_products/approach2.rs index 4a2a947..6377a6f 100644 --- a/src/problems/hackerrank/mathematics/scalar_products/approach2.rs +++ b/src/problems/hackerrank/mathematics/scalar_products/approach2.rs @@ -50,6 +50,7 @@ /// ---------------------------------------------------------------- /// IMPORTS /// ---------------------------------------------------------------- + use std::collections::HashSet; use std::fmt::Debug; use std::fmt::Display; @@ -65,6 +66,7 @@ use std::str::FromStr; /// MAIN /// ---------------------------------------------------------------- +/// entry point when used as a script #[allow(unused)] fn main() { let line = read_input(); @@ -85,11 +87,7 @@ pub fn run(c: i32, m: i32, n: usize) -> usize { // sequence generated by symmetric matrix let zero: Modulo = Modulo::new(0, m as i64); let one: Modulo = Modulo::new(1, m as i64); - let matrix_f: SymmMatrix2x2> = SymmMatrix2x2 { - a: zero, - b: one, - d: one, - }; + let matrix_f: SymmMatrix2x2> = SymmMatrix2x2 { a: zero, b: one, d: one }; /* ---- * * The n-the entry of the sequence @@ -128,14 +126,12 @@ pub fn run(c: i32, m: i32, n: usize) -> usize { values.insert(value); } - let num_unique = values.len(); - return num_unique; + return values.len(); } /// ---------------------------------------------------------------- /// SECONDARY /// ---------------------------------------------------------------- - #[derive(Clone, Copy, PartialEq, Eq)] struct Modulo where @@ -287,17 +283,18 @@ where } fn mul_vector(&self, u: &Vector2) -> Vector2 { - Vector2([ - (self.a * u.get(0) + self.b * u.get(1)), - (self.b * u.get(0) + self.d * u.get(1)), - ]) + Vector2( + [ + (self.a * u.get(0) + self.b * u.get(1)), + (self.b * u.get(0) + self.d * u.get(1)), + ], + ) } } /// ---------------------------------------------------------------- /// AUXILIARY /// ---------------------------------------------------------------- - #[allow(unused)] fn read_input() -> String { let stdin = io::stdin(); diff --git a/src/problems/hackerrank/mathematics/scalar_products/tests_approach1.rs b/src/problems/hackerrank/mathematics/scalar_products/tests_approach1.rs index 7a1fb0a..baa1888 100644 --- a/src/problems/hackerrank/mathematics/scalar_products/tests_approach1.rs +++ b/src/problems/hackerrank/mathematics/scalar_products/tests_approach1.rs @@ -1,12 +1,14 @@ /// ---------------------------------------------------------------- /// IMPORTS /// ---------------------------------------------------------------- -use crate::problems::hackerrank::mathematics::scalar_products::approach1 as approach; + +use super::approach1 as approach; /// ---------------------------------------------------------------- /// TESTS /// ---------------------------------------------------------------- +/// bundle of tests #[cfg(test)] mod tests { use super::*; diff --git a/src/problems/hackerrank/mathematics/scalar_products/tests_approach2.rs b/src/problems/hackerrank/mathematics/scalar_products/tests_approach2.rs index 9494312..96e8373 100644 --- a/src/problems/hackerrank/mathematics/scalar_products/tests_approach2.rs +++ b/src/problems/hackerrank/mathematics/scalar_products/tests_approach2.rs @@ -1,12 +1,14 @@ /// ---------------------------------------------------------------- /// IMPORTS /// ---------------------------------------------------------------- + use super::approach2 as approach; /// ---------------------------------------------------------------- /// TESTS /// ---------------------------------------------------------------- +/// bundle of tests #[cfg(test)] mod tests { use super::*; From 2a6df023b93b59b015355c77adb7d5319e36015d Mon Sep 17 00:00:00 2001 From: raj-open Date: Sun, 4 May 2025 15:58:29 +0200 Subject: [PATCH 03/54] story-problems > staging: corrected workflows vis-a-vis formatting --- .github/workflows/manual.yaml | 3 +++ justfile | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/manual.yaml b/.github/workflows/manual.yaml index b5ba444..010070d 100644 --- a/.github/workflows/manual.yaml +++ b/.github/workflows/manual.yaml @@ -106,6 +106,9 @@ jobs: # only performed if qa passes and option set deploy: name: DEPLOY + needs: 'qa' + # job only runs if deploy-checkbox is selected + if: ${{ github.event.inputs.deploy == 'true' }} runs-on: ${{ github.event.inputs.docker-image }} environment: "${{ github.event.inputs.environment }}" env: {} diff --git a/justfile b/justfile index 3affeef..26d2a54 100644 --- a/justfile +++ b/justfile @@ -117,7 +117,6 @@ build-requirements: @just build-requirements-dependencies build-requirements-basic: - @rustup default stable @cargo update --verbose @cargo install --locked --force cargo-zigbuild @# cargo install --locked --force rustfmt @@ -281,5 +280,5 @@ check-system: check-system-requirements: @just _check-tool "cargo" "cargo" - @just _check-tool "cargo fmt -- --force" "cargo fmt" + @# just _check-tool "cargo fmt -- --force" "cargo fmt" @just _check-tool "cargo-zigbuild" "cargo-zigbuild" From d6eb0a036d70bc66a8e5f8073f2171d44bb61aa9 Mon Sep 17 00:00:00 2001 From: raj-open Date: Sun, 4 May 2025 16:09:40 +0200 Subject: [PATCH 04/54] story-problems > staging: set warning messages --- .github/workflows/deploy.yaml | 2 +- .github/workflows/manual.yaml | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 8e2b75a..6980fce 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -61,4 +61,4 @@ jobs: - name: Message shell: bash run: |- - echo "Not yet implemented" + echo "::warning::Not yet implemented" diff --git a/.github/workflows/manual.yaml b/.github/workflows/manual.yaml index 010070d..fa2d0ff 100644 --- a/.github/workflows/manual.yaml +++ b/.github/workflows/manual.yaml @@ -114,9 +114,7 @@ jobs: env: {} steps: - - uses: actions/checkout@v4.2.2 - - name: Message shell: bash run: |- - echo "Not yet implemented" + echo "::warning::Not yet implemented" From 781de4eb2970ae70ff70844f66d62431c8d5c3dc Mon Sep 17 00:00:00 2001 From: raj-open Date: Sun, 4 May 2025 16:22:44 +0200 Subject: [PATCH 05/54] story-problems > staging: corrected input method --- .../mathematics/scalar_products/approach1.rs | 17 +++++++++++------ .../mathematics/scalar_products/approach2.rs | 17 +++++++++++------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/problems/hackerrank/mathematics/scalar_products/approach1.rs b/src/problems/hackerrank/mathematics/scalar_products/approach1.rs index ea39348..cba9b5c 100644 --- a/src/problems/hackerrank/mathematics/scalar_products/approach1.rs +++ b/src/problems/hackerrank/mathematics/scalar_products/approach1.rs @@ -16,6 +16,7 @@ use std::collections::HashSet; use std::fmt::Debug; use std::io; use std::io::BufRead; +use std::io::Stdin; use std::slice::Iter; use std::str::FromStr; @@ -26,7 +27,8 @@ use std::str::FromStr; /// entry point when used as a script #[allow(unused)] fn main() { - let line = read_input(); + let lines = read_input(&io::stdin()); + let line = lines.iter().nth(0).unwrap(); let args: Vec = line.split(" ").map(|x| x.to_string()).collect(); let mut args: Iter<'_, String> = args.iter(); @@ -139,12 +141,15 @@ impl IntoIterator for SeqPair { /// ---------------------------------------------------------------- /// AUXILIARY /// ---------------------------------------------------------------- + +/// Obtains input lines from stdin +/// as a vector of strings. #[allow(unused)] -fn read_input() -> String { - let stdin = io::stdin(); - let mut input = stdin.lock().lines(); - let line = input.next().unwrap().unwrap().trim().to_string(); - return line; +fn read_input(stream: &Stdin) -> Vec { + stream.lock() + .lines() + .filter_map(Result::ok) + .collect() } #[allow(unused)] diff --git a/src/problems/hackerrank/mathematics/scalar_products/approach2.rs b/src/problems/hackerrank/mathematics/scalar_products/approach2.rs index 6377a6f..f3d585b 100644 --- a/src/problems/hackerrank/mathematics/scalar_products/approach2.rs +++ b/src/problems/hackerrank/mathematics/scalar_products/approach2.rs @@ -55,6 +55,7 @@ use std::collections::HashSet; use std::fmt::Debug; use std::fmt::Display; use std::io; +use std::io::Stdin; use std::io::BufRead; use std::ops::Add; use std::ops::Mul; @@ -69,7 +70,8 @@ use std::str::FromStr; /// entry point when used as a script #[allow(unused)] fn main() { - let line = read_input(); + let lines = read_input(&io::stdin()); + let line = lines.iter().nth(0).unwrap(); let args: Vec = line.split(" ").map(|x| x.to_string()).collect(); let mut args: Iter<'_, String> = args.iter(); @@ -295,12 +297,15 @@ where /// ---------------------------------------------------------------- /// AUXILIARY /// ---------------------------------------------------------------- + +/// Obtains input lines from stdin +/// as a vector of strings. #[allow(unused)] -fn read_input() -> String { - let stdin = io::stdin(); - let mut input = stdin.lock().lines(); - let line = input.next().unwrap().unwrap().trim().to_string(); - return line; +fn read_input(stream: &Stdin) -> Vec { + stream.lock() + .lines() + .filter_map(Result::ok) + .collect() } #[allow(unused)] From e7bca8c837f3c4b4a9a560efb3f7b10b7d629933 Mon Sep 17 00:00:00 2001 From: raj-open Date: Sun, 4 May 2025 18:24:14 +0200 Subject: [PATCH 06/54] story-problems > staging: linting --- src/problems/hackerrank/mathematics/mod.rs | 1 + .../hackerrank/mathematics/scalar_products/approach1.rs | 5 +---- .../hackerrank/mathematics/scalar_products/approach2.rs | 5 +---- src/problems/hackerrank/mathematics/scalar_products/mod.rs | 1 + 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/problems/hackerrank/mathematics/mod.rs b/src/problems/hackerrank/mathematics/mod.rs index 277f45b..5f03c25 100644 --- a/src/problems/hackerrank/mathematics/mod.rs +++ b/src/problems/hackerrank/mathematics/mod.rs @@ -1,4 +1,5 @@ /// Contains solutions to challenges in the Mathematics /// section of Hackerrank. /// Source: . + pub mod scalar_products; diff --git a/src/problems/hackerrank/mathematics/scalar_products/approach1.rs b/src/problems/hackerrank/mathematics/scalar_products/approach1.rs index cba9b5c..00792d6 100644 --- a/src/problems/hackerrank/mathematics/scalar_products/approach1.rs +++ b/src/problems/hackerrank/mathematics/scalar_products/approach1.rs @@ -146,10 +146,7 @@ impl IntoIterator for SeqPair { /// as a vector of strings. #[allow(unused)] fn read_input(stream: &Stdin) -> Vec { - stream.lock() - .lines() - .filter_map(Result::ok) - .collect() + stream.lock().lines().filter_map(Result::ok).collect() } #[allow(unused)] diff --git a/src/problems/hackerrank/mathematics/scalar_products/approach2.rs b/src/problems/hackerrank/mathematics/scalar_products/approach2.rs index f3d585b..3e37ac4 100644 --- a/src/problems/hackerrank/mathematics/scalar_products/approach2.rs +++ b/src/problems/hackerrank/mathematics/scalar_products/approach2.rs @@ -302,10 +302,7 @@ where /// as a vector of strings. #[allow(unused)] fn read_input(stream: &Stdin) -> Vec { - stream.lock() - .lines() - .filter_map(Result::ok) - .collect() + stream.lock().lines().filter_map(Result::ok).collect() } #[allow(unused)] diff --git a/src/problems/hackerrank/mathematics/scalar_products/mod.rs b/src/problems/hackerrank/mathematics/scalar_products/mod.rs index 4020928..e5293f5 100644 --- a/src/problems/hackerrank/mathematics/scalar_products/mod.rs +++ b/src/problems/hackerrank/mathematics/scalar_products/mod.rs @@ -1,5 +1,6 @@ /// Solutions to the Hackerrank Mathematics challenge: /// . + pub mod approach1; pub mod approach2; From c2a80c9b62363c001a66c7f4b17a3573d801d7f4 Mon Sep 17 00:00:00 2001 From: raj-open Date: Sun, 4 May 2025 18:25:17 +0200 Subject: [PATCH 07/54] story-problems > staging: added problem description --- .../mathematics/scalar_products/README.md | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 src/problems/hackerrank/mathematics/scalar_products/README.md diff --git a/src/problems/hackerrank/mathematics/scalar_products/README.md b/src/problems/hackerrank/mathematics/scalar_products/README.md new file mode 100644 index 0000000..15f83fa --- /dev/null +++ b/src/problems/hackerrank/mathematics/scalar_products/README.md @@ -0,0 +1,126 @@ +# Problem: Scalar Products # + +Source: . + +Credit: User [@zemen](https://www.hackerrank.com/profile/zemen). + +## Description ## + +Let $C, m \in \mathbb{N}$. +Define + +$$ + (a_{i})_{i \in \mathbb{N}_{0}} + \subseteq + \mathbb{Z} / m\mathbb{Z} +$$ + +via + +- $a_{0} = 0$ +- $a_{1} = C$ +- $a_{i+2} = a_{i+1} + a_{i}$ + +and + +$$ +v_{k} + = \begin{pmatrix} + a_{2k}\\ + a_{2k + 1} + \end{pmatrix} +$$ + +for $k \in \mathbb{N}_{0}$. + +Given inputs $(C,M,n)$ compute $|S|$, +where + +$$ + S = \{ + \langle v_{i},\: v_{j} \rangle + \mid + 1 \leq i, j \leq n, + i \mathbb{N}eq j + \}, +$$ + +whereby the scalar products are again +computed over the ring $\mathbb{Z}/m\mathbb{Z}$. + +### Requirements ### + +Inputs occur in `stdin` of the form + +```bash +{C} {m} {n} +``` + +the output consists of a single number $|S|$, +streamed to `stdout`. + +### Example ### + +Sample input + +```bash +4 5 3 +``` + +one computes + +```text +a[0] = 0 +a[1] = 4 +a[2] = 4 +a[3] = 8 = 3 +a[4] = 7 = 2 +a[5] = 5 = 0 +a[6] = 2 +a[7] = 2 +a[8] = 4 +a[9] = 6 = 1 +a[10] = 5 = 0 +... +``` + +and thus + +$$ + v_{0} = \begin{pmatrix}0\\ 4\end{pmatrix}, + \: + v_{1} = \begin{pmatrix}4\\ 3\end{pmatrix}, + \: + v_{2} = \begin{pmatrix}2\\ 0\end{pmatrix}, + \: + v_{3} = \begin{pmatrix}2\\ 2\end{pmatrix}, + \: + \cdots +$$ + +The scalar products are + +$$ + S = \{ + \langle v_{1},\: v_{2} \rangle, + \langle v_{1},\: v_{3} \rangle, + \langle v_{2},\: v_{3} \rangle + \} + = \{ + (4 \cdot 2 + 3\cdot 0), + (4 \cdot 2 + 3\cdot 2), + (2 \cdot 2 + 0\cdot 2) + \} + = \{ + 3, + 14 \% 5, + 4 + \} + = \{3, 4\}. +$$ + +Hence the correct output is + +```bash +2 +``` From 64a4064a3b4e7cbe74d1418c7910ebe1568d4046 Mon Sep 17 00:00:00 2001 From: raj-open Date: Sun, 4 May 2025 18:46:39 +0200 Subject: [PATCH 08/54] story-problems > staging: added ignored test case and used `i64` instead --- .../mathematics/scalar_products/approach1.rs | 16 ++++++++-------- .../scalar_products/tests_approach1.rs | 8 ++++++++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/problems/hackerrank/mathematics/scalar_products/approach1.rs b/src/problems/hackerrank/mathematics/scalar_products/approach1.rs index 00792d6..47c4f8f 100644 --- a/src/problems/hackerrank/mathematics/scalar_products/approach1.rs +++ b/src/problems/hackerrank/mathematics/scalar_products/approach1.rs @@ -43,24 +43,24 @@ fn main() { } pub fn run(c: i32, m: i32, n: usize) -> usize { - let vecs = SeqPair::new(m, 0, c) + let vecs = SeqPair::new(m as i64, 0, c as i64) .into_iter() .map(|s| (s.current, s.next)) .skip(2) .step_by(2) .take(n); - let mut values: HashSet = HashSet::new(); + let mut values: HashSet = HashSet::new(); for (k, u) in vecs.enumerate() { - let vecs2 = SeqPair::new(m, u.0, u.1) + let vecs2 = SeqPair::new(m as i64, u.0, u.1) .into_iter() .map(|s| (s.current, s.next)) .skip(2) .step_by(2) .take(n - (k + 1)); for v in vecs2 { - let ip = (u.0 * v.0 + u.1 * v.1).rem_euclid(m); + let ip = (u.0 * v.0 + u.1 * v.1).rem_euclid(m as i64); values.insert(ip); } } @@ -74,9 +74,9 @@ pub fn run(c: i32, m: i32, n: usize) -> usize { /// ---------------------------------------------------------------- #[derive(Clone, Debug)] struct SeqPair { - modulus: i32, - current: i32, - next: i32, + modulus: i64, + current: i64, + next: i64, } trait EntityIterable { @@ -93,7 +93,7 @@ where } impl SeqPair { - fn new(modulus: i32, x: i32, y: i32) -> Self { + fn new(modulus: i64, x: i64, y: i64) -> Self { Self { modulus, current: x, next: y } } } diff --git a/src/problems/hackerrank/mathematics/scalar_products/tests_approach1.rs b/src/problems/hackerrank/mathematics/scalar_products/tests_approach1.rs index baa1888..a42a044 100644 --- a/src/problems/hackerrank/mathematics/scalar_products/tests_approach1.rs +++ b/src/problems/hackerrank/mathematics/scalar_products/tests_approach1.rs @@ -24,4 +24,12 @@ mod tests { let result = approach::run(1, 100, 1000); assert_eq!(result, 50); } + + /// NOTE: This approach is inefficient and therefore skipped. + #[test] + #[ignore] + fn test_case_heavy_1() { + let result = approach::run(991, 11495481, 112259); + assert_eq!(result, 224515); + } } From ca2d6052d92ef917d4f461a7c6d53c62b04ef0a5 Mon Sep 17 00:00:00 2001 From: raj-open Date: Sun, 4 May 2025 21:55:16 +0200 Subject: [PATCH 09/54] story-problems > staging: extended clean recipe --- justfile | 1 + 1 file changed, 1 insertion(+) diff --git a/justfile b/justfile index 26d2a54..3b053c8 100644 --- a/justfile +++ b/justfile @@ -215,6 +215,7 @@ clean-basic log_path="logs": @- just _clean-all-files "." ".DS_Store" 2> /dev/null @echo "All build artefacts will be force removed." @cargo clean + @just_clean-all-files "." "*.rs.bk" @- rm -rf ".venv" 2> /dev/null @- rm -rf "target" 2> /dev/null From 8498cb2e46900fcefe4f4681e0065af0a88a6fb0 Mon Sep 17 00:00:00 2001 From: raj-open Date: Sun, 4 May 2025 21:55:25 +0200 Subject: [PATCH 10/54] story-problems > staging: extended formatting config --- rustfmt.toml | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 420ed2d..f173e17 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,18 +1,24 @@ +reorder_imports = false combine_control_expr = false -comment_width = 80 condense_wildcard_suffixes = false disable_all_formatting = false + fn_args_layout = "Block" # "Visual", "Block" -fn_call_width = 60 fn_single_line = false + hard_tabs = false -max_width = 100 newline_style = "Unix" -normalize_comments = false -struct_lit_width = 40 trailing_comma = "Vertical" -reorder_imports = false -force_explicit_abi = true + format_strings = false -wrap_comments = false +force_explicit_abi = true + +struct_lit_width = 40 +fn_call_width = 60 +max_width = 100 +comment_width = 200 +normalize_comments = false +doc_comment_width = 200 normalize_doc_attributes = false +wrap_comments = false +wrap_doc_comments = false From c06f715ac50b57d347f245f57ae39dc167fff74c Mon Sep 17 00:00:00 2001 From: raj-open Date: Sun, 4 May 2025 21:55:44 +0200 Subject: [PATCH 11/54] story-problems > staging: added new problem --- src/problems/hackerrank/mod.rs | 2 + src/problems/hackerrank/project_euler/mod.rs | 5 + .../problem10_prime_summation/approach1.rs | 99 +++++++++++++++++++ .../problem10_prime_summation/mod.rs | 7 ++ .../tests_approach1.rs | 27 +++++ 5 files changed, 140 insertions(+) create mode 100644 src/problems/hackerrank/project_euler/mod.rs create mode 100644 src/problems/hackerrank/project_euler/problem10_prime_summation/approach1.rs create mode 100644 src/problems/hackerrank/project_euler/problem10_prime_summation/mod.rs create mode 100644 src/problems/hackerrank/project_euler/problem10_prime_summation/tests_approach1.rs diff --git a/src/problems/hackerrank/mod.rs b/src/problems/hackerrank/mod.rs index d859f52..63af568 100644 --- a/src/problems/hackerrank/mod.rs +++ b/src/problems/hackerrank/mod.rs @@ -1,3 +1,5 @@ /// Contains solutions to Hackerrank challenges. /// Source: . + +pub mod project_euler; pub mod mathematics; diff --git a/src/problems/hackerrank/project_euler/mod.rs b/src/problems/hackerrank/project_euler/mod.rs new file mode 100644 index 0000000..f6972f6 --- /dev/null +++ b/src/problems/hackerrank/project_euler/mod.rs @@ -0,0 +1,5 @@ +/// Contains solutions to challenges in the Mathematics +/// section of Hackerrank. +/// Source: . + +pub mod problem10_prime_summation; diff --git a/src/problems/hackerrank/project_euler/problem10_prime_summation/approach1.rs b/src/problems/hackerrank/project_euler/problem10_prime_summation/approach1.rs new file mode 100644 index 0000000..9d18f0c --- /dev/null +++ b/src/problems/hackerrank/project_euler/problem10_prime_summation/approach1.rs @@ -0,0 +1,99 @@ +/// # First approach # +/// +/// Computes Primes using the Sieve of Eratosthenes. +/// Then efficiently computes the cumulutative sum of primes +/// below certain integers. + +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +use std::io; +use std::io::BufRead; +use std::clone::Clone; +use std::fmt::Debug; +use std::cmp::Ord; +use std::collections::HashMap; +use std::io::Stdin; +use std::str::FromStr; + +/// ---------------------------------------------------------------- +/// MAIN +/// ---------------------------------------------------------------- + +/// entry point when used as a script +#[allow(unused)] +fn main() { + let lines = read_input(&io::stdin()); + let t = lines.iter().nth(0).unwrap().parse::(); + let numbers: Vec = lines.iter().skip(1).map(|x| x.parse().unwrap()).collect(); + + let sums = run(&numbers); + + for n in numbers.iter() { + if let Some(s) = sums.get(n) { + println!("{:?}", s); + } + } +} + +pub fn run(numbers: &Vec) -> HashMap { + let n_max: i64 = numbers.iter().fold(0, |prev, &n| prev.max(n)); + let primes = get_primes(n_max as i64); + let sums = compute_aggregates(&numbers, &primes); + return sums; +} + +/// ---------------------------------------------------------------- +/// HELPER METHODS +/// ---------------------------------------------------------------- + +/// computes the list of primes up to a value +fn get_primes(n_max: i64) -> Vec { + let mut map = HashMap::::new(); + let mut result = Vec::::new(); + for p in 2..(n_max + 1) { + if map.get(&p) != Some(&false) { + result.push(p); + ((2 * p)..(n_max + 1)).step_by(p as usize).for_each(|k| { + map.entry(k).or_insert(false); + }); + } + } + return result; +} + +fn compute_aggregates(numbers: &Vec, primes: &Vec) -> HashMap { + let mut numbers_sorted = numbers.clone(); + numbers_sorted.sort(); + numbers_sorted.dedup(); + let mut values = primes.clone(); + let mut sums = HashMap::::new(); + let mut sum: i64 = 0; + for n in numbers_sorted { + sum += values.iter().filter(|&&p| (p <= n)).sum::(); + values = values.iter().filter(|&&p| (p > n)).cloned().collect(); + sums.insert(n, sum); + } + return sums; +} + +/// ---------------------------------------------------------------- +/// AUXILIARY +/// ---------------------------------------------------------------- + +/// Obtains input lines from stdin +/// as a vector of strings. +#[allow(unused)] +fn read_input(stream: &Stdin) -> Vec { + stream.lock().lines().filter_map(Result::ok).collect() +} + +#[allow(unused)] +fn parse(text: &String) -> T +where + T: FromStr, + ::Err: Debug, +{ + return text.parse::().unwrap(); +} diff --git a/src/problems/hackerrank/project_euler/problem10_prime_summation/mod.rs b/src/problems/hackerrank/project_euler/problem10_prime_summation/mod.rs new file mode 100644 index 0000000..4793d78 --- /dev/null +++ b/src/problems/hackerrank/project_euler/problem10_prime_summation/mod.rs @@ -0,0 +1,7 @@ +/// Solutions to the Hackerrank Mathematics challenge: +/// . + +pub mod approach1; + +#[cfg(test)] +pub mod tests_approach1; diff --git a/src/problems/hackerrank/project_euler/problem10_prime_summation/tests_approach1.rs b/src/problems/hackerrank/project_euler/problem10_prime_summation/tests_approach1.rs new file mode 100644 index 0000000..3f8c44d --- /dev/null +++ b/src/problems/hackerrank/project_euler/problem10_prime_summation/tests_approach1.rs @@ -0,0 +1,27 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +use std::collections::HashMap; + +use super::approach1 as approach; + +/// ---------------------------------------------------------------- +/// TESTS +/// ---------------------------------------------------------------- + +/// bundle of tests +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_case1() { + let args = vec![5, 10]; + let result = approach::run(&args); + let mut expected = HashMap::::new(); + expected.insert(5, 10); + expected.insert(10, 17); + assert_eq!(result, expected); + } +} From 1efb97086ae9a88a7d3de02cc91632d0806de37b Mon Sep 17 00:00:00 2001 From: raj-open Date: Sun, 11 May 2025 11:38:45 +0200 Subject: [PATCH 12/54] =?UTF-8?q?story-problems=20>=20staging:=20replaced?= =?UTF-8?q?=20O(n=C2=B7log(n))=20by=20O(n)=20computation=20of=20powers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mathematics/scalar_products/approach2.rs | 421 ++++++++++++++---- 1 file changed, 322 insertions(+), 99 deletions(-) diff --git a/src/problems/hackerrank/mathematics/scalar_products/approach2.rs b/src/problems/hackerrank/mathematics/scalar_products/approach2.rs index 3e37ac4..7cd7966 100644 --- a/src/problems/hackerrank/mathematics/scalar_products/approach2.rs +++ b/src/problems/hackerrank/mathematics/scalar_products/approach2.rs @@ -51,12 +51,13 @@ /// IMPORTS /// ---------------------------------------------------------------- -use std::collections::HashSet; use std::fmt::Debug; use std::fmt::Display; use std::io; use std::io::Stdin; use std::io::BufRead; +use std::collections::HashMap; +use std::collections::HashSet; use std::ops::Add; use std::ops::Mul; use std::ops::Rem; @@ -76,8 +77,8 @@ fn main() { let args: Vec = line.split(" ").map(|x| x.to_string()).collect(); let mut args: Iter<'_, String> = args.iter(); - let c = parse::(args.next().unwrap()); - let m = parse::(args.next().unwrap()); + let c = parse::(args.next().unwrap()); + let m = parse::(args.next().unwrap()); let n = parse::(args.next().unwrap()); let num_unique = run(c, m, n); @@ -85,44 +86,29 @@ fn main() { println!("{:?}", num_unique); } -pub fn run(c: i32, m: i32, n: usize) -> usize { +pub fn run(c: i64, m: i64, n: usize) -> usize { // sequence generated by symmetric matrix - let zero: Modulo = Modulo::new(0, m as i64); - let one: Modulo = Modulo::new(1, m as i64); - let matrix_f: SymmMatrix2x2> = SymmMatrix2x2 { a: zero, b: one, d: one }; - - /* ---- * - * The n-the entry of the sequence - * is given by - * ---- */ - - // e is the smalles integer with 2^e >= (2*n) - let e = (2.0 * (n as f32)).log2().ceil() as i64; - - // compute G[k] = G^(2^k): - let mut matrix_g = matrix_f.pow2(); - let mut matrices_g = vec![matrix_g.clone()]; - for _ in 1..e { - matrix_g = matrix_g.pow2(); - matrices_g.push(matrix_g.clone()); - } + let zero: Modulo = Modulo::new(0, m); + let one: Modulo = Modulo::new(1, m); + let v0 = Vector2([zero, Modulo::new(c, m)]); + let matrix_f = SymmMatrix2x2 { a: zero, b: one, d: one }; + let matrix_g = matrix_f.pow2(); + + // compute system[k] = (_, G^k * v0) + let system = DynamicalSystem { + evolution: matrix_g, + state: v0, + }; + let n_max = 2 * (n as i64); + let system_powers = compute_powers(&system, n_max); // compute all powers of G: - let v0 = Vector2([zero, Modulo::new(c as i64, m as i64)]); let mut values: HashSet = HashSet::new(); - for k in 3..(2 * n) { - // compute v := G^k * v_0 using divide and conquer - let k_base2 = format!("{:b}", k); - let places = k_base2 - .chars() - .rev() - .enumerate() - .filter(|(_, d)| *d == '1') - .map(|(k, _)| k); - let mut v = v0.clone(); - for j in places { - v = matrices_g.get(j).unwrap().mul_vector(&v); - } + for k in 3.. n_max { + // k = i + j + // compute v := G^k * v_0 + let system_pow_k = system_powers.get(&(k as i64)).unwrap(); + let v = system_pow_k.state; // now compute < G^i v_0, G^j v_0 > = < G^k v_0, v_0 > = < v, v_0 > let value = Vector2::inner_product(&v, &v0).value; values.insert(value); @@ -132,39 +118,169 @@ pub fn run(c: i32, m: i32, n: usize) -> usize { } /// ---------------------------------------------------------------- -/// SECONDARY +/// ALGORITHMS /// ---------------------------------------------------------------- -#[derive(Clone, Copy, PartialEq, Eq)] -struct Modulo + +/// computes x^(2^k) for 1 <= k <= n +pub fn power_of_2_powers(x: &T, n: i64) -> HashMap where - T: Display + Clone + Copy + PartialEq + Eq, + T: Clone + Mul + BinaryPowers, { - value: T, - modulus: T, + let mut results: HashMap = HashMap::new(); + let mut x_pow_2_pow = x.clone(); + results.insert(0, x_pow_2_pow.clone()); + (1.. n).for_each(|k| { + x_pow_2_pow = x_pow_2_pow.pow2(); + results.insert(k as i64, x_pow_2_pow.clone()); + }); + return results; } -#[derive(Clone, Debug)] -struct Vector2([T; 2]); +/// efficiently computes x^k for 0 <= k <= n +/// Uses binary tree structure to avoid redundant computations. +/// Time complexity O(n) +pub fn compute_powers(x: &T, n: i64) -> HashMap +where + T: Clone + Mul + BinaryPowers, +{ + let mut powers: HashMap = HashMap::new(); + powers.insert(0, x.pow0()); -#[derive(Clone, Debug)] -struct SymmMatrix2x2 { - a: T, - b: T, - d: T, + // in trivial case stop + if n <= 0 { + return powers; + } + + /* -------------------------------- * + * Find l with 2^(l-1) <= n < 2^l (i.e. n has l digits) + * NOTE: + * 2^(l-1) <= n < 2^l + * <==> l - 1 <= log2(n) < l + * <==> l - 1 = floor(log2(n)) + * <==> l = floor(log2(n)) + 1 + * -------------------------------- */ + let l = (n as f64).log2().floor() as i64 + 1; + + // compute x^(2^k) for k from 0 to l-1 + let x_pow_2_pow = power_of_2_powers(x, l); + + // now compute along levels of a binary tree + let powers = (0.. l).fold( + powers, + |mut prev, k| { + let num_leaves = prev.len() as i64; + let x_pow_2_pow_k = x_pow_2_pow.get(&k).unwrap().clone(); + for (&j, value) in prev.clone().iter() { + let value_ = x_pow_2_pow_k.clone() * value.clone(); + prev.insert(j + num_leaves, value_); + }; + return prev; + } + ); + + return powers; +} + +/// ---------------------------------------------------------------- +/// STRUCTURES +/// ---------------------------------------------------------------- + +/// Helper structure for modulo computations +#[derive(Copy, Clone, PartialEq, Eq)] +pub struct Modulo +where + T: Clone + PartialEq + Eq, +{ + pub value: T, + pub modulus: T, +} + +#[derive(Copy, Clone, Debug)] +pub struct Vector2(pub [T; 2]); + +#[derive(Copy, Clone, Debug)] +pub struct SymmMatrix2x2 { + pub a: T, + pub b: T, + pub d: T, +} + +/// A dynamical system encodes +/// evolution = A +/// state = rho +/// with the assumption that rho = A*rho_0 +/// for some initial state rho_0 +#[derive(Copy, Clone, Debug)] +pub struct DynamicalSystem { + pub evolution: SymmMatrix2x2, + pub state: Vector2, +} + +/// ---------------------------------------------------------------- +/// TRAITS +/// ---------------------------------------------------------------- + +pub trait NumberLike { + fn positive(&self) -> bool; +} + +pub trait BinaryPowers { + fn zerolike(&self) -> Self; + fn pow0(&self) -> Self; + fn pow2(&self) -> Self; +} + +/// ---------------------------------------------------------------- +/// IMPLEMENTATIONS +/// ---------------------------------------------------------------- + +impl NumberLike for i64 { + fn positive(&self) -> bool { + *self > 0 + } +} + +impl BinaryPowers for i64 { + fn zerolike(&self) -> Self { + 0 + } + fn pow0(&self) -> Self { + 1 + } + fn pow2(&self) -> Self { + self * self + } } impl Modulo where - T: Display + Clone + Copy + PartialEq + Eq, + T: Display + Clone + PartialEq + Eq, { - fn new(value: T, modulus: T) -> Self { + pub fn new(value: T, modulus: T) -> Self { Self { value, modulus } } } +impl Modulo +where + T: Copy + Clone + PartialEq + Eq + NumberLike + Rem, +{ + // type Output = T; + // fn rem(self, rhs: Self) -> Self::Output { + // } + + pub fn remainder(mut self) -> Self { + let m = self.modulus; + if m.positive() { + self.value = self.value.rem(m) + } + return self; + } +} + impl Display for Modulo where - T: Display + Clone + Copy + PartialEq + Eq, + T: Display + Clone + PartialEq + Eq, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{} (mod {})", self.value, self.modulus) @@ -173,7 +289,7 @@ where impl Debug for Modulo where - T: Display + Clone + Copy + PartialEq + Eq, + T: Display + Clone + PartialEq + Eq, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self) @@ -183,11 +299,11 @@ where impl Add for Modulo where T: Display - + Clone + Copy + + Clone + PartialEq + Eq - + Add + + NumberLike + Add + Rem, { @@ -195,64 +311,60 @@ where fn add(self, other: Self) -> Self::Output { let modulus = self.modulus; - Self { - value: (self.value + other.value) % modulus, - modulus, - } + let value = self.value + other.value; + return Self::new(value, modulus).remainder(); } } impl Mul for Modulo where T: Display - + Clone + Copy + + Clone + PartialEq + Eq + + NumberLike + Mul - + Add + Rem, { type Output = Self; fn mul(self, other: Self) -> Self::Output { let modulus = self.modulus; - Self { - value: (self.value * other.value) % modulus, - modulus, - } + let value = self.value * other.value; + return Self::new(value, modulus).remainder(); } } -impl Add for SymmMatrix2x2 +impl BinaryPowers for Modulo where - T: Copy + Add, + T: Copy + + Clone + + PartialEq + + Eq + + NumberLike + + Mul + + Rem + + BinaryPowers, { - type Output = Self; + fn zerolike(&self) -> Self { + let value = self.value.zerolike(); + let modulus = self.modulus; + Self { value, modulus } + } - fn add(self, other: Self) -> Self::Output { - Self { - a: self.a + other.a, - b: self.b + other.b, - d: self.d + other.d, - } + fn pow0(&self) -> Self { + let value = self.value.pow0(); + let modulus = self.modulus; + Self { value, modulus } } -} -// impl Mul for SymmMatrix2x2 -// where -// T: Copy + Mul + Add, -// { -// type Output = Self; - -// fn mul(self, other: Self) -> Self::Output { -// Self { -// a: self.a * other.a + self.b * other.b, -// b: self.a * other.b + self.b * other.d, -// d: self.b * other.b + self.d * other.d, -// } -// } -// } + fn pow2(&self) -> Self { + let modulus = self.modulus; + let value = self.value.pow2().rem(modulus); + Self { value, modulus } + } +} impl Vector2 where @@ -265,7 +377,7 @@ where impl Vector2 where - T: Copy + Mul + Add, + T: Copy + Clone + Mul + Add, { fn inner_product(u: &Self, v: &Self) -> T { u.get(0) * v.get(0) + u.get(1) * v.get(1) @@ -276,14 +388,6 @@ impl SymmMatrix2x2 where T: Copy + Mul + Add, { - fn pow2(self) -> Self { - Self { - a: self.a * self.a + self.b * self.b, - b: (self.a + self.d) * self.b, - d: self.b * self.b + self.d * self.d, - } - } - fn mul_vector(&self, u: &Vector2) -> Vector2 { Vector2( [ @@ -294,6 +398,125 @@ where } } +impl Add for SymmMatrix2x2 +where + T: Clone + Add, +{ + type Output = Self; + + fn add(self, other: Self) -> Self::Output { + Self { + a: self.a + other.a, + b: self.b + other.b, + d: self.d + other.d, + } + } +} + +impl Mul for SymmMatrix2x2 +where + T: Clone + Mul, +{ + type Output = Self; + + fn mul(self, other: Self) -> Self::Output { + Self { + a: self.a * other.a, + b: self.b * other.b, + d: self.d * other.d, + } + } +} + +impl BinaryPowers for SymmMatrix2x2 +where + T: Copy + Mul + Add + BinaryPowers, +{ + fn zerolike(&self) -> Self { + Self { + a: self.a.pow0(), + b: self.b.zerolike(), + d: self.d.pow0(), + } + } + + fn pow0(&self) -> Self { + Self { + a: self.a.pow0(), + b: self.b.zerolike(), + d: self.d.pow0(), + } + } + + fn pow2(&self) -> Self { + let aa = self.a.pow2(); + let bb = self.b.pow2(); + let dd = self.d.pow2(); + let a = aa + bb; + let b = (self.a + self.d) * self.b; + let d = bb + dd; + Self { a, b, d } + } +} + +impl Mul for DynamicalSystem +where + T: Copy + Add + Mul, +{ + type Output = Self; + + /// Assumes dynamical system 1 and 2 share the same initial state + /// i.e. D1 = (U1, rho1), D2 = (U2, rho2) + /// with rho1 = U1*rho0 and rho2 = U2*rho0 + /// where rho0 = a common initial state + /// The "product" is determined by + /// application of evolution 1 to state2, + /// i.e. + /// + /// - replace evolution by U1 + /// - replace initial state by rho2 + /// + /// i.e. + /// + /// D1*D2 := (U1, U1 * rho2) + /// = (U1, U1 * U2 * rho0) + fn mul(self, other: Self) -> Self::Output { + let evolution = self.evolution; + let state = self.evolution.mul_vector(&other.state); + return Self { evolution, state }; + } +} + +impl BinaryPowers for DynamicalSystem +where + T: Copy + + Clone + + Add + + Mul + + BinaryPowers, +{ + fn zerolike(&self) -> Self { + Self { + evolution: self.evolution.zerolike(), + state: self.state, + } + } + + fn pow0(&self) -> Self { + Self { + evolution: self.evolution.pow0(), + state: self.state, + } + } + + fn pow2(&self) -> Self { + let mut evolution = self.evolution; + let state = self.evolution.mul_vector(&self.state); + evolution = evolution.pow2(); + Self { evolution, state } + } +} + /// ---------------------------------------------------------------- /// AUXILIARY /// ---------------------------------------------------------------- From 75a1cfe2d0f4a69e438bd65ba28af5ebcacc7dc0 Mon Sep 17 00:00:00 2001 From: raj-open Date: Sun, 11 May 2025 11:39:20 +0200 Subject: [PATCH 13/54] story-problems > staging: prevent suppression of println, etc. --- justfile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/justfile b/justfile index 3b053c8..ff17d7e 100644 --- a/justfile +++ b/justfile @@ -170,26 +170,26 @@ tests-logs log_path="logs": test-unit path *args: @cargo zigbuild --tests @echo "run unit tests in $( just _rust_path_to_test_module "{{path}}")" - @cargo test --lib "$( just _rust_path_to_test_module "{{path}}")" {{args}} + @cargo test --lib "$( just _rust_path_to_test_module "{{path}}")" {{args}} -- --nocapture @# echo "run unit tests in $( just _rust_path_to_module "{{path}}")" - @# cargo test --lib "$( just _rust_path_to_module "{{path}}")" {{args}} + @# cargo test --lib "$( just _rust_path_to_module "{{path}}")" {{args}} -- --nocapture test-unit-optimised path *args: @cargo zigbuild --tests --release @echo "run unit tests in $( just _rust_path_to_test_module "{{path}}")" - @cargo test --lib "$( just _rust_path_to_test_module "{{path}}")" {{args}} + @cargo test --lib "$( just _rust_path_to_test_module "{{path}}")" {{args}} -- --nocapture @# echo "run unit tests in $( just _rust_path_to_module "{{path}}")" - @# cargo test --lib "$( just _rust_path_to_module "{{path}}")" {{args}} + @# cargo test --lib "$( just _rust_path_to_module "{{path}}")" {{args}} -- --nocapture tests-unit *args: @just _reset-logs @cargo zigbuild --tests - @cargo test --lib {{args}} + @cargo test --lib {{args}} -- --nocapture tests-unit-optimised *args: @just _reset-logs @cargo zigbuild --tests --release - @cargo test --lib {{args}} + @cargo test --lib {{args}} -- --nocapture # -------------------------------- # TARGETS: prettify @@ -215,7 +215,7 @@ clean-basic log_path="logs": @- just _clean-all-files "." ".DS_Store" 2> /dev/null @echo "All build artefacts will be force removed." @cargo clean - @just_clean-all-files "." "*.rs.bk" + @just _clean-all-files "." "*.rs.bk" @- rm -rf ".venv" 2> /dev/null @- rm -rf "target" 2> /dev/null From 159ce8615873856842053f3931482446998546d1 Mon Sep 17 00:00:00 2001 From: raj-open Date: Sun, 11 May 2025 11:40:48 +0200 Subject: [PATCH 14/54] story-problems > staging: updated locks --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 94bdbe8..397bb79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -197,9 +197,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.37" +version = "4.5.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" +checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000" dependencies = [ "clap_builder", "clap_derive", @@ -207,9 +207,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.37" +version = "4.5.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" +checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120" dependencies = [ "anstream", "anstyle", @@ -266,9 +266,9 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "crc" -version = "3.2.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" dependencies = [ "crc-catalog", ] @@ -1448,9 +1448,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9fb597c990f03753e08d3c29efbfcf2019a003b4bf4ba19225c158e1549f0f3" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" dependencies = [ "memchr", ] From 867cf16e7231a07a5a36308974bc7e8e9e37da0e Mon Sep 17 00:00:00 2001 From: raj-open Date: Sun, 11 May 2025 11:46:07 +0200 Subject: [PATCH 15/54] story-problems > staging: updated doc string --- .../hackerrank/mathematics/scalar_products/approach2.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/problems/hackerrank/mathematics/scalar_products/approach2.rs b/src/problems/hackerrank/mathematics/scalar_products/approach2.rs index 7cd7966..776843e 100644 --- a/src/problems/hackerrank/mathematics/scalar_products/approach2.rs +++ b/src/problems/hackerrank/mathematics/scalar_products/approach2.rs @@ -38,13 +38,14 @@ /// for `k in [3:2n]` via /// products of powers of the form `G^(2^l)`, /// relying on the binary representation of each `k`. -/// We thereby only need to compute `floor(log2(2n)) = O(log(n))` powers, -/// and the products of such powers are themselves `O(log(n))` -/// and we do this for `O(n)` entries. +/// +/// By reorganising the multiplication tasks into a binary tree, +/// the total time complexity for computing powers is O(n). +/// (One can more precisely compute this as lying between n/2 and n) /// So in total, the time complexity is /// /// ``` -/// O(n log(n)^2). +/// O(n) + O(n) = O(n) /// ``` /// ---------------------------------------------------------------- From b43289d39b49e018f31b004cd163e5e2c7c833cb Mon Sep 17 00:00:00 2001 From: raj-open Date: Tue, 2 Sep 2025 16:57:19 +0100 Subject: [PATCH 16/54] story-problems > staging: minor --- src/problems/hackerrank/mod.rs | 2 +- .../hackerrank/project_euler/problem10_prime_summation/mod.rs | 3 +-- tests/lib.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/problems/hackerrank/mod.rs b/src/problems/hackerrank/mod.rs index 63af568..986e5ab 100644 --- a/src/problems/hackerrank/mod.rs +++ b/src/problems/hackerrank/mod.rs @@ -1,5 +1,5 @@ +pub mod mathematics; /// Contains solutions to Hackerrank challenges. /// Source: . pub mod project_euler; -pub mod mathematics; diff --git a/src/problems/hackerrank/project_euler/problem10_prime_summation/mod.rs b/src/problems/hackerrank/project_euler/problem10_prime_summation/mod.rs index 4793d78..d27bc37 100644 --- a/src/problems/hackerrank/project_euler/problem10_prime_summation/mod.rs +++ b/src/problems/hackerrank/project_euler/problem10_prime_summation/mod.rs @@ -1,6 +1,5 @@ -/// Solutions to the Hackerrank Mathematics challenge: +/// Solutions to the Hackerrank Project Euler challenge: /// . - pub mod approach1; #[cfg(test)] diff --git a/tests/lib.rs b/tests/lib.rs index ea13f49..d65fd56 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,4 +1,4 @@ -extern crate code_challenges; +extern crate general; extern crate rstest; // pub mod path_to_testmodule; From f6ab6d40254339cd03ccb411b4a23b4b368b0d22 Mon Sep 17 00:00:00 2001 From: raj-open Date: Tue, 2 Sep 2025 16:59:01 +0100 Subject: [PATCH 17/54] story-problems > staging: updated project settings --- Cargo.lock | 43 +++++++++++++++++++++---------------------- Cargo.toml | 10 +++++----- justfile | 4 ++-- rustfmt.toml | 3 ++- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 397bb79..86d095a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -151,9 +151,9 @@ dependencies = [ [[package]] name = "cargo-zigbuild" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6e9e856390d5b0a859acaeda16528f8a61c964bdb894c3216c254908f1c2ea" +checksum = "a9584d77470f7ffea2fb67fbcc9e8dbe9fa79a80dafd579a83507c0a08d1f658" dependencies = [ "anyhow", "cargo-config2", @@ -245,19 +245,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "code_challenges" -version = "0.1.0" -dependencies = [ - "cargo-zigbuild", - "dedent", - "dict_derive", - "rstest", - "rustfmt", - "serde", - "serde_json", -] - [[package]] name = "colorchoice" version = "1.0.3" @@ -446,6 +433,19 @@ dependencies = [ "slab", ] +[[package]] +name = "general" +version = "0.1.0" +dependencies = [ + "cargo-zigbuild", + "dedent", + "dict_derive", + "rstest", + "rustfmt", + "serde", + "serde_json", +] + [[package]] name = "getopts" version = "0.2.21" @@ -833,21 +833,20 @@ checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "rstest" -version = "0.25.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fc39292f8613e913f7df8fa892b8944ceb47c247b78e1b1ae2f09e019be789d" +checksum = "f5a3193c063baaa2a95a33f03035c8a72b83d97a54916055ba22d35ed3839d49" dependencies = [ "futures-timer", "futures-util", "rstest_macros", - "rustc_version 0.4.1", ] [[package]] name = "rstest_macros" -version = "0.25.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f168d99749d307be9de54d23fd226628d99768225ef08f6ffb52e0182a27746" +checksum = "9c845311f0ff7951c5506121a9ad75aec44d083c31583b2ea5a30bcb0b0abba0" dependencies = [ "cfg-if", "glob", @@ -995,9 +994,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ "itoa", "memchr", diff --git a/Cargo.toml b/Cargo.toml index 4894d3b..e336cd3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ # cargo-features = ["profile-rustflags"] [package] -name = "code_challenges" +name = "general" version = "0.1.0" edition = "2024" description = "Code for challenges from various platforms" @@ -12,7 +12,7 @@ authors = [ # cf. https://doc.rust-lang.org/cargo/reference/manifest.html # [lib] -# name = "code_challenges" +# name = "general" # crate-type = ["lib"] [workspace] @@ -50,13 +50,13 @@ strip = false [dependencies] serde = {version = "^1.0.219", features = ["derive"]} -serde_json = {version = "^1.0.140"} +serde_json = {version = "^1.0.143"} dict_derive = {version = "^0.6.0" } dedent = {version="^0.1.1"} [dev-dependencies] -cargo-zigbuild = {version = "^0.20.0"} -rstest = {version = "^0.25.0"} +cargo-zigbuild = {version = "^0.20.1"} +rstest = {version = "^0.26.1"} rustfmt = {version = "^0.10.0", features = []} # just = {version = "^1.40.0"} diff --git a/justfile b/justfile index ff17d7e..8f73b6f 100644 --- a/justfile +++ b/justfile @@ -196,11 +196,11 @@ tests-unit-optimised *args: # -------------------------------- prettify: - @cargo fmt --verbose -- --force + @cargo fmt --verbose prettify-dry: @echo "Not yet implemented" - @# cargo fmt --verbose --check -- --force + @# cargo fmt --verbose --check # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # TARGETS: clean diff --git a/rustfmt.toml b/rustfmt.toml index f173e17..19061f4 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -2,8 +2,9 @@ reorder_imports = false combine_control_expr = false condense_wildcard_suffixes = false disable_all_formatting = false +# use_small_heuristics = "Off" -fn_args_layout = "Block" # "Visual", "Block" +fn_args_layout = "Tall" fn_single_line = false hard_tabs = false From 8e0c5fb97e1564a6c705db82c019929829f68fae Mon Sep 17 00:00:00 2001 From: raj-open Date: Tue, 2 Sep 2025 17:03:48 +0100 Subject: [PATCH 18/54] story-game-gs > staging: prepared new binary --- Cargo.toml | 4 ++++ src/bin/games/genius_square/main.rs | 13 +++++++++++++ src/bin/games/genius_square/mod.rs | 0 3 files changed, 17 insertions(+) create mode 100644 src/bin/games/genius_square/main.rs create mode 100644 src/bin/games/genius_square/mod.rs diff --git a/Cargo.toml b/Cargo.toml index e336cd3..36c1423 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,10 @@ members = [ ".", ] +[[bin]] +name = "games-genius-square" +path = "src/bin/games/genius_square/main.rs" + # [env] # NOTE: has no effect # PYO3_PYTHON = { value = "python3" } diff --git a/src/bin/games/genius_square/main.rs b/src/bin/games/genius_square/main.rs new file mode 100644 index 0000000..1065e27 --- /dev/null +++ b/src/bin/games/genius_square/main.rs @@ -0,0 +1,13 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +use general::_core; + +/// ---------------------------------------------------------------- +/// MAIN +/// ---------------------------------------------------------------- + +fn main() { + _core::strings::greet("world"); +} diff --git a/src/bin/games/genius_square/mod.rs b/src/bin/games/genius_square/mod.rs new file mode 100644 index 0000000..e69de29 From e4f62288ff14f62e908a1dc2cf137d0ccba97c93 Mon Sep 17 00:00:00 2001 From: raj-open Date: Wed, 3 Sep 2025 08:49:57 +0100 Subject: [PATCH 19/54] story-game-gs > staging: allow arguments in recipes --- justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/justfile b/justfile index 8f73b6f..69f999f 100644 --- a/justfile +++ b/justfile @@ -146,7 +146,7 @@ run-py module="main" *args="": run-rust module="${MAIN_MODULE}" *args="": @just build-compile "{{module}}" @# "./target/release/{{module}}" {{args}} - @cargo run --bin "{{module}}" + @cargo run --bin "{{module}}" {{args}} # -------------------------------- # TARGETS: development From 3cb91f37472df7d738fce05078de079683780bc6 Mon Sep 17 00:00:00 2001 From: raj-open Date: Wed, 3 Sep 2025 08:50:13 +0100 Subject: [PATCH 20/54] story-game-gs > staging: added RNG to dependencies --- Cargo.lock | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 2 ++ 2 files changed, 99 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 86d095a..0d3f907 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -360,7 +360,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b1a357c911c352439b460d7b375b5c85977b9db395b703dfee5a94dfb4d66a2" dependencies = [ "num-traits", - "rand", + "rand 0.6.5", "rustc_version 0.2.3", "semver 0.9.0", "serde", @@ -440,6 +440,8 @@ dependencies = [ "cargo-zigbuild", "dedent", "dict_derive", + "rand 0.9.2", + "rand_chacha 0.9.0", "rstest", "rustfmt", "serde", @@ -463,7 +465,19 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.3+wasi-0.2.4", ] [[package]] @@ -621,6 +635,15 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + [[package]] name = "proc-macro-crate" version = "3.3.0" @@ -648,6 +671,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" version = "0.6.5" @@ -656,7 +685,7 @@ checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" dependencies = [ "autocfg 0.1.8", "libc", - "rand_chacha", + "rand_chacha 0.1.1", "rand_core 0.4.2", "rand_hc", "rand_isaac", @@ -667,6 +696,16 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + [[package]] name = "rand_chacha" version = "0.1.1" @@ -677,6 +716,16 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + [[package]] name = "rand_core" version = "0.3.1" @@ -692,6 +741,15 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + [[package]] name = "rand_hc" version = "0.1.0" @@ -769,7 +827,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom", + "getrandom 0.2.16", "libredox", "thiserror 1.0.69", ] @@ -1260,6 +1318,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.14.3+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51ae83037bdd272a9e28ce236db8c07016dd0d50c27038b3f407533c030c95" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "which" version = "7.0.3" @@ -1459,3 +1526,29 @@ name = "winsafe" version = "0.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + +[[package]] +name = "wit-bindgen" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814" + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] diff --git a/Cargo.toml b/Cargo.toml index 36c1423..cf9c497 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,8 @@ serde = {version = "^1.0.219", features = ["derive"]} serde_json = {version = "^1.0.143"} dict_derive = {version = "^0.6.0" } dedent = {version="^0.1.1"} +rand = {version="^0.9.2"} +rand_chacha = {version = "^0.9.0"} [dev-dependencies] cargo-zigbuild = {version = "^0.20.1"} From 82aab6f15ba04e3715e6a7875b5836a379e67a7f Mon Sep 17 00:00:00 2001 From: raj-open Date: Wed, 3 Sep 2025 08:50:27 +0100 Subject: [PATCH 21/54] story-game-gs > staging: added RNG methods to core --- src/_core/mod.rs | 1 + src/_core/rand.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/_core/rand.rs diff --git a/src/_core/mod.rs b/src/_core/mod.rs index a385ff7..a715ece 100644 --- a/src/_core/mod.rs +++ b/src/_core/mod.rs @@ -1,2 +1,3 @@ pub mod errors; +pub mod rand; pub mod strings; diff --git a/src/_core/rand.rs b/src/_core/rand.rs new file mode 100644 index 0000000..5191f06 --- /dev/null +++ b/src/_core/rand.rs @@ -0,0 +1,31 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +use rand; +use rand::SeedableRng; +use rand_chacha::ChaCha8Rng; + +/// ---------------------------------------------------------------- +/// METHODS +/// ---------------------------------------------------------------- + +#[allow(unused)] +pub fn seed_rng(x: Option) -> ChaCha8Rng { + match x { + Some(seed_str) => { + // string -> bytes + let mut seed = [0u8; 32]; + let seed_bytes = seed_str.as_bytes(); + let len = seed_bytes.len().min(32); + seed[..len].copy_from_slice(&seed_bytes[..len]); + + // create RNG + let rng = ChaCha8Rng::from_seed(seed); + return rng; + }, + None => { + return ChaCha8Rng::from_os_rng(); + }, + } +} From 197833887cfbe27131088e253d8aabfdf7d0dc65 Mon Sep 17 00:00:00 2001 From: raj-open Date: Wed, 3 Sep 2025 09:03:26 +0100 Subject: [PATCH 22/54] story-game-gs > staging: added basic structure + read in and process cli args --- src/bin/games/genius_square/algorithms/mod.rs | 3 +++ .../games/genius_square/algorithms/solve.rs | 0 .../genius_square/features/create_game.rs | 27 +++++++++++++++++++ src/bin/games/genius_square/features/mod.rs | 3 +++ src/bin/games/genius_square/main.rs | 14 +++++++++- src/bin/games/genius_square/mod.rs | 5 ++++ .../genius_square/models/dice/constants.rs | 19 +++++++++++++ .../genius_square/models/dice/methods.rs | 21 +++++++++++++++ .../games/genius_square/models/dice/mod.rs | 4 +++ src/bin/games/genius_square/models/mod.rs | 4 +++ .../genius_square/models/pieces/constants.rs | 12 +++++++++ .../genius_square/models/pieces/methods.rs | 14 ++++++++++ .../games/genius_square/models/pieces/mod.rs | 4 +++ 13 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 src/bin/games/genius_square/algorithms/mod.rs create mode 100644 src/bin/games/genius_square/algorithms/solve.rs create mode 100644 src/bin/games/genius_square/features/create_game.rs create mode 100644 src/bin/games/genius_square/features/mod.rs create mode 100644 src/bin/games/genius_square/models/dice/constants.rs create mode 100644 src/bin/games/genius_square/models/dice/methods.rs create mode 100644 src/bin/games/genius_square/models/dice/mod.rs create mode 100644 src/bin/games/genius_square/models/mod.rs create mode 100644 src/bin/games/genius_square/models/pieces/constants.rs create mode 100644 src/bin/games/genius_square/models/pieces/methods.rs create mode 100644 src/bin/games/genius_square/models/pieces/mod.rs diff --git a/src/bin/games/genius_square/algorithms/mod.rs b/src/bin/games/genius_square/algorithms/mod.rs new file mode 100644 index 0000000..06fb1e9 --- /dev/null +++ b/src/bin/games/genius_square/algorithms/mod.rs @@ -0,0 +1,3 @@ +/// Algorithms used to solve a game state. + +pub mod solve; diff --git a/src/bin/games/genius_square/algorithms/solve.rs b/src/bin/games/genius_square/algorithms/solve.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/bin/games/genius_square/features/create_game.rs b/src/bin/games/genius_square/features/create_game.rs new file mode 100644 index 0000000..d290cdd --- /dev/null +++ b/src/bin/games/genius_square/features/create_game.rs @@ -0,0 +1,27 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +use rand_chacha::ChaCha8Rng; + +use crate::models::dice::methods::roll_dice; + +/// ---------------------------------------------------------------- +/// METHODS +/// ---------------------------------------------------------------- + +pub fn feature_create_game( + rng: &mut ChaCha8Rng, + option_roll: Option>, +) { + let roll: Vec; + match option_roll { + Some(x) => { + roll = x; + }, + None => { + roll = roll_dice(rng); + } + } + println!("\nRoll: {}.\n", roll.join(", ")); +} diff --git a/src/bin/games/genius_square/features/mod.rs b/src/bin/games/genius_square/features/mod.rs new file mode 100644 index 0000000..0b4fdb0 --- /dev/null +++ b/src/bin/games/genius_square/features/mod.rs @@ -0,0 +1,3 @@ +/// Highest logic of application. + +pub mod create_game; diff --git a/src/bin/games/genius_square/main.rs b/src/bin/games/genius_square/main.rs index 1065e27..21e06cd 100644 --- a/src/bin/games/genius_square/main.rs +++ b/src/bin/games/genius_square/main.rs @@ -2,12 +2,24 @@ /// IMPORTS /// ---------------------------------------------------------------- +use std::env; + use general::_core; +mod algorithms; +mod models; +mod features; + +use features::create_game::feature_create_game; + /// ---------------------------------------------------------------- /// MAIN /// ---------------------------------------------------------------- fn main() { - _core::strings::greet("world"); + let args: Vec = env::args().skip(1).collect(); + let option_roll = if args.len() >= 7 { Some(args[0..7].to_vec()) } else { None }; + let option_seed = if args.len() >= 1 { Some(args[args.len() - 1].clone()) } else { None }; + let mut rng = _core::rand::seed_rng(option_seed); + feature_create_game(&mut rng, option_roll); } diff --git a/src/bin/games/genius_square/mod.rs b/src/bin/games/genius_square/mod.rs index e69de29..47b895e 100644 --- a/src/bin/games/genius_square/mod.rs +++ b/src/bin/games/genius_square/mod.rs @@ -0,0 +1,5 @@ +/// Code base for game Genius Square + +pub mod algorithms; +pub mod features; +pub mod models; diff --git a/src/bin/games/genius_square/models/dice/constants.rs b/src/bin/games/genius_square/models/dice/constants.rs new file mode 100644 index 0000000..2ad925b --- /dev/null +++ b/src/bin/games/genius_square/models/dice/constants.rs @@ -0,0 +1,19 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +// + +/// ---------------------------------------------------------------- +/// CONSTANTS +/// ---------------------------------------------------------------- + +pub const DICE: &[&[&str]] = &[ + &["A5","A5","F2","F2","E1","B6"], + &["A6","A6","A6","F1","F1","F1"], + &["D5","E4","E5","E6","F4","F5"], + &["A2","A3","B1","B2","B3","C2"], + &["A1","C1","D1","D2","E2","F3"], + &["B4","C3","C4","D3","D4","E3"], + &["A4","B5","C5","C6","D6","F6"], +]; diff --git a/src/bin/games/genius_square/models/dice/methods.rs b/src/bin/games/genius_square/models/dice/methods.rs new file mode 100644 index 0000000..33b0227 --- /dev/null +++ b/src/bin/games/genius_square/models/dice/methods.rs @@ -0,0 +1,21 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +use rand_chacha::ChaCha8Rng; +use rand::prelude::IndexedRandom; + +use super::constants; + +/// ---------------------------------------------------------------- +/// METHODS +/// ---------------------------------------------------------------- + +pub fn roll_dice( + rng: &mut ChaCha8Rng, +) -> Vec { + constants::DICE + .iter() + .map(|die| die.choose(rng).unwrap().to_string()) + .collect() +} diff --git a/src/bin/games/genius_square/models/dice/mod.rs b/src/bin/games/genius_square/models/dice/mod.rs new file mode 100644 index 0000000..850dec7 --- /dev/null +++ b/src/bin/games/genius_square/models/dice/mod.rs @@ -0,0 +1,4 @@ +/// Models used in game. + +pub mod constants; +pub mod methods; diff --git a/src/bin/games/genius_square/models/mod.rs b/src/bin/games/genius_square/models/mod.rs new file mode 100644 index 0000000..c8605e6 --- /dev/null +++ b/src/bin/games/genius_square/models/mod.rs @@ -0,0 +1,4 @@ +/// Models used in game. + +pub mod dice; +pub mod pieces; diff --git a/src/bin/games/genius_square/models/pieces/constants.rs b/src/bin/games/genius_square/models/pieces/constants.rs new file mode 100644 index 0000000..702187d --- /dev/null +++ b/src/bin/games/genius_square/models/pieces/constants.rs @@ -0,0 +1,12 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +// + +/// ---------------------------------------------------------------- +/// CONSTANTS +/// ---------------------------------------------------------------- + +#[allow(unused)] +pub const PIECES: &[&[&str]] = &[]; diff --git a/src/bin/games/genius_square/models/pieces/methods.rs b/src/bin/games/genius_square/models/pieces/methods.rs new file mode 100644 index 0000000..9e382d4 --- /dev/null +++ b/src/bin/games/genius_square/models/pieces/methods.rs @@ -0,0 +1,14 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +// use super::constants; + +/// ---------------------------------------------------------------- +/// METHODS +/// ---------------------------------------------------------------- + +#[allow(unused)] +pub fn method() { + panic!("not implemented"); +} diff --git a/src/bin/games/genius_square/models/pieces/mod.rs b/src/bin/games/genius_square/models/pieces/mod.rs new file mode 100644 index 0000000..850dec7 --- /dev/null +++ b/src/bin/games/genius_square/models/pieces/mod.rs @@ -0,0 +1,4 @@ +/// Models used in game. + +pub mod constants; +pub mod methods; From 25eae75d30145a6e334154f5ce95853d62924dac Mon Sep 17 00:00:00 2001 From: raj-open Date: Wed, 3 Sep 2025 09:18:30 +0100 Subject: [PATCH 23/54] story-game-gs > staging: renamed --- src/bin/games/genius_square/features/mod.rs | 2 +- .../genius_square/features/{create_game.rs => setup_game.rs} | 2 +- src/bin/games/genius_square/main.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename src/bin/games/genius_square/features/{create_game.rs => setup_game.rs} (95%) diff --git a/src/bin/games/genius_square/features/mod.rs b/src/bin/games/genius_square/features/mod.rs index 0b4fdb0..aee96f5 100644 --- a/src/bin/games/genius_square/features/mod.rs +++ b/src/bin/games/genius_square/features/mod.rs @@ -1,3 +1,3 @@ /// Highest logic of application. -pub mod create_game; +pub mod setup_game; diff --git a/src/bin/games/genius_square/features/create_game.rs b/src/bin/games/genius_square/features/setup_game.rs similarity index 95% rename from src/bin/games/genius_square/features/create_game.rs rename to src/bin/games/genius_square/features/setup_game.rs index d290cdd..42194e2 100644 --- a/src/bin/games/genius_square/features/create_game.rs +++ b/src/bin/games/genius_square/features/setup_game.rs @@ -10,7 +10,7 @@ use crate::models::dice::methods::roll_dice; /// METHODS /// ---------------------------------------------------------------- -pub fn feature_create_game( +pub fn feature_setup_game( rng: &mut ChaCha8Rng, option_roll: Option>, ) { diff --git a/src/bin/games/genius_square/main.rs b/src/bin/games/genius_square/main.rs index 21e06cd..b4dcd9d 100644 --- a/src/bin/games/genius_square/main.rs +++ b/src/bin/games/genius_square/main.rs @@ -10,7 +10,7 @@ mod algorithms; mod models; mod features; -use features::create_game::feature_create_game; +use features::setup_game::feature_setup_game; /// ---------------------------------------------------------------- /// MAIN @@ -21,5 +21,5 @@ fn main() { let option_roll = if args.len() >= 7 { Some(args[0..7].to_vec()) } else { None }; let option_seed = if args.len() >= 1 { Some(args[args.len() - 1].clone()) } else { None }; let mut rng = _core::rand::seed_rng(option_seed); - feature_create_game(&mut rng, option_roll); + feature_setup_game(&mut rng, option_roll); } From 1652759ecd10529bb23863b026ae067e3ffa2564 Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 09:50:43 +0100 Subject: [PATCH 24/54] story-game-gs > staging: added dependencies and renamed binaries --- Cargo.lock | 101 +++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 18 +++++--- templates/template.env | 2 +- 3 files changed, 114 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d3f907..e9bb744 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -440,12 +440,16 @@ dependencies = [ "cargo-zigbuild", "dedent", "dict_derive", + "indoc", + "itertools", + "ndarray", "rand 0.9.2", "rand_chacha 0.9.0", "rstest", "rustfmt", "serde", "serde_json", + "strip-ansi-escapes", ] [[package]] @@ -519,12 +523,27 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "indoc" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" + [[package]] name = "is_terminal_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.15" @@ -584,12 +603,55 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +[[package]] +name = "matrixmultiply" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" +dependencies = [ + "autocfg 1.4.0", + "rawpointer", +] + [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "ndarray" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841" +dependencies = [ + "matrixmultiply", + "num-complex", + "num-integer", + "num-traits", + "portable-atomic", + "portable-atomic-util", + "rawpointer", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -635,6 +697,21 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -812,6 +889,12 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + [[package]] name = "rdrand" version = "0.4.0" @@ -1095,6 +1178,15 @@ dependencies = [ "log 0.3.9", ] +[[package]] +name = "strip-ansi-escapes" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a8f8038e7e7969abb3f1b7c2a811225e9296da208539e0f79c5251d6cac0025" +dependencies = [ + "vte", +] + [[package]] name = "strsim" version = "0.11.1" @@ -1312,6 +1404,15 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "vte" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "231fdcd7ef3037e8330d8e17e61011a2c244126acc0a982f4040ac3f9f0bc077" +dependencies = [ + "memchr", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index cf9c497..611906e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ name = "general" version = "0.1.0" edition = "2024" description = "Code for challenges from various platforms" +homepage = "github.com/raj-open/code-challenges" rust-version = "1.86" authors = [ "raj-open ", @@ -20,10 +21,6 @@ members = [ ".", ] -[[bin]] -name = "games-genius-square" -path = "src/bin/games/genius_square/main.rs" - # [env] # NOTE: has no effect # PYO3_PYTHON = { value = "python3" } @@ -57,8 +54,13 @@ serde = {version = "^1.0.219", features = ["derive"]} serde_json = {version = "^1.0.143"} dict_derive = {version = "^0.6.0" } dedent = {version="^0.1.1"} +itertools = {version = "^0.14.0"} +indoc = {version="^2.0.6"} +strip-ansi-escapes = {version="^0.2.1"} rand = {version="^0.9.2"} rand_chacha = {version = "^0.9.0"} +# numpy = {version = "^0.26.0"} +ndarray = {version = "^0.16.1"} [dev-dependencies] cargo-zigbuild = {version = "^0.20.1"} @@ -67,9 +69,13 @@ rustfmt = {version = "^0.10.0", features = []} # just = {version = "^1.40.0"} [[bin]] -name = "code-challenges" +name = "CodeChallenges" path = "src/main.rs" [[bin]] -name = "hackerrank_mathematics" +name = "HackerRankMathematiks" path = "src/problems/hackerrank/mathematics/main.rs" + +[[bin]] +name = "GeniusSquare" +path = "src/bin/games/genius_square/main.rs" diff --git a/templates/template.env b/templates/template.env index d3a3044..1616d08 100644 --- a/templates/template.env +++ b/templates/template.env @@ -2,7 +2,7 @@ # PROJECT SETTINGS # ---------------------------------------------------------------- -MAIN_MODULE="code_challenges" +MAIN_MODULE="CodeChallenges" # ---------------------------------------------------------------- # LOCAL SYSTEM SETTINGS From 31ba07d32acc05bf43b28b67b8c9c490c4f1ed12 Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 09:51:31 +0100 Subject: [PATCH 25/54] story-game-gs > staging: refactor - added core + app methods --- src/_core/strings.rs | 14 +++++++++++++- src/app/messages.rs | 45 ++++++++++++++++++++++++++++++++++++++++++++ src/app/mod.rs | 3 +++ src/lib.rs | 3 +++ src/mod.rs | 3 +++ 5 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/app/messages.rs create mode 100644 src/app/mod.rs diff --git a/src/_core/strings.rs b/src/_core/strings.rs index b313a66..9673e89 100644 --- a/src/_core/strings.rs +++ b/src/_core/strings.rs @@ -2,7 +2,7 @@ /// IMPORTS /// ---------------------------------------------------------------- -/// +use strip_ansi_escapes::strip; /// ---------------------------------------------------------------- /// METHODS @@ -11,3 +11,15 @@ pub fn greet(name: &str) { println!("Hello, {}!", name); } + +#[allow(unused)] +/// Strips potential ANSII characters +pub fn purify_string(text: &String) -> String { + String::from_utf8(strip(text)).unwrap_or(text.clone()) +} + +#[allow(unused)] +/// Computes length of purified string +pub fn purify_string_length(text: &String) -> usize { + purify_string(text).len() +} diff --git a/src/app/messages.rs b/src/app/messages.rs new file mode 100644 index 0000000..b6ea18c --- /dev/null +++ b/src/app/messages.rs @@ -0,0 +1,45 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +use std::env; + +use super::super::_core::strings::purify_string_length; + +/// ---------------------------------------------------------------- +/// METHODS +/// ---------------------------------------------------------------- + +#[allow(unused)] +pub fn welcome_screen() { + let exe = env::current_exe().unwrap(); + let app_name: &str = exe.file_name().unwrap().to_str().unwrap(); + const VERSION: &str = env!("CARGO_PKG_VERSION"); + const URL: &str = env!("CARGO_PKG_HOMEPAGE"); + let lines: Vec = vec![ + format!("{app_name} \x1b[92;1mv{VERSION}\x1b[0m"), + format!("{URL}"), + ]; + display_bordered_message(lines); +} + +/// ---------------------------------------------------------------- +/// AUXILIARY METHODS +/// ---------------------------------------------------------------- + +fn display_bordered_message(lines: Vec) { + // determine padding + let n = lines.iter().map(purify_string_length).max().unwrap_or(0); + let hspace = " ".repeat(n + 2); + let hbar = "\u{2500}".repeat(n + 2); + + println!("\u{250C}{hbar}\u{2510}"); + println!("\u{2502}{hspace}\u{2502}"); + let _: Vec<_> = lines.iter().map(|line| { + let k = purify_string_length(line); + let pad = " ".repeat(n - k); + println!("\u{2502} {line}{pad} \u{2502}"); + }).collect(); + println!("\u{2502}{hspace}\u{2502}"); + println!("\u{2514}{hbar}\u{2518}"); +} diff --git a/src/app/mod.rs b/src/app/mod.rs new file mode 100644 index 0000000..2de8453 --- /dev/null +++ b/src/app/mod.rs @@ -0,0 +1,3 @@ +/// Submodules for app-level methods + +pub mod messages; diff --git a/src/lib.rs b/src/lib.rs index 077fd81..46446e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,6 @@ +/// Modules available from General crate for other crates + +pub mod app; pub mod _core; pub mod models; pub mod problems; diff --git a/src/mod.rs b/src/mod.rs index 63c7f2b..108d231 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -1,2 +1,5 @@ +/// Modules available for General code base + +pub mod app; pub mod models; pub mod problems; From 075e402745d838fcaa049a50f353e8c7b75305db Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 09:51:53 +0100 Subject: [PATCH 26/54] story-game-gs > staging: refactored and completed models --- .../games/genius_square/models/arrays/mod.rs | 3 + .../genius_square/models/arrays/models.rs | 234 ++++++++++++++++++ .../games/genius_square/models/board/mod.rs | 3 + .../genius_square/models/board/models.rs | 188 ++++++++++++++ .../constants.rs => constants/board.rs} | 4 +- .../{dice/constants.rs => constants/dice.rs} | 36 +++ .../genius_square/models/constants/enums.rs | 121 +++++++++ .../genius_square/models/constants/mod.rs | 6 + .../genius_square/models/constants/pieces.rs | 109 ++++++++ .../genius_square/models/dice/methods.rs | 4 +- .../games/genius_square/models/dice/mod.rs | 4 +- .../games/genius_square/models/dice/models.rs | 60 +++++ src/bin/games/genius_square/models/mod.rs | 3 + .../games/genius_square/models/pieces/mod.rs | 4 +- .../genius_square/models/pieces/models.rs | 175 +++++++++++++ 15 files changed, 946 insertions(+), 8 deletions(-) create mode 100644 src/bin/games/genius_square/models/arrays/mod.rs create mode 100644 src/bin/games/genius_square/models/arrays/models.rs create mode 100644 src/bin/games/genius_square/models/board/mod.rs create mode 100644 src/bin/games/genius_square/models/board/models.rs rename src/bin/games/genius_square/models/{pieces/constants.rs => constants/board.rs} (82%) rename src/bin/games/genius_square/models/{dice/constants.rs => constants/dice.rs} (51%) create mode 100644 src/bin/games/genius_square/models/constants/enums.rs create mode 100644 src/bin/games/genius_square/models/constants/mod.rs create mode 100644 src/bin/games/genius_square/models/constants/pieces.rs create mode 100644 src/bin/games/genius_square/models/dice/models.rs create mode 100644 src/bin/games/genius_square/models/pieces/models.rs diff --git a/src/bin/games/genius_square/models/arrays/mod.rs b/src/bin/games/genius_square/models/arrays/mod.rs new file mode 100644 index 0000000..93e2fc4 --- /dev/null +++ b/src/bin/games/genius_square/models/arrays/mod.rs @@ -0,0 +1,3 @@ +/// Models for handling arrays + +pub mod models; diff --git a/src/bin/games/genius_square/models/arrays/models.rs b/src/bin/games/genius_square/models/arrays/models.rs new file mode 100644 index 0000000..62e097d --- /dev/null +++ b/src/bin/games/genius_square/models/arrays/models.rs @@ -0,0 +1,234 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +use ndarray::Array2; +use ndarray::s as slice; +use std::fmt::Debug; +use std::fmt::Display; +use std::fmt::Formatter; +use std::fmt::Result; + +use std::ops::Add; +use std::ops::Mul; +use itertools::iproduct; + +/// ---------------------------------------------------------------- +/// STRUCTS +/// ---------------------------------------------------------------- + +#[derive(Clone, Debug)] +pub struct BinArray { + m: usize, + n: usize, + values: Array2, +} + +/// ---------------------------------------------------------------- +/// IMPLEMENTATIONS +/// ---------------------------------------------------------------- + +impl BinArray { + pub fn from_coords( + coords: Vec<(usize, usize)>, + m: usize, + n: usize, + ) -> Self { + let mut values = Array2::::zeros((m, n)); + for coord in coords { + values[[coord.0, coord.1]] = 1; + } + Self {m, n, values} + } + + pub fn to_coords(&self) -> Vec<(usize, usize)> { + let mut coords: Vec<(usize, usize)> = vec![]; + for (i, row) in self.values.rows().into_iter().enumerate() { + for (j, &val) in row.iter().enumerate() { + if val == 1 { + coords.push((i, j)); + } + } + } + return coords; + } + + pub fn get_weight(&self) -> u8 { + let values = self.values.mapv(|x| if x == 0 {0} else {1}); + let weight = values.sum(); + return weight; + } + + pub fn get_coweight(&self) -> u8 { + let covalues = self.values.mapv(|x| if x == 0 {1} else {0}); + let coweight = covalues.sum(); + return coweight; + } + + pub fn get_shape(&self) -> (usize, usize) { + (self.m, self.n) + } + + pub fn get_values(&self) -> Array2 { + self.values.clone() + } + + /// Shifts array as far as possible to top left + pub fn recentre(&self) -> Self { + // determine maximal h+v-shifts + let coords = self.to_coords(); + let i_min: usize = *coords.iter().map(|(i, _)| i).min().unwrap_or(&0); + let j_min: usize = *coords.iter().map(|(_, j)| j).min().unwrap_or(&0); + // shift coords + let result = self.transform_shift(-(i_min as isize), -(j_min as isize)); + return result; + } + + pub fn transform_shift( + &self, + di: isize, + dj: isize, + ) -> Self { + // shift coords + let m = self.m as isize; + let n = self.n as isize; + let coords = self.to_coords(); + let coords: Vec<(usize, usize)> = coords + .iter() + .map(|&(i, j)| (i as isize, j as isize)) + .map(|(i, j)| (i + di, j + dj)) + .filter(|&(i, j)| (0 <= i && i < m && 0 <= j && j < n)) + .map(|(i, j)| (usize::try_from(i).unwrap(), usize::try_from(j).unwrap())) + .collect(); + + // update values + let m = self.m; + let n = self.n; + let mut values = Array2::::zeros((m, n)); + for coord in coords { + values[[coord.0, coord.1]] = 1; + } + let result = Self {m, n, values}; + return result; + } + + pub fn transform_hflip(&self, recentre: bool) -> Self{ + let m = self.m; + let n = self.n; + let values = self.values.slice(slice![.., ..;-1]).to_owned(); + let mut result = Self {m, n, values}; + if recentre { + result = result.recentre(); + } + return result; + } + + pub fn transform_vflip(&self, recentre: bool) -> Self { + let m = self.m; + let n = self.n; + let values = self.values.slice(slice![..;-1, ..]).to_owned(); + let mut result = Self {m, n, values}; + if recentre { + result = result.recentre(); + } + return result; + + } + + pub fn transform_transpose(&self, recentre: bool) -> Self { + let m = self.m; + let n = self.n; + let values = self.values.t().to_owned(); + let mut result = Self {m, n, values}; + if recentre { + result = result.recentre(); + } + return result; + } + + /// For collision comparison + pub fn transform_dither(&self) -> Self { + let (m, n) = self.get_shape(); + let coords = self.to_coords(); + let arr = BinArray::from_coords(coords, m + 2, n + 2); + arr.transform_shift(1, 1); + let arr1 = arr.transform_shift(-1, 0).to_owned(); + let arr2 = arr.transform_shift(1, 0).to_owned(); + let arr3 = arr.transform_shift(0, -1).to_owned(); + let arr4 = arr.transform_shift(0, 1).to_owned(); + let arr = arr + arr1 + arr2 + arr3 + arr4; + let values = arr.values + .mapv(|x| x.min(1)) + .slice(slice![1..-1, 1..-1]) + .to_owned(); + let result = Self {m, n, values}; + return result; + } + + pub fn moves(&self) -> impl Iterator { + let m = self.m; + let n = self.n; + let range_i: Vec = (0.. m).map(|i| i as isize).collect(); + let range_j: Vec = (0.. n).map(|j| j as isize).collect(); + let params = iproduct!( + [false, true], + [false, true], + [false, true], + range_i, + range_j, + ); + let moves = params + .map(|(hflip, vflip, tr, di, dj)| { + // recover original + let mut arr = self.clone(); + if hflip { + arr = arr.transform_hflip(false); + } + if vflip { + arr = arr.transform_vflip(false); + } + if tr { + arr = arr.transform_transpose(false); + } + if hflip | vflip | tr { + arr = arr.recentre(); + } + arr = arr.transform_shift(di, dj); + return arr; + }) + // if geometric operations shift shape off the grid, skip + .filter(|arr| { + let wt = self.get_weight(); + return arr.get_weight() == wt; + }); + return moves; + } +} + +impl Display for BinArray { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "{}", self.values) + } +} + +impl Add for BinArray { + type Output = Self; + + fn add(self, other: Self) -> Self::Output { + let m = self.m; + let n = self.n; + let values = self.values + other.values; + return Self {m, n, values}; + } +} + +impl Mul for BinArray { + type Output = Self; + + fn mul(self, other: Self) -> Self::Output { + let m = self.m; + let n = self.n; + let values = self.values * other.values; + return Self {m, n, values}; + } +} diff --git a/src/bin/games/genius_square/models/board/mod.rs b/src/bin/games/genius_square/models/board/mod.rs new file mode 100644 index 0000000..a5034f1 --- /dev/null +++ b/src/bin/games/genius_square/models/board/mod.rs @@ -0,0 +1,3 @@ +/// Models for handling game board + +pub mod models; diff --git a/src/bin/games/genius_square/models/board/models.rs b/src/bin/games/genius_square/models/board/models.rs new file mode 100644 index 0000000..4425f70 --- /dev/null +++ b/src/bin/games/genius_square/models/board/models.rs @@ -0,0 +1,188 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +use ndarray::Array2; +use std::fmt::Debug; +use std::fmt::Display; +use std::fmt::Formatter; +use std::fmt::Result; +use std::collections::HashMap; + +use crate::models::constants::board::*; +use crate::models::constants::dice::*; +use crate::models::constants::enums::*; +use crate::models::pieces::models::*; + +/// ---------------------------------------------------------------- +/// STRUCTS +/// ---------------------------------------------------------------- + +#[derive(Clone, Debug)] +pub struct GameBoard { + block: Piece, + pieces: HashMap, +} + +/// ---------------------------------------------------------------- +/// IMPLEMENTATIONS +/// ---------------------------------------------------------------- + +impl GameBoard { + pub fn new(block: &Piece) -> Self { + let pieces: HashMap = HashMap::new(); + return Self {block: block.clone(), pieces} + } + + pub fn add_piece(&mut self, symb: &EnumPiece, piece: &Piece) { + self.pieces.insert(symb.clone(), piece.clone()); + } + + pub fn get_block(&self) -> &Piece { + &self.block + } + + pub fn to_string(&self) -> String { + let field = self.to_array_of_strings(false); + let text = Self::array_to_string(&field); + return text; + } + + #[allow(unused)] + pub fn to_formatted(&self) -> String { + let field = self.to_array_of_strings(true); + let text = Self::array_to_string(&field); + return text; + } + + pub fn pretty(&self) -> String { + let _m = GRID_HEIGHT; + let n = GRID_WIDTH; + let field = self.to_array_of_strings(true); + + fn create_border(lcorder: &str, fill: &str, mid: &str, rcorner: &str, n: usize) -> String { + let middle = format!("{fill}{mid}{fill}{fill}").repeat(n); + format!("{lcorder}{fill}{fill}{middle}{fill}{rcorner}") + } + + let top1 = create_border("\u{2552}", "\u{2550}", "\u{2564}", "\u{2555}", n); + let top2 = create_border("\u{255E}", "\u{2550}", "\u{256A}", "\u{2561}", n); + let mid = create_border("\u{251C}", "\u{2500}", "\u{253C}", "\u{2524}", n); + let bot = create_border("\u{2558}", "\u{2550}", "\u{2567}", "\u{255B}", n); + + let head = FACE1_FMT.join(" \u{2502} ").to_string(); + let head = format!("{top1}\n\u{2502} \u{2502} {head} \u{2502}\n{top2}"); + + let middle = field.rows() + .into_iter() + .enumerate() + .map(|(i, row)| { + let index = FACE2_FMT[i]; + let line = row.iter().map(|s| s.to_string()).collect::>().join(" \u{2502} "); + return format!("\u{2502} {index} \u{2502} {line} \u{2502}"); + }) + .collect::>() + .join(format!("\n{mid}\n").as_str()); + + let text = format!("{head}\n{middle}\n{bot}"); + + return text; + } + + fn to_array_of_strings(&self, formatted: bool) -> Array2 { + let m = GRID_HEIGHT; + let n = GRID_WIDTH; + let mut trace: Array2 = Array2::from_elem((m, n), " ".to_string()); + let piece = &self.block; + for (i, j) in piece.to_coords() { + let alpha = if formatted { piece.get_symb_fmt() } else { piece.get_symb() }; + trace[[i, j]] = alpha; + } + for (_, piece) in self.pieces.iter() { + for (i, j) in piece.to_coords() { + let alpha = if formatted { piece.get_symb_fmt() } else { piece.get_symb() }; + trace[[i, j]] = alpha; + } + } + return trace; + } + + fn array_to_string(field: &Array2) -> String { + let n = GRID_WIDTH; + let hbar = "\u{2500}".repeat(n + 2); + let top = format!("\u{250C}{hbar}\u{2510}"); + let bot = format!("\u{2514}{hbar}\u{2518}"); + let middle = field.rows() + .into_iter() + .map(|row| { + let line = row.iter().map(|s| s.as_str()).collect::(); + return format!("\u{2502} {line} \u{2502}"); + }) + .collect::>() + .join("\n"); + let text = format!("{top}\n{middle}\n{bot}"); + return text; + } + + pub fn moves( + &self, + piece: &Piece, + obst: &Piece, + ) -> impl Iterator { + let mut used: Vec = vec![]; + let it = piece + // convert to positions + .get_positions() + // get all possible moves + .moves() + // skip all moves which collide with obstacle + .filter(|pos| { + let pos_obst = obst.get_positions(); + let collision = pos.to_owned() * pos_obst.to_owned(); + let penalty = collision.get_weight(); + return penalty == 0; + }) + // skip all moves which lead to forbidden adjacent pieces + .filter(|pos| { + // only need to check for collisions of pieces of a paritcular kind + if !(NON_ADJACENT.contains(&piece.get_kind())) { + return true; + } + let pos_dither = pos.transform_dither(); + for (s, q) in self.pieces.iter() { + // only need to check for collisions of pieces of a paritcular kind + if !(NON_ADJACENT.contains(s)) { + continue; + } + if *s == piece.get_kind() { + continue; + } + let collision = pos_dither.to_owned() * q.get_positions().to_owned(); + let penalty = collision.get_weight(); + if penalty > 0 { + return false + } + } + return true; + }) + // convert to piece + .map(|pos| { + let kind = piece.get_kind(); + Piece::from_kind(&kind, Some(pos)) + }) + // skip duplicates + .filter(move |p| { + let value = p.to_string(); + let dupl = used.contains(&value); + used.push(value); + return !dupl; + }); + return it; + } +} + +impl Display for GameBoard { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "{}", self.to_string()) + } +} diff --git a/src/bin/games/genius_square/models/pieces/constants.rs b/src/bin/games/genius_square/models/constants/board.rs similarity index 82% rename from src/bin/games/genius_square/models/pieces/constants.rs rename to src/bin/games/genius_square/models/constants/board.rs index 702187d..9fb056d 100644 --- a/src/bin/games/genius_square/models/pieces/constants.rs +++ b/src/bin/games/genius_square/models/constants/board.rs @@ -8,5 +8,5 @@ /// CONSTANTS /// ---------------------------------------------------------------- -#[allow(unused)] -pub const PIECES: &[&[&str]] = &[]; +pub const GRID_HEIGHT: usize = 6; +pub const GRID_WIDTH: usize = 6; diff --git a/src/bin/games/genius_square/models/dice/constants.rs b/src/bin/games/genius_square/models/constants/dice.rs similarity index 51% rename from src/bin/games/genius_square/models/dice/constants.rs rename to src/bin/games/genius_square/models/constants/dice.rs index 2ad925b..5f8a492 100644 --- a/src/bin/games/genius_square/models/dice/constants.rs +++ b/src/bin/games/genius_square/models/constants/dice.rs @@ -8,6 +8,42 @@ /// CONSTANTS /// ---------------------------------------------------------------- +pub const FACE1: &[&str] = &[ + "A", + "B", + "C", + "D", + "E", + "F", +]; + +pub const FACE2: &[&str] = &[ + "1", + "2", + "3", + "4", + "5", + "6", +]; + +pub const FACE1_FMT: &[&str] = &[ + "\x1b[91,1mA\x1b[0m", + "\x1b[91,1mB\x1b[0m", + "\x1b[91,1mC\x1b[0m", + "\x1b[91,1mD\x1b[0m", + "\x1b[91,1mE\x1b[0m", + "\x1b[91,1mF\x1b[0m", +]; + +pub const FACE2_FMT: &[&str] = &[ + "\x1b[91,1m1\x1b[0m", + "\x1b[91,1m2\x1b[0m", + "\x1b[91,1m3\x1b[0m", + "\x1b[91,1m4\x1b[0m", + "\x1b[91,1m5\x1b[0m", + "\x1b[91,1m6\x1b[0m", +]; + pub const DICE: &[&[&str]] = &[ &["A5","A5","F2","F2","E1","B6"], &["A6","A6","A6","F1","F1","F1"], diff --git a/src/bin/games/genius_square/models/constants/enums.rs b/src/bin/games/genius_square/models/constants/enums.rs new file mode 100644 index 0000000..9979c5b --- /dev/null +++ b/src/bin/games/genius_square/models/constants/enums.rs @@ -0,0 +1,121 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +use std::fmt::Debug; +use std::fmt::Display; +use std::fmt::Formatter; +use std::fmt::Result; + +use crate::models::arrays::models::BinArray; +use super::board::*; +use super::pieces::*; + +/// ---------------------------------------------------------------- +/// STRUCTS AND CONSTANTS +/// ---------------------------------------------------------------- + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub enum EnumPiece { + Block, + Symb1, + Symb2, + Symb3, + Symb4, + C, + L, + T, + X, + Z, +} + +pub const ENUM_PIECES: &[EnumPiece] = &[ + EnumPiece::Block, + EnumPiece::Symb1, + EnumPiece::Symb2, + EnumPiece::Symb3, + EnumPiece::Symb4, + EnumPiece::C, + EnumPiece::L, + EnumPiece::T, + EnumPiece::X, + EnumPiece::Z, +]; + +pub const NON_ADJACENT: &[EnumPiece] = &[ + EnumPiece::Symb1, + EnumPiece::Symb2, + EnumPiece::Symb3, + EnumPiece::C, +]; + +/// ---------------------------------------------------------------- +/// IMPLEMENTATIONS +/// ---------------------------------------------------------------- + +impl EnumPiece { + #[allow(unused)] + pub const fn as_str(&self) -> &'static str { + match self { + EnumPiece::Block => SYMB_BLOCK, + EnumPiece::Symb1 => SYMB_PIECE_1, + EnumPiece::Symb2 => SYMB_PIECE_2, + EnumPiece::Symb3 => SYMB_PIECE_3, + EnumPiece::Symb4 => SYMB_PIECE_4, + EnumPiece::C => SYMB_PIECE_C, + EnumPiece::L => SYMB_PIECE_L, + EnumPiece::T => SYMB_PIECE_T, + EnumPiece::X => SYMB_PIECE_X, + EnumPiece::Z => SYMB_PIECE_Z, + } + } + + #[allow(unused)] + pub const fn to_formatted(&self) -> &'static str { + match self { + EnumPiece::Block => SYMB_FMT_BLOCK, + EnumPiece::Symb1 => SYMB_FMT_PIECE_1, + EnumPiece::Symb2 => SYMB_FMT_PIECE_2, + EnumPiece::Symb3 => SYMB_FMT_PIECE_3, + EnumPiece::Symb4 => SYMB_FMT_PIECE_4, + EnumPiece::C => SYMB_FMT_PIECE_C, + EnumPiece::L => SYMB_FMT_PIECE_L, + EnumPiece::T => SYMB_FMT_PIECE_T, + EnumPiece::X => SYMB_FMT_PIECE_X, + EnumPiece::Z => SYMB_FMT_PIECE_Z, + } + } + + pub fn get_positions(&self) -> BinArray { + let raw = match self { + EnumPiece::Block => BLOCK, + EnumPiece::Symb1 => PIECE_1, + EnumPiece::Symb2 => PIECE_2, + EnumPiece::Symb3 => PIECE_3, + EnumPiece::Symb4 => PIECE_4, + EnumPiece::C => PIECE_C, + EnumPiece::L => PIECE_L, + EnumPiece::T => PIECE_T, + EnumPiece::X => PIECE_X, + EnumPiece::Z => PIECE_Z, + }; + let mut coords: Vec<(usize, usize)> = vec![]; + for (i, line) in raw.lines().enumerate() { + for (j, a) in line.chars().enumerate() { + if a.to_string() == "+" { + coords.push((i, j)); + } + } + } + let m = GRID_HEIGHT; + let n = GRID_WIDTH; + let positions = BinArray::from_coords(coords, m, n); + return positions; + } +} + +impl Display for EnumPiece { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "{}", self.to_formatted()) + } +} diff --git a/src/bin/games/genius_square/models/constants/mod.rs b/src/bin/games/genius_square/models/constants/mod.rs new file mode 100644 index 0000000..416606a --- /dev/null +++ b/src/bin/games/genius_square/models/constants/mod.rs @@ -0,0 +1,6 @@ +/// Models for handling constants + +pub mod board; +pub mod dice; +pub mod enums; +pub mod pieces; diff --git a/src/bin/games/genius_square/models/constants/pieces.rs b/src/bin/games/genius_square/models/constants/pieces.rs new file mode 100644 index 0000000..01b890f --- /dev/null +++ b/src/bin/games/genius_square/models/constants/pieces.rs @@ -0,0 +1,109 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +use indoc::indoc; + +/// ---------------------------------------------------------------- +/// CONSTANTS +/// ---------------------------------------------------------------- + +pub const SYMB_BLOCK: &str = "\u{25A0}"; +pub const SYMB_FMT_BLOCK: &str = "\u{25A0}"; +pub const BLOCK: &str = indoc! {" + +..... + ...... + ...... + ...... + ...... +"}; + +pub const SYMB_PIECE_1: &str = "1"; +pub const SYMB_FMT_PIECE_1: &str = "1"; +pub const PIECE_1: &str = indoc! {" + +..... + ...... + ...... + ...... + ...... +"}; + +pub const SYMB_PIECE_2: &str = "2"; +pub const SYMB_FMT_PIECE_2: &str = "2"; +pub const PIECE_2: &str = indoc! {" + ++.... + ...... + ...... + ...... + ...... +"}; + +pub const SYMB_PIECE_3: &str = "3"; +pub const SYMB_FMT_PIECE_3: &str = "3"; +pub const PIECE_3: &str = indoc! {" + +++... + ...... + ...... + ...... + ...... +"}; + +pub const SYMB_PIECE_4: &str = "4"; +pub const SYMB_FMT_PIECE_4: &str = "4"; +pub const PIECE_4: &str = indoc! {" + ++++.. + ...... + ...... + ...... + ...... +"}; + +pub const SYMB_PIECE_C: &str = "C"; +pub const SYMB_FMT_PIECE_C: &str = "C"; +pub const PIECE_C: &str = indoc! {" + ++.... + +..... + ...... + ...... + ...... +"}; + +pub const SYMB_PIECE_L: &str = "L"; +pub const SYMB_FMT_PIECE_L: &str = "L"; +pub const PIECE_L: &str = indoc! {" + ++.... + +..... + +..... + ...... + ...... +"}; + +pub const SYMB_PIECE_T: &str = "T"; +pub const SYMB_FMT_PIECE_T: &str = "T"; +pub const PIECE_T: &str = indoc! {" + +++... + .+.... + ...... + ...... + ...... +"}; + +pub const SYMB_PIECE_X: &str = "X"; +pub const SYMB_FMT_PIECE_X: &str = "X"; +pub const PIECE_X: &str = indoc! {" + ++.... + ++.... + ...... + ...... + ...... +"}; + +pub const SYMB_PIECE_Z: &str = "Z"; +pub const SYMB_FMT_PIECE_Z: &str = "Z"; +pub const PIECE_Z: &str = indoc! {" + .++... + ++.... + ...... + ...... + ...... +"}; diff --git a/src/bin/games/genius_square/models/dice/methods.rs b/src/bin/games/genius_square/models/dice/methods.rs index 33b0227..d4839a1 100644 --- a/src/bin/games/genius_square/models/dice/methods.rs +++ b/src/bin/games/genius_square/models/dice/methods.rs @@ -5,7 +5,7 @@ use rand_chacha::ChaCha8Rng; use rand::prelude::IndexedRandom; -use super::constants; +use crate::models::constants::dice::*; /// ---------------------------------------------------------------- /// METHODS @@ -14,7 +14,7 @@ use super::constants; pub fn roll_dice( rng: &mut ChaCha8Rng, ) -> Vec { - constants::DICE + DICE .iter() .map(|die| die.choose(rng).unwrap().to_string()) .collect() diff --git a/src/bin/games/genius_square/models/dice/mod.rs b/src/bin/games/genius_square/models/dice/mod.rs index 850dec7..d66666c 100644 --- a/src/bin/games/genius_square/models/dice/mod.rs +++ b/src/bin/games/genius_square/models/dice/mod.rs @@ -1,4 +1,4 @@ -/// Models used in game. +/// Models for handling dice -pub mod constants; pub mod methods; +pub mod models; diff --git a/src/bin/games/genius_square/models/dice/models.rs b/src/bin/games/genius_square/models/dice/models.rs new file mode 100644 index 0000000..650325f --- /dev/null +++ b/src/bin/games/genius_square/models/dice/models.rs @@ -0,0 +1,60 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +use std::fmt::Debug; +use std::fmt::Display; +use std::fmt::Formatter; +use std::fmt::Result; + +use crate::models::constants::dice::*; + +/// ---------------------------------------------------------------- +/// STRUCTS +/// ---------------------------------------------------------------- + +#[derive(Copy, Clone, Debug)] +pub struct Die { + i: usize, + j: usize, +} + +/// ---------------------------------------------------------------- +/// IMPLEMENTATIONS +/// ---------------------------------------------------------------- + +impl Die { + pub fn from_string(face: &String) -> Die { + let chars: Vec = face.chars().map(|c| c.to_string()).collect(); + let char1 = chars.get(0).unwrap(); + let char2 = chars.get(1).unwrap(); + let index1 = FACE1.iter().position(|x| x == char1).unwrap(); + let index2 = FACE2.iter().position(|x| x == char2).unwrap(); + return Die { + i: index2, + j: index1, + } + } + + pub fn to_string(&self) -> String { + let char1: String = FACE1[self.j].to_string(); + let char2: String = FACE2[self.i].to_string(); + return format!("{char1}{char2}"); + } + + #[allow(unused)] + pub fn from_coords(i: usize, j: usize) -> Die { + return Die {i, j} + } + + #[allow(unused)] + pub fn to_coords(&self) -> (usize, usize) { + return (self.i, self.j) + } +} + +impl Display for Die { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "{}", self.to_string()) + } +} diff --git a/src/bin/games/genius_square/models/mod.rs b/src/bin/games/genius_square/models/mod.rs index c8605e6..33a3833 100644 --- a/src/bin/games/genius_square/models/mod.rs +++ b/src/bin/games/genius_square/models/mod.rs @@ -1,4 +1,7 @@ /// Models used in game. +pub mod arrays; +pub mod board; +pub mod constants; pub mod dice; pub mod pieces; diff --git a/src/bin/games/genius_square/models/pieces/mod.rs b/src/bin/games/genius_square/models/pieces/mod.rs index 850dec7..2ea0b25 100644 --- a/src/bin/games/genius_square/models/pieces/mod.rs +++ b/src/bin/games/genius_square/models/pieces/mod.rs @@ -1,4 +1,4 @@ -/// Models used in game. +/// Models for handling pieces -pub mod constants; pub mod methods; +pub mod models; diff --git a/src/bin/games/genius_square/models/pieces/models.rs b/src/bin/games/genius_square/models/pieces/models.rs new file mode 100644 index 0000000..985be77 --- /dev/null +++ b/src/bin/games/genius_square/models/pieces/models.rs @@ -0,0 +1,175 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +use std::fmt::Debug; +use std::fmt::Display; +use std::fmt::Formatter; +use std::fmt::Result; +use std::ops::Add; +use std::ops::Mul; + +use crate::models::arrays::models::BinArray; +use crate::models::constants::board::*; +use crate::models::constants::enums::*; + +/// ---------------------------------------------------------------- +/// STRUCTS +/// ---------------------------------------------------------------- + +#[derive(Clone, Debug)] +pub struct Piece { + kind: EnumPiece, + positions: BinArray, +} + +/// ---------------------------------------------------------------- +/// IMPLEMENTATIONS +/// ---------------------------------------------------------------- + +impl Piece { + pub fn from_kind(kind: &EnumPiece, positions: Option) -> Self { + let kind = kind.clone(); + let positions = positions.unwrap_or_else(|| kind.get_positions()); + Self {kind, positions} + } + + pub fn from_coords( + coords: Vec<(usize, usize)>, + option_kind: Option, + ) -> Self { + let m = GRID_HEIGHT; + let n = GRID_WIDTH; + let positions = BinArray::from_coords(coords, m, n); + let kind = option_kind.unwrap_or(EnumPiece::Block); + Self {kind, positions} + } + + pub fn to_coords(&self) -> Vec<(usize, usize)> { + self.positions.to_coords() + } + + pub fn get_kind(&self) -> EnumPiece { + self.kind.clone() + } + + pub fn get_symb(&self) -> String { + self.kind.as_str().to_string() + } + + pub fn get_symb_fmt(&self) -> String { + self.kind.to_formatted().to_string() + } + + pub fn get_positions(&self) -> &BinArray { + &self.positions + } + + #[allow(unused)] + pub fn get_weight(&self) -> u8 { + self.positions.get_weight() + } + + #[allow(unused)] + pub fn get_coweight(&self) -> u8 { + self.positions.get_coweight() + } + + pub fn to_string(&self) -> String { + let n = GRID_WIDTH; + let hbar = "\u{2500}".repeat(n + 2); + let top = format!("\u{250C}{hbar}\u{2510}"); + let bot = format!("\u{2514}{hbar}\u{2518}"); + let middle = self.positions.get_values().rows() + .into_iter() + .map(|row| { + let line = row + .iter() + .map(|&val| { + if val == 1 { + "+".to_string() + } else { + ".".to_string() + } + }) + .collect::>() + .join(""); + return format!("\u{2502} {line} \u{2502}"); + }) + .collect::>() + .join("\n"); + let text = format!("{top}\n{middle}\n{bot}"); + return text; + } + + #[allow(unused)] + pub fn transform_hflip(&self, recentre: bool) -> Self { + let kind = self.get_kind(); + let positions = self.positions.transform_hflip(recentre); + let result = Self{kind, positions}; + return result; + } + + #[allow(unused)] + pub fn transform_vflip(&self, recentre: bool) -> Self { + let kind = self.get_kind(); + let positions = self.positions.transform_vflip(recentre); + let result = Self {kind, positions}; + return result; + + } + + #[allow(unused)] + pub fn transform_transpose(&self, recentre: bool) -> Self { + let kind = self.get_kind(); + let positions = self.positions.transform_transpose(recentre); + let result = Self {kind, positions}; + return result; + } + + #[allow(unused)] + pub fn transform_shift( + &self, + di: isize, + dj: isize, + ) -> Self { + let kind = self.get_kind(); + let positions = self.positions.transform_shift(di, dj); + let result = Self {kind, positions}; + return result; + } + + #[allow(unused)] + pub fn transform_dither(&self) -> Self { + let kind = self.get_kind(); + let positions = self.positions.transform_dither(); + let result = Self {kind, positions}; + return result; + } +} + +impl Display for Piece { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "{}", self.to_string()) + } +} + +impl Add for Piece { + type Output = Self; + + fn add(self, other: Self) -> Self::Output { + let kind = self.get_kind(); + let positions = self.get_positions().to_owned() + other.get_positions().to_owned(); + return Self {kind, positions}; + } +} + +impl Mul for Piece { + type Output = Self; + + fn mul(self, other: Self) -> Self::Output { + let kind = self.get_kind(); + let positions = self.get_positions().to_owned() * other.get_positions().to_owned(); + return Self {kind, positions}; + } +} From eaa2691b0d7650084160c4ef8a92738253ee79d3 Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 09:52:26 +0100 Subject: [PATCH 27/54] story-game-gs > staging: updated higher logic --- .../genius_square/features/setup_game.rs | 32 +++++++++++++------ src/bin/games/genius_square/lib.rs | 5 +++ src/bin/games/genius_square/main.rs | 2 ++ src/bin/games/genius_square/mod.rs | 2 +- 4 files changed, 30 insertions(+), 11 deletions(-) create mode 100644 src/bin/games/genius_square/lib.rs diff --git a/src/bin/games/genius_square/features/setup_game.rs b/src/bin/games/genius_square/features/setup_game.rs index 42194e2..c549de0 100644 --- a/src/bin/games/genius_square/features/setup_game.rs +++ b/src/bin/games/genius_square/features/setup_game.rs @@ -5,6 +5,11 @@ use rand_chacha::ChaCha8Rng; use crate::models::dice::methods::roll_dice; +use crate::models::dice::models::Die; +use crate::models::constants::enums::EnumPiece; +use crate::models::pieces::models::Piece; +use crate::models::board::models::GameBoard; +use crate::algorithms::solve::solve_brute_force; /// ---------------------------------------------------------------- /// METHODS @@ -14,14 +19,21 @@ pub fn feature_setup_game( rng: &mut ChaCha8Rng, option_roll: Option>, ) { - let roll: Vec; - match option_roll { - Some(x) => { - roll = x; - }, - None => { - roll = roll_dice(rng); - } - } - println!("\nRoll: {}.\n", roll.join(", ")); + // Roll the dice + let faces = option_roll.unwrap_or_else(|| roll_dice(rng)); + let dice: Vec = faces.iter() + .map(|face| Die::from_string(face)) + .collect(); + println!("\nRoll: {}.\n", faces.join(", ")); + + // Establish the problem + let coords = dice.iter().map(|die| die.to_coords()).collect(); + let block = Piece::from_coords(coords, Some(EnumPiece::Block)); + let mut board = GameBoard::new(&block); + println!("\nProblem:\n{}\n", board.pretty()); + + // Solve the problem + println!("\nCompute solution...\n"); + solve_brute_force(&mut board); + println!("\nSolution:\n{}\n", board.pretty()); } diff --git a/src/bin/games/genius_square/lib.rs b/src/bin/games/genius_square/lib.rs new file mode 100644 index 0000000..8c3bf74 --- /dev/null +++ b/src/bin/games/genius_square/lib.rs @@ -0,0 +1,5 @@ +/// Modules available for Genius Square binary + +pub mod algorithms; +pub mod features; +pub mod models; diff --git a/src/bin/games/genius_square/main.rs b/src/bin/games/genius_square/main.rs index b4dcd9d..4812415 100644 --- a/src/bin/games/genius_square/main.rs +++ b/src/bin/games/genius_square/main.rs @@ -4,6 +4,7 @@ use std::env; +use general::app::messages::welcome_screen; use general::_core; mod algorithms; @@ -21,5 +22,6 @@ fn main() { let option_roll = if args.len() >= 7 { Some(args[0..7].to_vec()) } else { None }; let option_seed = if args.len() >= 1 { Some(args[args.len() - 1].clone()) } else { None }; let mut rng = _core::rand::seed_rng(option_seed); + welcome_screen(); feature_setup_game(&mut rng, option_roll); } diff --git a/src/bin/games/genius_square/mod.rs b/src/bin/games/genius_square/mod.rs index 47b895e..d0c2985 100644 --- a/src/bin/games/genius_square/mod.rs +++ b/src/bin/games/genius_square/mod.rs @@ -1,4 +1,4 @@ -/// Code base for game Genius Square +/// Modules for code base Genius Square pub mod algorithms; pub mod features; From 63ed2dad086b84c1fbb8c9128bae32bcbdb45e61 Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 09:52:56 +0100 Subject: [PATCH 28/54] story-game-gs > staging: added brute force algorithm TODO: runs, but gets stuck. Needs to be debugged. --- .../games/genius_square/algorithms/solve.rs | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/src/bin/games/genius_square/algorithms/solve.rs b/src/bin/games/genius_square/algorithms/solve.rs index e69de29..6d4aef8 100644 --- a/src/bin/games/genius_square/algorithms/solve.rs +++ b/src/bin/games/genius_square/algorithms/solve.rs @@ -0,0 +1,70 @@ +/// ---------------------------------------------------------------- +/// IMPORTS +/// ---------------------------------------------------------------- + +use std::collections::HashMap; + +use crate::models::constants::enums::ENUM_PIECES; +use crate::models::constants::enums::EnumPiece; +use crate::models::pieces::models::Piece; +use crate::models::board::models::GameBoard; + +/// ---------------------------------------------------------------- +/// METHODS +/// ---------------------------------------------------------------- + +/// Recursively solves by check all possibilities +pub fn solve_brute_force( + board: &mut GameBoard, +) { + let solution = recursion(board, None, None, None); + let pieces = solution.unwrap_or_else(|| HashMap::new()); + for (kind, piece) in pieces.iter() { + board.add_piece(&kind, &piece); + } +} + +/// ---------------------------------------------------------------- +/// AUXILIARY METHODS +/// ---------------------------------------------------------------- + +fn recursion( + board: &GameBoard, + obst: Option, + kinds: Option<&[EnumPiece]>, + solution: Option>, +) -> Option> { + + // if nothing left to solve, then return pieces, provide everything is filled + let kinds = kinds.unwrap_or(ENUM_PIECES); + let obst = obst.unwrap_or_else(|| board.get_block().to_owned()); + let pieces = solution.clone().unwrap_or_else(|| HashMap::new()); + if kinds.len() == 0 { + if obst.get_coweight() == 0 { + return Some(pieces); + } + return None; + } + + // otherwise go through all permissible moves for next piece and then proceed recursively + let kind = &kinds[0].clone(); + let kinds_ = &kinds[1..]; + let piece = Piece::from_kind(kind, None); // initialised piece + for p in board.moves(&piece, &obst) { + // update the obstacle + let obst_ = obst.clone() + p.clone(); + + // update the solution + let mut pieces_ = pieces.clone(); + pieces_.insert(kind.clone(), p); + + // compute remainder of solution recursively + match recursion(board, Some(obst_), Some(kinds_), Some(pieces_)) { + Some(result) => { + return Some(result); + }, + None => {}, + } + } + return None; +} From 255de08fc36282c789759b7e8a4be0c441fbf64e Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 10:02:50 +0100 Subject: [PATCH 29/54] story-game-gs > staging: added piece rotation and included this in iterations --- .../genius_square/models/arrays/models.rs | 24 +++++++++++++++---- .../genius_square/models/pieces/models.rs | 8 +++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/bin/games/genius_square/models/arrays/models.rs b/src/bin/games/genius_square/models/arrays/models.rs index 62e097d..7a0a21e 100644 --- a/src/bin/games/genius_square/models/arrays/models.rs +++ b/src/bin/games/genius_square/models/arrays/models.rs @@ -146,6 +146,20 @@ impl BinArray { return result; } + pub fn transform_rotate(&self, k: i8, recentre: bool) -> Self { + match k { + 1 => { + return self.transform_transpose(false).transform_vflip(recentre); + }, + -1 => { + return self.transform_vflip(false).transform_transpose(recentre); + }, + _ => { + return self.clone(); + } + } + } + /// For collision comparison pub fn transform_dither(&self) -> Self { let (m, n) = self.get_shape(); @@ -173,12 +187,12 @@ impl BinArray { let params = iproduct!( [false, true], [false, true], - [false, true], + [0, 1, -1], range_i, range_j, ); let moves = params - .map(|(hflip, vflip, tr, di, dj)| { + .map(|(hflip, vflip, rot, di, dj)| { // recover original let mut arr = self.clone(); if hflip { @@ -187,10 +201,10 @@ impl BinArray { if vflip { arr = arr.transform_vflip(false); } - if tr { - arr = arr.transform_transpose(false); + if rot != 0 { + arr = arr.transform_rotate(rot, false); } - if hflip | vflip | tr { + if hflip | vflip | (rot != 0) { arr = arr.recentre(); } arr = arr.transform_shift(di, dj); diff --git a/src/bin/games/genius_square/models/pieces/models.rs b/src/bin/games/genius_square/models/pieces/models.rs index 985be77..24b7d73 100644 --- a/src/bin/games/genius_square/models/pieces/models.rs +++ b/src/bin/games/genius_square/models/pieces/models.rs @@ -127,6 +127,14 @@ impl Piece { return result; } + #[allow(unused)] + pub fn transform_rotate(&self, k: i8, recentre: bool) -> Self { + let kind = self.get_kind(); + let positions = self.positions.transform_rotate(k, recentre); + let result = Self {kind, positions}; + return result; + } + #[allow(unused)] pub fn transform_shift( &self, From 45ab1b84531b0a1174eafb4896e29b2769d6c334 Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 12:49:03 +0100 Subject: [PATCH 30/54] story-game-gs > staging: cleanup + faster shift-method --- .../games/genius_square/algorithms/solve.rs | 12 +-- .../genius_square/models/arrays/models.rs | 75 ++++++++++--------- .../genius_square/models/board/models.rs | 16 +++- 3 files changed, 60 insertions(+), 43 deletions(-) diff --git a/src/bin/games/genius_square/algorithms/solve.rs b/src/bin/games/genius_square/algorithms/solve.rs index 6d4aef8..25d02e0 100644 --- a/src/bin/games/genius_square/algorithms/solve.rs +++ b/src/bin/games/genius_square/algorithms/solve.rs @@ -49,19 +49,19 @@ fn recursion( // otherwise go through all permissible moves for next piece and then proceed recursively let kind = &kinds[0].clone(); let kinds_ = &kinds[1..]; - let piece = Piece::from_kind(kind, None); // initialised piece - for p in board.moves(&piece, &obst) { + let piece0 = Piece::from_kind(kind, None); // initialised piece + for piece in board.get_configurations(&piece0, &obst) { // update the obstacle - let obst_ = obst.clone() + p.clone(); + let obst_ = obst.clone() + piece.clone(); // update the solution let mut pieces_ = pieces.clone(); - pieces_.insert(kind.clone(), p); + pieces_.insert(kind.clone(), piece); // compute remainder of solution recursively match recursion(board, Some(obst_), Some(kinds_), Some(pieces_)) { - Some(result) => { - return Some(result); + Some(pieces) => { + return Some(pieces); }, None => {}, } diff --git a/src/bin/games/genius_square/models/arrays/models.rs b/src/bin/games/genius_square/models/arrays/models.rs index 7a0a21e..4eb09ee 100644 --- a/src/bin/games/genius_square/models/arrays/models.rs +++ b/src/bin/games/genius_square/models/arrays/models.rs @@ -89,25 +89,25 @@ impl BinArray { di: isize, dj: isize, ) -> Self { - // shift coords - let m = self.m as isize; - let n = self.n as isize; - let coords = self.to_coords(); - let coords: Vec<(usize, usize)> = coords - .iter() - .map(|&(i, j)| (i as isize, j as isize)) - .map(|(i, j)| (i + di, j + dj)) - .filter(|&(i, j)| (0 <= i && i < m && 0 <= j && j < n)) - .map(|(i, j)| (usize::try_from(i).unwrap(), usize::try_from(j).unwrap())) - .collect(); - - // update values + // create blank 3 x 3 meta block let m = self.m; let n = self.n; - let mut values = Array2::::zeros((m, n)); - for coord in coords { - values[[coord.0, coord.1]] = 1; - } + let mut slate = Array2::::zeros((3*m, 3*n)); + + // slot in values in location shifted from the middle + let i0 = self.m as isize + di; + let i1 = (self.m as isize) + i0; + let j0 = self.n as isize + dj; + let j1 = (self.n as isize) + j0; + let mut view = slate.slice_mut(slice![i0..i1, j0..j1]); + view.assign(&self.values); + + // restrict to "middle" part + let i0 = self.m; + let i1 = self.m + i0; + let j0 = self.n; + let j1 = self.n + j0; + let values = slate.slice_mut(slice![i0..i1, j0..j1]).to_owned(); let result = Self {m, n, values}; return result; } @@ -179,30 +179,35 @@ impl BinArray { return result; } - pub fn moves(&self) -> impl Iterator { - let m = self.m; - let n = self.n; - let range_i: Vec = (0.. m).map(|i| i as isize).collect(); - let range_j: Vec = (0.. n).map(|j| j as isize).collect(); - let params = iproduct!( + /// Determines all possible configurations + /// of the same array subject to + /// + /// - rotations, + /// - v- and h-flips, + /// - v- and h-shifts + /// + /// provided the moves preserve the "weight" of the shadow in the array + pub fn get_configurations(&self) -> impl Iterator { + let m = self.m as isize; + let n = self.n as isize; + let iterator = iproduct!( + [0, 1, -1], [false, true], [false, true], - [0, 1, -1], - range_i, - range_j, - ); - let moves = params - .map(|(hflip, vflip, rot, di, dj)| { + (0.. m), + (0.. n), + ) + .map(|(rot, vflip, hflip, di, dj)| { // recover original let mut arr = self.clone(); - if hflip { - arr = arr.transform_hflip(false); + if rot != 0 { + arr = arr.transform_rotate(rot, false); } if vflip { arr = arr.transform_vflip(false); } - if rot != 0 { - arr = arr.transform_rotate(rot, false); + if hflip { + arr = arr.transform_hflip(false); } if hflip | vflip | (rot != 0) { arr = arr.recentre(); @@ -213,9 +218,9 @@ impl BinArray { // if geometric operations shift shape off the grid, skip .filter(|arr| { let wt = self.get_weight(); - return arr.get_weight() == wt; + return arr.get_weight() >= wt; }); - return moves; + return iterator; } } diff --git a/src/bin/games/genius_square/models/board/models.rs b/src/bin/games/genius_square/models/board/models.rs index 4425f70..0e7a122 100644 --- a/src/bin/games/genius_square/models/board/models.rs +++ b/src/bin/games/genius_square/models/board/models.rs @@ -124,7 +124,19 @@ impl GameBoard { return text; } - pub fn moves( + /// Determines all possible configurations + /// of the same piece subject to + /// + /// - rotations, + /// - v- and h-flips, + /// - v- and h-shifts + /// + /// provided the moves preserve the "weight" of the shadow in the array + /// and provided + /// + /// - no collisions occur with already placed pieces (marked by `obst`) + /// - the piece is not adjacent to certain other pieces. + pub fn get_configurations( &self, piece: &Piece, obst: &Piece, @@ -134,7 +146,7 @@ impl GameBoard { // convert to positions .get_positions() // get all possible moves - .moves() + .get_configurations() // skip all moves which collide with obstacle .filter(|pos| { let pos_obst = obst.get_positions(); From 5c62cd20d13d43ff82b03a61e175e5bd32d4f11c Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 14:17:48 +0100 Subject: [PATCH 31/54] story-game-gs > staging: corrected types --- src/bin/games/genius_square/models/arrays/models.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/games/genius_square/models/arrays/models.rs b/src/bin/games/genius_square/models/arrays/models.rs index 4eb09ee..ebc5439 100644 --- a/src/bin/games/genius_square/models/arrays/models.rs +++ b/src/bin/games/genius_square/models/arrays/models.rs @@ -53,13 +53,13 @@ impl BinArray { return coords; } - pub fn get_weight(&self) -> u8 { + pub fn get_weight(&self) -> isize { let values = self.values.mapv(|x| if x == 0 {0} else {1}); let weight = values.sum(); return weight; } - pub fn get_coweight(&self) -> u8 { + pub fn get_coweight(&self) -> isize { let covalues = self.values.mapv(|x| if x == 0 {1} else {0}); let coweight = covalues.sum(); return coweight; From c8e6d256b3fc94620e74b194ba549f18b72b0b83 Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 14:20:18 +0100 Subject: [PATCH 32/54] story-game-gs > staging: use negative penalties --- src/bin/games/genius_square/models/board/models.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/bin/games/genius_square/models/board/models.rs b/src/bin/games/genius_square/models/board/models.rs index 0e7a122..8b38860 100644 --- a/src/bin/games/genius_square/models/board/models.rs +++ b/src/bin/games/genius_square/models/board/models.rs @@ -34,10 +34,16 @@ impl GameBoard { return Self {block: block.clone(), pieces} } + #[allow(unused)] pub fn add_piece(&mut self, symb: &EnumPiece, piece: &Piece) { self.pieces.insert(symb.clone(), piece.clone()); } + #[allow(unused)] + pub fn set_pieces(&mut self, pieces: &HashMap) { + self.pieces = pieces.clone(); + } + pub fn get_block(&self) -> &Piece { &self.block } @@ -93,7 +99,7 @@ impl GameBoard { let m = GRID_HEIGHT; let n = GRID_WIDTH; let mut trace: Array2 = Array2::from_elem((m, n), " ".to_string()); - let piece = &self.block; + let piece = self.get_block(); for (i, j) in piece.to_coords() { let alpha = if formatted { piece.get_symb_fmt() } else { piece.get_symb() }; trace[[i, j]] = alpha; @@ -169,9 +175,10 @@ impl GameBoard { if *s == piece.get_kind() { continue; } + let collision = pos_dither.to_owned() * q.get_positions().to_owned(); let penalty = collision.get_weight(); - if penalty > 0 { + if penalty < 0 { return false } } From 3b30fdf835c6312f2ab4a77ae61595527d3253c0 Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 14:20:45 +0100 Subject: [PATCH 33/54] story-game-gs > staging: add blank enum as default --- src/bin/games/genius_square/models/constants/enums.rs | 4 ++++ src/bin/games/genius_square/models/pieces/models.rs | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/bin/games/genius_square/models/constants/enums.rs b/src/bin/games/genius_square/models/constants/enums.rs index 9979c5b..c47d112 100644 --- a/src/bin/games/genius_square/models/constants/enums.rs +++ b/src/bin/games/genius_square/models/constants/enums.rs @@ -17,6 +17,7 @@ use super::pieces::*; #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub enum EnumPiece { + Blank, Block, Symb1, Symb2, @@ -57,6 +58,7 @@ impl EnumPiece { #[allow(unused)] pub const fn as_str(&self) -> &'static str { match self { + EnumPiece::Blank => " ", EnumPiece::Block => SYMB_BLOCK, EnumPiece::Symb1 => SYMB_PIECE_1, EnumPiece::Symb2 => SYMB_PIECE_2, @@ -73,6 +75,7 @@ impl EnumPiece { #[allow(unused)] pub const fn to_formatted(&self) -> &'static str { match self { + EnumPiece::Blank => " ", EnumPiece::Block => SYMB_FMT_BLOCK, EnumPiece::Symb1 => SYMB_FMT_PIECE_1, EnumPiece::Symb2 => SYMB_FMT_PIECE_2, @@ -88,6 +91,7 @@ impl EnumPiece { pub fn get_positions(&self) -> BinArray { let raw = match self { + EnumPiece::Blank => " ", EnumPiece::Block => BLOCK, EnumPiece::Symb1 => PIECE_1, EnumPiece::Symb2 => PIECE_2, diff --git a/src/bin/games/genius_square/models/pieces/models.rs b/src/bin/games/genius_square/models/pieces/models.rs index 24b7d73..1bf73e6 100644 --- a/src/bin/games/genius_square/models/pieces/models.rs +++ b/src/bin/games/genius_square/models/pieces/models.rs @@ -41,7 +41,7 @@ impl Piece { let m = GRID_HEIGHT; let n = GRID_WIDTH; let positions = BinArray::from_coords(coords, m, n); - let kind = option_kind.unwrap_or(EnumPiece::Block); + let kind = option_kind.unwrap_or(EnumPiece::Blank); Self {kind, positions} } @@ -66,12 +66,12 @@ impl Piece { } #[allow(unused)] - pub fn get_weight(&self) -> u8 { + pub fn get_weight(&self) -> isize { self.positions.get_weight() } #[allow(unused)] - pub fn get_coweight(&self) -> u8 { + pub fn get_coweight(&self) -> isize { self.positions.get_coweight() } From b56e17e2ecac9600cb3478237e1cc09cb4cc0fac Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 14:22:14 +0100 Subject: [PATCH 34/54] story-game-gs > staging: refactored --- .../games/genius_square/algorithms/solve.rs | 69 +++++++++---------- .../genius_square/features/setup_game.rs | 2 +- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/src/bin/games/genius_square/algorithms/solve.rs b/src/bin/games/genius_square/algorithms/solve.rs index 25d02e0..f9ab334 100644 --- a/src/bin/games/genius_square/algorithms/solve.rs +++ b/src/bin/games/genius_square/algorithms/solve.rs @@ -2,8 +2,6 @@ /// IMPORTS /// ---------------------------------------------------------------- -use std::collections::HashMap; - use crate::models::constants::enums::ENUM_PIECES; use crate::models::constants::enums::EnumPiece; use crate::models::pieces::models::Piece; @@ -15,12 +13,16 @@ use crate::models::board::models::GameBoard; /// Recursively solves by check all possibilities pub fn solve_brute_force( - board: &mut GameBoard, -) { - let solution = recursion(board, None, None, None); - let pieces = solution.unwrap_or_else(|| HashMap::new()); - for (kind, piece) in pieces.iter() { - board.add_piece(&kind, &piece); + board: &GameBoard, +) -> GameBoard { + let obst = board.get_block().to_owned(); + match recursion(board, &obst, None) { + Some(board_) => { + return board_; + }, + None => { + return board.to_owned(); + } } } @@ -30,41 +32,38 @@ pub fn solve_brute_force( fn recursion( board: &GameBoard, - obst: Option, + obst: &Piece, kinds: Option<&[EnumPiece]>, - solution: Option>, -) -> Option> { - - // if nothing left to solve, then return pieces, provide everything is filled +) -> Option { let kinds = kinds.unwrap_or(ENUM_PIECES); - let obst = obst.unwrap_or_else(|| board.get_block().to_owned()); - let pieces = solution.clone().unwrap_or_else(|| HashMap::new()); + if kinds.len() == 0 { + // if nothing left to solve, then return pieces, provide everything is filled if obst.get_coweight() == 0 { - return Some(pieces); + return Some(board.to_owned()); } - return None; - } + } else { + // otherwise go through all permissible moves for next piece and then proceed recursively + let kind = &kinds[0].clone(); + let kinds = &kinds[1..]; + let piece0 = Piece::from_kind(kind, None); // initialised piece + for piece in board.get_configurations(&piece0, &obst) { + // update the obstacle + let obst_ = obst.clone() + piece.clone(); - // otherwise go through all permissible moves for next piece and then proceed recursively - let kind = &kinds[0].clone(); - let kinds_ = &kinds[1..]; - let piece0 = Piece::from_kind(kind, None); // initialised piece - for piece in board.get_configurations(&piece0, &obst) { - // update the obstacle - let obst_ = obst.clone() + piece.clone(); + // update the solution + let mut board_ = board.clone(); + board_.add_piece(&kind.clone(), &piece); - // update the solution - let mut pieces_ = pieces.clone(); - pieces_.insert(kind.clone(), piece); - - // compute remainder of solution recursively - match recursion(board, Some(obst_), Some(kinds_), Some(pieces_)) { - Some(pieces) => { - return Some(pieces); - }, - None => {}, + // compute remainder of solution recursively + match recursion(&mut board_, &obst_, Some(kinds)) { + Some(board_) => { + return Some(board_); + }, + None => {}, + } } } + return None; } diff --git a/src/bin/games/genius_square/features/setup_game.rs b/src/bin/games/genius_square/features/setup_game.rs index c549de0..2c359cf 100644 --- a/src/bin/games/genius_square/features/setup_game.rs +++ b/src/bin/games/genius_square/features/setup_game.rs @@ -34,6 +34,6 @@ pub fn feature_setup_game( // Solve the problem println!("\nCompute solution...\n"); - solve_brute_force(&mut board); + board = solve_brute_force(&board); println!("\nSolution:\n{}\n", board.pretty()); } From a69a691720ecc1f628114429d5ac7c171d40c35f Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 14:22:47 +0100 Subject: [PATCH 35/54] story-game-gs > staging: `bugfix` - corrected design --- src/bin/games/genius_square/models/constants/enums.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bin/games/genius_square/models/constants/enums.rs b/src/bin/games/genius_square/models/constants/enums.rs index c47d112..2f27ee6 100644 --- a/src/bin/games/genius_square/models/constants/enums.rs +++ b/src/bin/games/genius_square/models/constants/enums.rs @@ -31,7 +31,6 @@ pub enum EnumPiece { } pub const ENUM_PIECES: &[EnumPiece] = &[ - EnumPiece::Block, EnumPiece::Symb1, EnumPiece::Symb2, EnumPiece::Symb3, From 4e8d64a124c86d4dfa2a80017ab4178bc9862210 Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 14:23:59 +0100 Subject: [PATCH 36/54] story-game-gs > staging: `bugfix` - corrected computation of penalty --- src/bin/games/genius_square/models/board/models.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bin/games/genius_square/models/board/models.rs b/src/bin/games/genius_square/models/board/models.rs index 8b38860..2a0748b 100644 --- a/src/bin/games/genius_square/models/board/models.rs +++ b/src/bin/games/genius_square/models/board/models.rs @@ -157,8 +157,8 @@ impl GameBoard { .filter(|pos| { let pos_obst = obst.get_positions(); let collision = pos.to_owned() * pos_obst.to_owned(); - let penalty = collision.get_weight(); - return penalty == 0; + let penalty = -collision.get_weight(); + return penalty >= 0; }) // skip all moves which lead to forbidden adjacent pieces .filter(|pos| { @@ -177,7 +177,7 @@ impl GameBoard { } let collision = pos_dither.to_owned() * q.get_positions().to_owned(); - let penalty = collision.get_weight(); + let penalty = -collision.get_weight(); if penalty < 0 { return false } From c39874fd4e910fe4750e73506e41f7af24c809e8 Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 14:51:43 +0100 Subject: [PATCH 37/54] story-game-gs > staging: added optimisation for release and use `--release` with execution --- Cargo.toml | 5 +++++ justfile | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 611906e..6a6c481 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,12 +36,17 @@ members = [ # ] debug = true strip = false +opt-level = 3 +lto = true # link-time optimisation +codegen-units = 1 [profile.dev] # rustflags = [ # "-A", "unused_imports", # "-A", "dead_code", # ] +opt-level = 0 +lto = false # link-time optimisation [profile.test] # rustflags = [ diff --git a/justfile b/justfile index 69f999f..3b6a9a7 100644 --- a/justfile +++ b/justfile @@ -146,7 +146,7 @@ run-py module="main" *args="": run-rust module="${MAIN_MODULE}" *args="": @just build-compile "{{module}}" @# "./target/release/{{module}}" {{args}} - @cargo run --bin "{{module}}" {{args}} + @cargo run --release --bin "{{module}}" {{args}} # -------------------------------- # TARGETS: development @@ -155,6 +155,11 @@ run-rust module="${MAIN_MODULE}" *args="": dev *args: @echo "Not yet implemented" +dev-rust module="${MAIN_MODULE}" *args="": + @just build-compile "{{module}}" + @# "./target/release/{{module}}" {{args}} + @cargo run --bin "{{module}}" {{args}} + # -------------------------------- # TARGETS: tests # -------------------------------- From 4ff27f5500fa76f3fa9c8408992269f661f3ad97 Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 14:52:03 +0100 Subject: [PATCH 38/54] story-game-gs > staging: minor --- src/bin/games/genius_square/models/board/models.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/games/genius_square/models/board/models.rs b/src/bin/games/genius_square/models/board/models.rs index 2a0748b..1e6dc1f 100644 --- a/src/bin/games/genius_square/models/board/models.rs +++ b/src/bin/games/genius_square/models/board/models.rs @@ -179,7 +179,7 @@ impl GameBoard { let collision = pos_dither.to_owned() * q.get_positions().to_owned(); let penalty = -collision.get_weight(); if penalty < 0 { - return false + return false; } } return true; From 8bc675778aaf6a9e5fd34f6a2d27639099b308d3 Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 22:55:49 +0100 Subject: [PATCH 39/54] story-game-gs > staging: minor --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index eb47120..81d8062 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ /** !/.gitignore !/.gitattributes -!/.funcignore # ---------------------------------------------------------------- # ROOT From 23976e6623a44ee2945a2ef90be651562252be3b Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 22:55:59 +0100 Subject: [PATCH 40/54] story-game-gs > staging: minor cleanup --- src/bin/games/genius_square/models/board/models.rs | 5 +++-- src/bin/games/genius_square/models/pieces/models.rs | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/bin/games/genius_square/models/board/models.rs b/src/bin/games/genius_square/models/board/models.rs index 1e6dc1f..274c930 100644 --- a/src/bin/games/genius_square/models/board/models.rs +++ b/src/bin/games/genius_square/models/board/models.rs @@ -163,7 +163,8 @@ impl GameBoard { // skip all moves which lead to forbidden adjacent pieces .filter(|pos| { // only need to check for collisions of pieces of a paritcular kind - if !(NON_ADJACENT.contains(&piece.get_kind())) { + let kind = piece.get_kind(); + if !(NON_ADJACENT.contains(&kind)) { return true; } let pos_dither = pos.transform_dither(); @@ -172,7 +173,7 @@ impl GameBoard { if !(NON_ADJACENT.contains(s)) { continue; } - if *s == piece.get_kind() { + if *s == kind { continue; } diff --git a/src/bin/games/genius_square/models/pieces/models.rs b/src/bin/games/genius_square/models/pieces/models.rs index 1bf73e6..a0deed6 100644 --- a/src/bin/games/genius_square/models/pieces/models.rs +++ b/src/bin/games/genius_square/models/pieces/models.rs @@ -65,6 +65,11 @@ impl Piece { &self.positions } + #[allow(unused)] + pub fn set_positions(&mut self, positions: &BinArray) { + self.positions = positions.clone(); + } + #[allow(unused)] pub fn get_weight(&self) -> isize { self.positions.get_weight() From 1a43fcb667c282138db8ed79e9903c90bdf7ed33 Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 22:56:27 +0100 Subject: [PATCH 41/54] story-game-gs > staging: `bugfix` - corrected dithering --- .../genius_square/models/arrays/models.rs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/bin/games/genius_square/models/arrays/models.rs b/src/bin/games/genius_square/models/arrays/models.rs index ebc5439..29733e9 100644 --- a/src/bin/games/genius_square/models/arrays/models.rs +++ b/src/bin/games/genius_square/models/arrays/models.rs @@ -164,15 +164,14 @@ impl BinArray { pub fn transform_dither(&self) -> Self { let (m, n) = self.get_shape(); let coords = self.to_coords(); - let arr = BinArray::from_coords(coords, m + 2, n + 2); - arr.transform_shift(1, 1); - let arr1 = arr.transform_shift(-1, 0).to_owned(); - let arr2 = arr.transform_shift(1, 0).to_owned(); - let arr3 = arr.transform_shift(0, -1).to_owned(); - let arr4 = arr.transform_shift(0, 1).to_owned(); - let arr = arr + arr1 + arr2 + arr3 + arr4; + let mut arr = BinArray::from_coords(coords, m + 2, n + 2); + arr = arr.transform_shift(1, 1); + let arr1 = arr.transform_shift(-1, 0); + let arr2 = arr.transform_shift(1, 0); + let arr3 = arr.transform_shift(0, -1); + let arr4 = arr.transform_shift(0, 1); + arr = arr + arr1 + arr2 + arr3 + arr4; let values = arr.values - .mapv(|x| x.min(1)) .slice(slice![1..-1, 1..-1]) .to_owned(); let result = Self {m, n, values}; @@ -236,7 +235,8 @@ impl Add for BinArray { fn add(self, other: Self) -> Self::Output { let m = self.m; let n = self.n; - let values = self.values + other.values; + let mut values = self.values.to_owned() + other.values.to_owned(); + values = values.mapv(|x| x.min(1)); return Self {m, n, values}; } } @@ -247,7 +247,7 @@ impl Mul for BinArray { fn mul(self, other: Self) -> Self::Output { let m = self.m; let n = self.n; - let values = self.values * other.values; + let values = self.values.to_owned() * other.values.to_owned(); return Self {m, n, values}; } } From d78a3221dd3a30e68eb0688a916a68d1cd11d2a2 Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 23:24:01 +0100 Subject: [PATCH 42/54] story-game-gs > staging: added dependency --- Cargo.lock | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + 2 files changed, 212 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e9bb744..4b30973 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,6 +109,12 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + [[package]] name = "camino" version = "1.1.9" @@ -251,6 +257,19 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "console" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e09ced7ebbccb63b4c65413d821f2e00ce54c5ca4514ddc6b3c892fdbcbc69d" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width 0.2.1", + "windows-sys 0.60.2", +] + [[package]] name = "crc" version = "3.3.0" @@ -321,6 +340,12 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "env_home" version = "0.1.0" @@ -440,6 +465,7 @@ dependencies = [ "cargo-zigbuild", "dedent", "dict_derive", + "indicatif", "indoc", "itertools", "ndarray", @@ -458,7 +484,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" dependencies = [ - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -523,6 +549,19 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "indicatif" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a646d946d06bedbbc4cac4c218acf4bbf2d87757a784857025f4d447e4e1cd" +dependencies = [ + "console", + "portable-atomic", + "unicode-width 0.2.1", + "unit-prefix", + "web-time", +] + [[package]] name = "indoc" version = "2.0.6" @@ -550,6 +589,16 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "js-sys" +version = "0.3.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -1386,12 +1435,24 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-width" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" + [[package]] name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +[[package]] +name = "unit-prefix" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "323402cff2dd658f39ca17c789b502021b3f18707c91cdf22e3838e1b4023817" + [[package]] name = "utf8-ranges" version = "1.0.5" @@ -1428,6 +1489,74 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasm-bindgen" +version = "0.2.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb" +dependencies = [ + "bumpalo", + "log 0.4.27", + "proc-macro2", + "quote", + "syn 2.0.101", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "which" version = "7.0.3" @@ -1474,6 +1603,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + [[package]] name = "windows-sys" version = "0.48.0" @@ -1492,6 +1627,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -1516,13 +1660,30 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -1535,6 +1696,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -1547,6 +1714,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -1559,12 +1732,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -1577,6 +1762,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -1589,6 +1780,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -1601,6 +1798,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -1613,6 +1816,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" version = "0.7.10" diff --git a/Cargo.toml b/Cargo.toml index 6a6c481..ea392e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,7 @@ dict_derive = {version = "^0.6.0" } dedent = {version="^0.1.1"} itertools = {version = "^0.14.0"} indoc = {version="^2.0.6"} +indicatif = {version = "^0.18.0"} strip-ansi-escapes = {version="^0.2.1"} rand = {version="^0.9.2"} rand_chacha = {version = "^0.9.0"} From 3666fcafe7193a960e17bcae8a8daf2defffb14e Mon Sep 17 00:00:00 2001 From: raj-open Date: Thu, 4 Sep 2025 23:24:14 +0100 Subject: [PATCH 43/54] story-game-gs > staging: added progress bar --- .../games/genius_square/algorithms/solve.rs | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/bin/games/genius_square/algorithms/solve.rs b/src/bin/games/genius_square/algorithms/solve.rs index f9ab334..efd880e 100644 --- a/src/bin/games/genius_square/algorithms/solve.rs +++ b/src/bin/games/genius_square/algorithms/solve.rs @@ -2,6 +2,9 @@ /// IMPORTS /// ---------------------------------------------------------------- +use indicatif::ProgressBar; +use indicatif::ProgressStyle; + use crate::models::constants::enums::ENUM_PIECES; use crate::models::constants::enums::EnumPiece; use crate::models::pieces::models::Piece; @@ -16,7 +19,7 @@ pub fn solve_brute_force( board: &GameBoard, ) -> GameBoard { let obst = board.get_block().to_owned(); - match recursion(board, &obst, None) { + match recursion(board, &obst, None, None) { Some(board_) => { return board_; }, @@ -33,13 +36,34 @@ pub fn solve_brute_force( fn recursion( board: &GameBoard, obst: &Piece, - kinds: Option<&[EnumPiece]>, + option_kinds: Option<&[EnumPiece]>, + option_pbar: Option<&ProgressBar>, ) -> Option { - let kinds = kinds.unwrap_or(ENUM_PIECES); + let kinds = option_kinds.unwrap_or(ENUM_PIECES); + let n = kinds.len() as u64; - if kinds.len() == 0 { + let pbar0 = ProgressBar::new(n); + let pbar: &ProgressBar; + match option_pbar { + Some(pbar_) => { + pbar = &pbar_; + }, + None => { + pbar = &pbar0; + pbar.set_style( + ProgressStyle::with_template( + "{spinner:.white} [{elapsed_precise}] [{wide_bar:.white}] {pos}/{len} ({eta_precise})" + ) + .unwrap(), + ); + } + } + + if n == 0 { // if nothing left to solve, then return pieces, provide everything is filled if obst.get_coweight() == 0 { + pbar.finish_and_clear(); + println!("Completed in {:.2?}", pbar.elapsed()); return Some(board.to_owned()); } } else { @@ -48,6 +72,7 @@ fn recursion( let kinds = &kinds[1..]; let piece0 = Piece::from_kind(kind, None); // initialised piece for piece in board.get_configurations(&piece0, &obst) { + pbar.inc(1); // update the obstacle let obst_ = obst.clone() + piece.clone(); @@ -56,11 +81,14 @@ fn recursion( board_.add_piece(&kind.clone(), &piece); // compute remainder of solution recursively - match recursion(&mut board_, &obst_, Some(kinds)) { + match recursion(&mut board_, &obst_, Some(kinds), Some(&pbar)) { Some(board_) => { return Some(board_); }, - None => {}, + None => { + let k = pbar.position(); + pbar.set_position((k - 1).max(0)); + }, } } } From 021ff0204b7aac56b88f7cafbe540307f27fe821 Mon Sep 17 00:00:00 2001 From: raj-open Date: Fri, 5 Sep 2025 07:20:21 +0100 Subject: [PATCH 44/54] story-game-gs > staging: minor --- src/bin/games/genius_square/algorithms/solve.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/bin/games/genius_square/algorithms/solve.rs b/src/bin/games/genius_square/algorithms/solve.rs index efd880e..ba3a5cf 100644 --- a/src/bin/games/genius_square/algorithms/solve.rs +++ b/src/bin/games/genius_square/algorithms/solve.rs @@ -50,12 +50,8 @@ fn recursion( }, None => { pbar = &pbar0; - pbar.set_style( - ProgressStyle::with_template( - "{spinner:.white} [{elapsed_precise}] [{wide_bar:.white}] {pos}/{len} ({eta_precise})" - ) - .unwrap(), - ); + let style = ProgressStyle::with_template("{spinner:.white} [{elapsed_precise}] [{wide_bar:.white}] {pos}/{len} ({eta_precise})"); + pbar.set_style(style.unwrap()) } } From c6d820d544a083bee0771f64dd4718997e2c1390 Mon Sep 17 00:00:00 2001 From: raj-open Date: Fri, 5 Sep 2025 07:23:55 +0100 Subject: [PATCH 45/54] story-game-gs > staging: faster computation of coordinates + added negative + added anchor point --- .../genius_square/models/arrays/models.rs | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/bin/games/genius_square/models/arrays/models.rs b/src/bin/games/genius_square/models/arrays/models.rs index 29733e9..09a26b7 100644 --- a/src/bin/games/genius_square/models/arrays/models.rs +++ b/src/bin/games/genius_square/models/arrays/models.rs @@ -8,7 +8,6 @@ use std::fmt::Debug; use std::fmt::Display; use std::fmt::Formatter; use std::fmt::Result; - use std::ops::Add; use std::ops::Mul; use itertools::iproduct; @@ -41,28 +40,31 @@ impl BinArray { Self {m, n, values} } + /// Gets the list of co-ordinates of the entries which are non-zero pub fn to_coords(&self) -> Vec<(usize, usize)> { - let mut coords: Vec<(usize, usize)> = vec![]; - for (i, row) in self.values.rows().into_iter().enumerate() { - for (j, &val) in row.iter().enumerate() { - if val == 1 { - coords.push((i, j)); - } - } - } - return coords; + self.values + .indexed_iter() + .filter_map(|((i, j), &v)| if v == 0 { None } else { Some((i, j)) }) + .collect() + } + + /// Determines a single co-ordinate to be used as an anchor point. + /// If none exists, defaults to (0, 0). + pub fn get_anchor(&self) -> (usize, usize) { + self.values + .indexed_iter() + .find_or_first(|&(_, &v)| v != 0) + .map_or((0, 0), |((i, j), _)| (i, j)) } pub fn get_weight(&self) -> isize { - let values = self.values.mapv(|x| if x == 0 {0} else {1}); - let weight = values.sum(); - return weight; + self.values + .mapv(|x| if x == 0 {0} else {1}) + .sum() } pub fn get_coweight(&self) -> isize { - let covalues = self.values.mapv(|x| if x == 0 {1} else {0}); - let coweight = covalues.sum(); - return coweight; + self.transform_invert().get_weight() } pub fn get_shape(&self) -> (usize, usize) { @@ -84,6 +86,14 @@ impl BinArray { return result; } + /// Flips 0s and 1s + pub fn transform_invert(&self) -> Self { + let m = self.m; + let n = self.n; + let values = self.values.mapv(|x| if x == 0 {1} else {0}); + return Self {m, n, values}; + } + pub fn transform_shift( &self, di: isize, From 694d37fce17837aef9f4177902b9bbcf9a3cdbf9 Mon Sep 17 00:00:00 2001 From: raj-open Date: Fri, 5 Sep 2025 07:24:58 +0100 Subject: [PATCH 46/54] story-game-gs > staging: only consider shifts based on moving an anchor point to a free location --- .../genius_square/models/arrays/models.rs | 48 ++++++++++++++++--- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/src/bin/games/genius_square/models/arrays/models.rs b/src/bin/games/genius_square/models/arrays/models.rs index 09a26b7..a275087 100644 --- a/src/bin/games/genius_square/models/arrays/models.rs +++ b/src/bin/games/genius_square/models/arrays/models.rs @@ -11,6 +11,7 @@ use std::fmt::Result; use std::ops::Add; use std::ops::Mul; use itertools::iproduct; +use itertools::Itertools; /// ---------------------------------------------------------------- /// STRUCTS @@ -196,17 +197,23 @@ impl BinArray { /// - v- and h-shifts /// /// provided the moves preserve the "weight" of the shadow in the array - pub fn get_configurations(&self) -> impl Iterator { - let m = self.m as isize; - let n = self.n as isize; + /// and provided + /// + /// - no collisions occur with an optional obstacle. + pub fn get_configurations( + &self, + option_obst: Option<&BinArray>, + ) -> impl Iterator { + let (m, n) = self.get_shape(); + let obst = option_obst.map_or_else(|| BinArray::from_coords(vec![], m, n), |x| x.clone()); + let free = obst.transform_invert(); let iterator = iproduct!( [0, 1, -1], [false, true], [false, true], - (0.. m), - (0.. n), ) - .map(|(rot, vflip, hflip, di, dj)| { + // iterate through all orientations + .map(|(rot, vflip, hflip)| { // recover original let mut arr = self.clone(); if rot != 0 { @@ -221,13 +228,40 @@ impl BinArray { if hflip | vflip | (rot != 0) { arr = arr.recentre(); } - arr = arr.transform_shift(di, dj); return arr; }) + // by fixing an anchor point and viewing the non-occupied positions + // get all possible shifts of the array + .map(move |arr| { + // an anchor point of the piece + let (i0, j0) = arr.get_anchor(); + let i0 = i0 as isize; + let j0 = j0 as isize; + // all non-occupied points on gameboard + let shifts = free + .to_coords() + .iter() + .map(|&(i, j)| { + let di = (i as isize) - i0; + let dj = (j as isize) - j0; + let arr_ = arr.transform_shift(di, dj); + return arr_; + }) + .collect::>(); + return shifts; + }) + // since returned a vector of possibilities, need to flatten + .flatten() // if geometric operations shift shape off the grid, skip .filter(|arr| { let wt = self.get_weight(); return arr.get_weight() >= wt; + }) + // if geometric operations collide with obstacle, skip + .filter(move |arr| { + let collision = arr.to_owned() * obst.to_owned(); + let penalty = -collision.get_weight(); + return penalty >= 0; }); return iterator; } From 6a58a63e47497308b605bee919a2e45867dbef80 Mon Sep 17 00:00:00 2001 From: raj-open Date: Fri, 5 Sep 2025 07:25:30 +0100 Subject: [PATCH 47/54] story-game-gs > staging: moved collision detection for obstacle to get-configurations --- src/bin/games/genius_square/models/board/models.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/bin/games/genius_square/models/board/models.rs b/src/bin/games/genius_square/models/board/models.rs index 274c930..79be121 100644 --- a/src/bin/games/genius_square/models/board/models.rs +++ b/src/bin/games/genius_square/models/board/models.rs @@ -151,15 +151,8 @@ impl GameBoard { let it = piece // convert to positions .get_positions() - // get all possible moves - .get_configurations() - // skip all moves which collide with obstacle - .filter(|pos| { - let pos_obst = obst.get_positions(); - let collision = pos.to_owned() * pos_obst.to_owned(); - let penalty = -collision.get_weight(); - return penalty >= 0; - }) + // get all possible orientations + shifts which do not collide with obstacle + .get_configurations(Some(obst.get_positions())) // skip all moves which lead to forbidden adjacent pieces .filter(|pos| { // only need to check for collisions of pieces of a paritcular kind From 5d24d1e695001ffb1ff250f3c331d1f1da7abbef Mon Sep 17 00:00:00 2001 From: raj-open Date: Fri, 5 Sep 2025 07:39:40 +0100 Subject: [PATCH 48/54] story-game-gs > staging: removed superfluous recentring this is superfluous, since we shift based on an anchor point --- src/bin/games/genius_square/models/arrays/models.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/bin/games/genius_square/models/arrays/models.rs b/src/bin/games/genius_square/models/arrays/models.rs index a275087..1208bec 100644 --- a/src/bin/games/genius_square/models/arrays/models.rs +++ b/src/bin/games/genius_square/models/arrays/models.rs @@ -225,9 +225,10 @@ impl BinArray { if hflip { arr = arr.transform_hflip(false); } - if hflip | vflip | (rot != 0) { - arr = arr.recentre(); - } + // NOTE: No longer need this as anchor point will be shifted + // if hflip | vflip | (rot != 0) { + // arr = arr.recentre(); + // } return arr; }) // by fixing an anchor point and viewing the non-occupied positions From d187c96861d8c3bf7d7d4e1390083f0608d77135 Mon Sep 17 00:00:00 2001 From: raj-open Date: Fri, 5 Sep 2025 07:42:37 +0100 Subject: [PATCH 49/54] story-game-gs > staging: removed magic number --- src/bin/games/genius_square/main.rs | 3 ++- src/bin/games/genius_square/models/constants/dice.rs | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bin/games/genius_square/main.rs b/src/bin/games/genius_square/main.rs index 4812415..760e790 100644 --- a/src/bin/games/genius_square/main.rs +++ b/src/bin/games/genius_square/main.rs @@ -11,6 +11,7 @@ mod algorithms; mod models; mod features; +use models::constants::dice::NUM_DICE; use features::setup_game::feature_setup_game; /// ---------------------------------------------------------------- @@ -19,7 +20,7 @@ use features::setup_game::feature_setup_game; fn main() { let args: Vec = env::args().skip(1).collect(); - let option_roll = if args.len() >= 7 { Some(args[0..7].to_vec()) } else { None }; + let option_roll = if args.len() >= NUM_DICE { Some(args[0..NUM_DICE].to_vec()) } else { None }; let option_seed = if args.len() >= 1 { Some(args[args.len() - 1].clone()) } else { None }; let mut rng = _core::rand::seed_rng(option_seed); welcome_screen(); diff --git a/src/bin/games/genius_square/models/constants/dice.rs b/src/bin/games/genius_square/models/constants/dice.rs index 5f8a492..e2c50a9 100644 --- a/src/bin/games/genius_square/models/constants/dice.rs +++ b/src/bin/games/genius_square/models/constants/dice.rs @@ -53,3 +53,5 @@ pub const DICE: &[&[&str]] = &[ &["B4","C3","C4","D3","D4","E3"], &["A4","B5","C5","C6","D6","F6"], ]; + +pub const NUM_DICE: usize = DICE.len(); From 7f605d052263ff7aa8fba34ca155c10528b8f357 Mon Sep 17 00:00:00 2001 From: raj-open Date: Fri, 5 Sep 2025 08:00:52 +0100 Subject: [PATCH 50/54] story-game-gs > staging: minor --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ea392e6..0566c02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,7 +79,7 @@ name = "CodeChallenges" path = "src/main.rs" [[bin]] -name = "HackerRankMathematiks" +name = "HackerRankMathematics" path = "src/problems/hackerrank/mathematics/main.rs" [[bin]] From f535bcbb580fd9735a8a7f5aa117e06cb4cd32e8 Mon Sep 17 00:00:00 2001 From: raj-open Date: Fri, 5 Sep 2025 08:05:39 +0100 Subject: [PATCH 51/54] story-game-gs > staging: added Binaries to README --- README.md | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/README.md b/README.md index 82cd8e1..ca3ea8a 100644 --- a/README.md +++ b/README.md @@ -83,3 +83,128 @@ just tests-unit The `tests` folder contains integration tests for rust code, and unit tests for python code. + +## Execution of Binaries ## + +This repository contains some binaries (see [Cargo.toml](./Cargo.toml)): + +- `CodeChallenges` +- `HackerRankMathematics` +- `GeniusSquare` + +To run a binary call + +```bash +# runs with optimisation (slower compile time) +just run-rust {NAME_OF_BINARY} [flags] +# runs without optimisation (faster compile time, slower run time) +just dev-rust {NAME_OF_BINARY} [flags] +``` + +### Genius Squares ### + +The binary `GeniusSquare` solves instances of +the _Smart Games_ puzzle [Genius Square](https://smarttoysandgames.co.uk/uk/genius-square). +Usage is as follows: + +```bash +# provides random instance of the puzzle and solves it: +just run-rust GeniusSquare +# ... with random seeding for repeatability: +just run-rust GeniusSquare {Seed} +# solves an instance of the game for a particular initialisation (roll of the dice): +just run-rust GeniusSquare {Dice1} {Dice2} ... {Dice7} +``` + +e.g. + +```bash +just run-rust GeniusSquare 1234 # with random seed +just run-rust GeniusSquare B1 C4 D6 F1 F2 F3 F5 # with given initialisation +``` + +The `run` command builds and runs the binary. +To perform this separately, use + +```bash +just build-compile GeniusSquare +``` + +which produces the binary in [target/release/GeniusSquare](target/release/GeniusSquare). +The standalone binary can be called as above: + +```bash +./target/release/GeniusSquare +# with random seed +./target/release/GeniusSquare {Seed} +./target/release/GeniusSquare 1234 +# with given initialisation +./target/release/GeniusSquare {Dice1} {Dice2} ... {Dice7} +./target/release/GeniusSquare B1 C4 D6 F1 F2 F3 F5 +``` + +#### Example #### + +Calling + +```bash +just run-rust GeniusSquare B1 C4 D6 F1 F2 F3 F5 +``` + +results in + +```bash +Roll: B1, C4, D6, F1, F2, F3, F5. + + +Problem: +╔═══╦═══╤═══╤═══╤═══╤═══╤═══╕ +║ ║ A │ B │ C │ D │ E │ F │ +╠═══╬═══╪═══╪═══╪═══╪═══╪═══╡ +║ 1 ║ │ ■ │ │ │ │ ■ │ +╠───╬───┼───┼───┼───┼───┼───┤ +║ 2 ║ │ │ │ │ │ ■ │ +╠───╬───┼───┼───┼───┼───┼───┤ +║ 3 ║ │ │ │ │ │ ■ │ +╠───╬───┼───┼───┼───┼───┼───┤ +║ 4 ║ │ │ ■ │ │ │ │ +╠───╬───┼───┼───┼───┼───┼───┤ +║ 5 ║ │ │ │ │ │ ■ │ +╠───╬───┼───┼───┼───┼───┼───┤ +║ 6 ║ │ │ │ ■ │ │ │ +╙───╨───┴───┴───┴───┴───┴───┘ + +Compute solution... + +...completed in 725.18ms + +Solution: +╔═══╦═══╤═══╤═══╤═══╤═══╤═══╕ +║ ║ A │ B │ C │ D │ E │ F │ +╠═══╬═══╪═══╪═══╪═══╪═══╪═══╡ +║ 1 ║ 1 │ ■ │ 2 │ 2 │ Z │ ■ │ +╠───╬───┼───┼───┼───┼───┼───┤ +║ 2 ║ L │ X │ X │ Z │ Z │ ■ │ +╠───╬───┼───┼───┼───┼───┼───┤ +║ 3 ║ L │ X │ X │ Z │ T │ ■ │ +╠───╬───┼───┼───┼───┼───┼───┤ +║ 4 ║ L │ L │ ■ │ T │ T │ T │ +╠───╬───┼───┼───┼───┼───┼───┤ +║ 5 ║ 4 │ 4 │ 4 │ 4 │ C │ ■ │ +╠───╬───┼───┼───┼───┼───┼───┤ +║ 6 ║ 3 │ 3 │ 3 │ ■ │ C │ C │ +╙───╨───┴───┴───┴───┴───┴───┘ +``` + +in the console. +The solver currently relies on a brute force tree-search algorithm, +and provides solutions at the `Wizard` level, +viz. no collisions occur and none of the pieces + +```text +1 2 3 CC + 2 3 C + 3 +``` + +are adjacent (in the sense of touching edges). From 9f8a4dd99f30079a38f0e7a3f400011c5bc49798 Mon Sep 17 00:00:00 2001 From: raj-open Date: Fri, 5 Sep 2025 08:34:50 +0100 Subject: [PATCH 52/54] story-game-gs > staging: improved logging/representation of game board --- .../games/genius_square/algorithms/solve.rs | 2 +- .../genius_square/features/setup_game.rs | 2 +- .../genius_square/models/board/models.rs | 26 ++++++++++++------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/bin/games/genius_square/algorithms/solve.rs b/src/bin/games/genius_square/algorithms/solve.rs index ba3a5cf..89e6eae 100644 --- a/src/bin/games/genius_square/algorithms/solve.rs +++ b/src/bin/games/genius_square/algorithms/solve.rs @@ -59,7 +59,7 @@ fn recursion( // if nothing left to solve, then return pieces, provide everything is filled if obst.get_coweight() == 0 { pbar.finish_and_clear(); - println!("Completed in {:.2?}", pbar.elapsed()); + println!("...completed in {:.2?}", pbar.elapsed()); return Some(board.to_owned()); } } else { diff --git a/src/bin/games/genius_square/features/setup_game.rs b/src/bin/games/genius_square/features/setup_game.rs index 2c359cf..d3d85f3 100644 --- a/src/bin/games/genius_square/features/setup_game.rs +++ b/src/bin/games/genius_square/features/setup_game.rs @@ -30,7 +30,7 @@ pub fn feature_setup_game( let coords = dice.iter().map(|die| die.to_coords()).collect(); let block = Piece::from_coords(coords, Some(EnumPiece::Block)); let mut board = GameBoard::new(&block); - println!("\nProblem:\n{}\n", board.pretty()); + println!("\nProblem:\n{}", board.pretty()); // Solve the problem println!("\nCompute solution...\n"); diff --git a/src/bin/games/genius_square/models/board/models.rs b/src/bin/games/genius_square/models/board/models.rs index 79be121..c0cc9e1 100644 --- a/src/bin/games/genius_square/models/board/models.rs +++ b/src/bin/games/genius_square/models/board/models.rs @@ -66,18 +66,26 @@ impl GameBoard { let n = GRID_WIDTH; let field = self.to_array_of_strings(true); - fn create_border(lcorder: &str, fill: &str, mid: &str, rcorner: &str, n: usize) -> String { - let middle = format!("{fill}{mid}{fill}{fill}").repeat(n); - format!("{lcorder}{fill}{fill}{middle}{fill}{rcorner}") + fn create_border( + lcorner1: &str, + fill1: &str, + lcorner2: &str, + fill2: &str, + mid2: &str, + rcorner: &str, + n: usize, + ) -> String { + let middle = format!("{fill2}{mid2}{fill2}{fill2}").repeat(n-1); + format!("{lcorner1}{fill1}{fill1}{fill1}{lcorner2}{fill2}{fill2}{middle}{fill2}{rcorner}") } - let top1 = create_border("\u{2552}", "\u{2550}", "\u{2564}", "\u{2555}", n); - let top2 = create_border("\u{255E}", "\u{2550}", "\u{256A}", "\u{2561}", n); - let mid = create_border("\u{251C}", "\u{2500}", "\u{253C}", "\u{2524}", n); - let bot = create_border("\u{2558}", "\u{2550}", "\u{2567}", "\u{255B}", n); + let top1 = create_border("\u{02554}", "\u{2550}", "\u{02566}", "\u{2550}", "\u{2564}", "\u{2555}", n); + let top2 = create_border("\u{02560}", "\u{2550}", "\u{0256C}", "\u{2550}", "\u{256A}", "\u{2561}", n); + let mid = create_border("\u{02560}", "\u{2500}", "\u{0256C}", "\u{2500}", "\u{253C}", "\u{2524}", n); + let bot = create_border("\u{02559}", "\u{2500}", "\u{02568}", "\u{2500}", "\u{02534}", "\u{02518}", n); let head = FACE1_FMT.join(" \u{2502} ").to_string(); - let head = format!("{top1}\n\u{2502} \u{2502} {head} \u{2502}\n{top2}"); + let head = format!("{top1}\n\u{02551} \u{02551} {head} \u{2502}\n{top2}"); let middle = field.rows() .into_iter() @@ -85,7 +93,7 @@ impl GameBoard { .map(|(i, row)| { let index = FACE2_FMT[i]; let line = row.iter().map(|s| s.to_string()).collect::>().join(" \u{2502} "); - return format!("\u{2502} {index} \u{2502} {line} \u{2502}"); + return format!("\u{02551} {index} \u{02551} {line} \u{2502}"); }) .collect::>() .join(format!("\n{mid}\n").as_str()); From 21f0cccfde0f3d93eecaa98e9b2e05a547d567c6 Mon Sep 17 00:00:00 2001 From: raj-open Date: Fri, 5 Sep 2025 08:39:59 +0100 Subject: [PATCH 53/54] story-game-gs > staging: corrected environment --- .github/workflows/auto.yaml | 2 +- .github/workflows/manual.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/auto.yaml b/.github/workflows/auto.yaml index e156e95..8ec323c 100644 --- a/.github/workflows/auto.yaml +++ b/.github/workflows/auto.yaml @@ -85,7 +85,7 @@ jobs: touch .env && rm .env echo " - MAIN_MODULE="code-challenges" + MAIN_MODULE="CodeChallenges" PYTHON_PATH="python${{ env.PYTHON_VERSION }}" ARCHITECTURE="${{ env.ARCHITECTURE }}" RUST_BACKTRACE=full diff --git a/.github/workflows/manual.yaml b/.github/workflows/manual.yaml index fa2d0ff..c3f7675 100644 --- a/.github/workflows/manual.yaml +++ b/.github/workflows/manual.yaml @@ -83,7 +83,7 @@ jobs: touch .env && rm .env echo " - MAIN_MODULE="code-challenges" + MAIN_MODULE="CodeChallenges" PYTHON_PATH="python${{ env.PYTHON_VERSION }}" ARCHITECTURE="${{ env.ARCHITECTURE }}" RUST_BACKTRACE=full From 36c57432f49d97b570de5399df815d574a7c887e Mon Sep 17 00:00:00 2001 From: raj-open Date: Fri, 5 Sep 2025 08:46:18 +0100 Subject: [PATCH 54/54] staging > main: VERSION bump (minor) --- Cargo.lock | 2 +- Cargo.toml | 2 +- dist/VERSION | 2 +- pyproject.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4b30973..92af14d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -460,7 +460,7 @@ dependencies = [ [[package]] name = "general" -version = "0.1.0" +version = "0.2.0" dependencies = [ "cargo-zigbuild", "dedent", diff --git a/Cargo.toml b/Cargo.toml index 0566c02..85a5fcc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "general" -version = "0.1.0" +version = "0.2.0" edition = "2024" description = "Code for challenges from various platforms" homepage = "github.com/raj-open/code-challenges" diff --git a/dist/VERSION b/dist/VERSION index 77d6f4c..0ea3a94 100644 --- a/dist/VERSION +++ b/dist/VERSION @@ -1 +1 @@ -0.0.0 +0.2.0 diff --git a/pyproject.toml b/pyproject.toml index 9a5fb39..184aee3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = 'code_challenges' -version = "0.1.0" +version = "0.2.0" description = 'Code for challenges from various platforms' authors = [ {name="raj-open", email="raj-open@users.noreply.github.com"},