From 539e6201b82f20438f6f31e312cda767301e68c7 Mon Sep 17 00:00:00 2001 From: Tom Milligan Date: Fri, 5 Apr 2019 22:45:59 +0100 Subject: [PATCH] add alternate ramp bigint backend --- Cargo.lock | 135 ++++++++++++++++++++++++++++++ Cargo.toml | 8 +- Makefile | 8 +- README.md | 12 +++ src/backend/backend_num_bigint.rs | 48 +++++++++++ src/backend/backend_ramp.rs | 48 +++++++++++ src/backend/mod.rs | 28 +++++++ src/combinations_wr.rs | 2 +- src/lib.rs | 60 +------------ test/check | 14 ++++ 10 files changed, 302 insertions(+), 61 deletions(-) create mode 100644 src/backend/backend_num_bigint.rs create mode 100644 src/backend/backend_ramp.rs create mode 100644 src/backend/mod.rs create mode 100755 test/check diff --git a/Cargo.lock b/Cargo.lock index bac37b2..8ed6ecc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "adler32" version = "1.0.3" @@ -63,6 +65,11 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cc" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cfg-if" version = "0.1.7" @@ -82,6 +89,14 @@ dependencies = [ "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "deflate" version = "0.7.19" @@ -103,6 +118,11 @@ dependencies = [ "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "glib" version = "0.7.1" @@ -134,6 +154,11 @@ dependencies = [ "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hamming" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "humantime" version = "1.2.0" @@ -142,6 +167,11 @@ dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ieee754" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "inflate" version = "0.4.5" @@ -186,9 +216,21 @@ dependencies = [ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ramp 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-bigint" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-bigint" version = "0.2.2" @@ -215,6 +257,14 @@ dependencies = [ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-traits" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-traits" version = "0.2.6" @@ -249,6 +299,66 @@ name = "quick-error" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ramp" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "hamming 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ieee754 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-cfg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_syscall" version = "0.1.51" @@ -282,6 +392,16 @@ dependencies = [ "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-cfg" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "strsim" version = "0.7.0" @@ -394,31 +514,46 @@ dependencies = [ "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cairo-rs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e09d8a818b2ccc8983f04d95a9350c3cf8d24cc456cedca3b88fa3a81fdc0e2" "checksum cairo-sys-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fa13914fdc013387afa771f554f2f71d6ae931f4e5be9246c337d60c3dc484" +"checksum cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "30f813bf45048a18eda9190fd3c6b78644146056740c43172a5a3699118588fd" "checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86" "checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum glib 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e8fdc159c196a5dfa53a92929ac4c10c8a6637ffb43951f3fff89c2cd2365" "checksum glib-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5bda542f3caee39a027638e9644ff89204101ad916fd7370b585ad2c5fc97e61" "checksum gobject-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23e05a14290d3dc255223cba51db4b0f3da438d5250657996fa99b2a30faf43e" +"checksum hamming 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" +"checksum ieee754 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9007da9cacbd3e6343da136e98b0d2df013f553d35bdec8b518f07bea768e19c" "checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" +"checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" "checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" +"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9adebf7fb91ccf5eac9da1a8e00e83cb8ae882c3e8d8e4ad59da73cb8c82a2c9" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum ramp 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0ca970d0666c000527f44cfdb4d6c3490e53417b9806166463a4d68b88a950ce" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2faa04d391c92f3d7d3207dc7eec10e52ae663ca70f282044ce6f735a17d62e0" "checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" +"checksum rustc-cfg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37937dfed502ccc4e644c3cc272222e31adc2b1f5d215f6f8f8e1a422072e516" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" diff --git a/Cargo.toml b/Cargo.toml index 883e67a..f20b284 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,15 +4,21 @@ version = "0.1.0" authors = ["Tom Milligan "] edition = "2018" +[features] +backend-num = ["num-bigint"] +backend-ramp = ["ramp"] +default = ["backend-num"] + [dependencies] cairo-rs = { version = "0.6.0", features = ["png"] } clap = "^2.32.0" env_logger = "^0.6.1" lazy_static = "^1.3.0" log = "^0.4.6" -num-bigint = "^0.2.2" +num-bigint = { version = "^0.2.2", optional = true } num-traits = "^0.2.6" num_cpus = "^1.10.0" png = "0.14.0" +ramp = { version = "0.5.1", optional = true } threadpool = "^1.7.1" diff --git a/Makefile b/Makefile index d597d3d..dac9088 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,15 @@ -.PHONY: dev integrate test +.PHONY: build-ramp dev integrate test + +build-ramp: + cargo +nightly build --no-default-features --features backend-ramp dev: rustup component add rustfmt + rustup toolchain install nightly integrate: ./integrate/check test: cargo fmt -- --check - cargo test --locked + ./test/check diff --git a/README.md b/README.md index e292542..94016f1 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,18 @@ Search for integers with high multiplicative persistence values. This project uses the standard `rustup` and `cargo` toolchain. Originally tested against `rustc 1.33.0`. +By default the library uses `num-bigint` internally. This can be swapped for `ramp` as a dependency by specifying: + +``` +multiplicative-persistence = { version = "*", features = ["backend-ramp"], default-features = false } +``` + +Or as a binary by building with: + +```bash +cargo +nightly build --no-default-features --features backend-ramp +``` + ## Usage Build binaries with `cargo build --release --bins`, they will be output in `target/release`: diff --git a/src/backend/backend_num_bigint.rs b/src/backend/backend_num_bigint.rs new file mode 100644 index 0000000..97f60b1 --- /dev/null +++ b/src/backend/backend_num_bigint.rs @@ -0,0 +1,48 @@ +extern crate num_bigint; +extern crate num_traits; + +use num_bigint::BigUint; +use num_traits::Num; + +lazy_static! { + static ref BIG_UINT_NINE: BigUint = BigUint::from(9 as usize); +} + +/// Multiply digits of an integer together and return the result. +fn multiply_digits(a: &BigUint) -> BigUint { + a.to_str_radix(10) + .chars() + .map(|c| BigUint::from(c.to_digit(10).expect("Could not convert char to digit."))) + .product() +} + +/// Return the multiplicative persistence of a positive integer given as a string. +pub fn multiplicative_persistence(candidate: &str) -> usize { + let mut derived_int: BigUint = + Num::from_str_radix(candidate, 10).expect("Could not convert candidate to BigUint"); + + let mut counter: usize = 0; + while derived_int > *BIG_UINT_NINE { + derived_int = multiply_digits(&derived_int); + counter += 1; + } + counter +} + +#[cfg(test)] +mod test { + use super::*; + + /// Test helper to cut down on boilerplate + fn big(n: usize) -> BigUint { + BigUint::from(n) + } + + #[test] + fn test_multiply_digits() { + assert_eq!(multiply_digits(&big(0)), big(0)); + assert_eq!(multiply_digits(&big(3)), big(3)); + assert_eq!(multiply_digits(&big(24)), big(8)); + assert_eq!(multiply_digits(&big(12345)), big(120)); + } +} diff --git a/src/backend/backend_ramp.rs b/src/backend/backend_ramp.rs new file mode 100644 index 0000000..da0c37d --- /dev/null +++ b/src/backend/backend_ramp.rs @@ -0,0 +1,48 @@ +extern crate ramp; + +use std::ops::Mul; + +use ramp::Int; + +lazy_static! { + static ref RAMP_NINE: Int = Int::from(9); +} + +/// Multiply digits of an integer together and return the result. +fn multiply_digits(a: &Int) -> Int { + a.to_str_radix(10, false) + .chars() + .map(|c| Int::from(c.to_digit(10).expect("Could not convert char to digit."))) + .fold(Int::one(), Int::mul) +} + +/// Return the multiplicative persistence of a positive integer given as a string. +pub fn multiplicative_persistence(candidate: &str) -> usize { + let mut derived_int = + Int::from_str_radix(candidate, 10).expect("Could not convert candidate to BigUint"); + + let mut counter: usize = 0; + while derived_int > *RAMP_NINE { + derived_int = multiply_digits(&derived_int); + counter += 1; + } + counter +} + +#[cfg(test)] +mod test { + use super::*; + + /// Test helper to cut down on boilerplate + fn big(n: usize) -> Int { + Int::from(n) + } + + #[test] + fn test_multiply_digits() { + assert_eq!(multiply_digits(&big(0)), big(0)); + assert_eq!(multiply_digits(&big(3)), big(3)); + assert_eq!(multiply_digits(&big(24)), big(8)); + assert_eq!(multiply_digits(&big(12345)), big(120)); + } +} diff --git a/src/backend/mod.rs b/src/backend/mod.rs new file mode 100644 index 0000000..289b716 --- /dev/null +++ b/src/backend/mod.rs @@ -0,0 +1,28 @@ +#[cfg(feature = "backend-num")] +pub mod backend_num_bigint; +#[cfg(feature = "backend-ramp")] +pub mod backend_ramp; + +#[cfg(feature = "backend-num")] +pub use backend_num_bigint::multiplicative_persistence; +#[cfg(feature = "backend-ramp")] +pub use backend_ramp::multiplicative_persistence; + +#[cfg(test)] +mod test { + use super::*; + + // Over 64-bit integer + const TOO_LARGE_INT: &'static str = + "12346789123467891234678912346789123467891234678912346789123467891234678912346789123467891234678912346789123467891234678912346789"; + + #[test] + fn test_multiplicative_persistence() { + assert_eq!(multiplicative_persistence("0"), 0); + assert_eq!(multiplicative_persistence("3"), 0); + assert_eq!(multiplicative_persistence("24"), 1); + assert_eq!(multiplicative_persistence("39"), 3); + assert_eq!(multiplicative_persistence(&TOO_LARGE_INT), 2); + } + +} diff --git a/src/combinations_wr.rs b/src/combinations_wr.rs index 46e2f2b..9d129e5 100644 --- a/src/combinations_wr.rs +++ b/src/combinations_wr.rs @@ -78,7 +78,7 @@ impl Iterator for CombinationsWithReplacement { } #[cfg(test)] -mod tests { +mod test { use super::*; #[test] diff --git a/src/lib.rs b/src/lib.rs index 2550703..06fc2f8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,42 +1,14 @@ #[macro_use] extern crate lazy_static; -extern crate num_bigint; -extern crate num_traits; - -use num_bigint::BigUint; -use num_traits::Num; +pub mod backend; pub mod combinations_wr; +pub use backend::multiplicative_persistence; use combinations_wr::CombinationsWithReplacement; static DIGITS_HEAD: &'static [&'static str; 4] = &["", "2", "3", "4"]; static DIGITS_TAIL: &'static [char; 4] = &['6', '7', '8', '9']; -lazy_static! { - static ref BIG_UINT_NINE: BigUint = BigUint::from(9 as usize); -} - -/// Multiply digits of an integer together and return the result. -fn multiply_digits(a: &BigUint) -> BigUint { - a.to_str_radix(10) - .chars() - .map(|c| BigUint::from(c.to_digit(10).expect("Could not convert char to digit."))) - .product() -} - -/// Return the multiplicative persistence of a positive integer given as a string. -pub fn multiplicative_persistence(candidate: &str) -> usize { - let mut derived_int: BigUint = - Num::from_str_radix(candidate, 10).expect("Could not convert candidate to BigUint"); - - let mut counter: usize = 0; - while derived_int > *BIG_UINT_NINE { - derived_int = multiply_digits(&derived_int); - counter += 1; - } - counter -} - #[derive(Debug, PartialEq)] pub struct SearchResult { pub candidate: String, @@ -140,35 +112,9 @@ impl<'a> Iterator for SearchRound<'a> { } #[cfg(test)] -mod tests { +mod test { use super::*; - /// Test helper to cut down on boilerplate - fn big(n: usize) -> BigUint { - BigUint::from(n) - } - - // Over 64-bit integer - const TOO_LARGE_INT: &'static str = - "12346789123467891234678912346789123467891234678912346789123467891234678912346789123467891234678912346789123467891234678912346789"; - - #[test] - fn test_multiplicative_persistence() { - assert_eq!(multiplicative_persistence("0"), 0); - assert_eq!(multiplicative_persistence("3"), 0); - assert_eq!(multiplicative_persistence("24"), 1); - assert_eq!(multiplicative_persistence("39"), 3); - assert_eq!(multiplicative_persistence(&TOO_LARGE_INT), 2); - } - - #[test] - fn test_multiply_digits() { - assert_eq!(multiply_digits(&big(0)), big(0)); - assert_eq!(multiply_digits(&big(3)), big(3)); - assert_eq!(multiply_digits(&big(24)), big(8)); - assert_eq!(multiply_digits(&big(12345)), big(120)); - } - #[test] fn test_candidates() { let candidates: Vec = Candidates::new(1).collect(); diff --git a/test/check b/test/check new file mode 100755 index 0000000..bf0e70a --- /dev/null +++ b/test/check @@ -0,0 +1,14 @@ +#!/bin/bash + +set -ex + +log() { + echo $@ 1>&2 +} + +TEST="test --locked" +RAMP_BACKEND="--no-default-features --features backend-ramp" + +cargo $TEST +cargo +nightly $TEST $RAMP_BACKEND +