From 9624356fec3bc4161899c1824bd76c2f7ca534a8 Mon Sep 17 00:00:00 2001 From: Rorik Star Platinum Date: Thu, 11 Dec 2025 01:02:04 +0300 Subject: [PATCH] comptime sieve --- rust/prime-factors/.exercism/config.json | 36 ++++++ rust/prime-factors/.gitignore | 2 + rust/prime-factors/Cargo.toml | 9 ++ rust/prime-factors/HELP.md | 89 ++++++++++++++ rust/prime-factors/README.md | 68 +++++++++++ rust/prime-factors/src/lib.rs | 3 + rust/prime-factors/tests/prime_factors.rs | 96 +++++++++++++++ rust/sieve/.exercism/config.json | 37 ++++++ rust/sieve/.gitignore | 2 + rust/sieve/Cargo.toml | 9 ++ rust/sieve/HELP.md | 89 ++++++++++++++ rust/sieve/README.md | 142 ++++++++++++++++++++++ rust/sieve/src/lib.rs | 52 ++++++++ rust/sieve/tests/sieve.rs | 51 ++++++++ 14 files changed, 685 insertions(+) create mode 100644 rust/prime-factors/.exercism/config.json create mode 100644 rust/prime-factors/.gitignore create mode 100644 rust/prime-factors/Cargo.toml create mode 100644 rust/prime-factors/HELP.md create mode 100644 rust/prime-factors/README.md create mode 100644 rust/prime-factors/src/lib.rs create mode 100644 rust/prime-factors/tests/prime_factors.rs create mode 100644 rust/sieve/.exercism/config.json create mode 100644 rust/sieve/.gitignore create mode 100644 rust/sieve/Cargo.toml create mode 100644 rust/sieve/HELP.md create mode 100644 rust/sieve/README.md create mode 100644 rust/sieve/src/lib.rs create mode 100644 rust/sieve/tests/sieve.rs diff --git a/rust/prime-factors/.exercism/config.json b/rust/prime-factors/.exercism/config.json new file mode 100644 index 0000000..d8ab1c7 --- /dev/null +++ b/rust/prime-factors/.exercism/config.json @@ -0,0 +1,36 @@ +{ + "authors": [ + "sacherjj" + ], + "contributors": [ + "attilahorvath", + "coriolinus", + "cwhakes", + "eddyp", + "efx", + "ErikSchierboom", + "lutostag", + "nathanielknight", + "nfiles", + "petertseng", + "rofrol", + "stringparser", + "xakon", + "ZapAnton" + ], + "files": { + "solution": [ + "src/lib.rs", + "Cargo.toml" + ], + "test": [ + "tests/prime_factors.rs" + ], + "example": [ + ".meta/example.rs" + ] + }, + "blurb": "Compute the prime factors of a given natural number.", + "source": "The Prime Factors Kata by Uncle Bob", + "source_url": "https://web.archive.org/web/20221026171801/http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata" +} diff --git a/rust/prime-factors/.gitignore b/rust/prime-factors/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/rust/prime-factors/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/rust/prime-factors/Cargo.toml b/rust/prime-factors/Cargo.toml new file mode 100644 index 0000000..0c8df82 --- /dev/null +++ b/rust/prime-factors/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "prime_factors" +version = "0.1.0" +edition = "2024" + +# Not all libraries from crates.io are available in Exercism's test runner. +# The full list of available libraries is here: +# https://github.com/exercism/rust-test-runner/blob/main/local-registry/Cargo.toml +[dependencies] diff --git a/rust/prime-factors/HELP.md b/rust/prime-factors/HELP.md new file mode 100644 index 0000000..22a6c00 --- /dev/null +++ b/rust/prime-factors/HELP.md @@ -0,0 +1,89 @@ +# Help + +## Running the tests + +Execute the tests with: + +```bash +$ cargo test +``` + +All but the first test have been ignored. After you get the first test to +pass, open the tests source file which is located in the `tests` directory +and remove the `#[ignore]` flag from the next test and get the tests to pass +again. Each separate test is a function with `#[test]` flag above it. +Continue, until you pass every test. + +If you wish to run _only ignored_ tests without editing the tests source file, use: + +```bash +$ cargo test -- --ignored +``` + +If you are using Rust 1.51 or later, you can run _all_ tests with + +```bash +$ cargo test -- --include-ignored +``` + +To run a specific test, for example `some_test`, you can use: + +```bash +$ cargo test some_test +``` + +If the specific test is ignored, use: + +```bash +$ cargo test some_test -- --ignored +``` + +To learn more about Rust tests refer to the online [test documentation][rust-tests]. + +[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html + +## Submitting your solution + +You can submit your solution using the `exercism submit src/lib.rs Cargo.toml` command. +This command will upload your solution to the Exercism website and print the solution page's URL. + +It's possible to submit an incomplete solution which allows you to: + +- See how others have completed the exercise +- Request help from a mentor + +## Need to get help? + +If you'd like help solving the exercise, check the following pages: + +- The [Rust track's documentation](https://exercism.org/docs/tracks/rust) +- The [Rust track's programming category on the forum](https://forum.exercism.org/c/programming/rust) +- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5) +- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs) + +Should those resources not suffice, you could submit your (incomplete) solution to request mentoring. + +## Rust Installation + +Refer to the [exercism help page][help-page] for Rust installation and learning +resources. + +## Submitting the solution + +Generally you should submit all files in which you implemented your solution (`src/lib.rs` in most cases). If you are using any external crates, please consider submitting the `Cargo.toml` file. This will make the review process faster and clearer. + +## Feedback, Issues, Pull Requests + +Head to [the forum](https://forum.exercism.org/c/programming/rust/) and create a post to provide feedback about an exercise or if you want to help implement new exercises. +Members of the rust track team are happy to help! + +The GitHub [track repository][github] is the home for all of the Rust exercises. + +If you want to know more about Exercism, take a look at the [contribution guide]. + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. + +[help-page]: https://exercism.org/tracks/rust/learning +[github]: https://github.com/exercism/rust +[contribution guide]: https://exercism.org/docs/community/contributors \ No newline at end of file diff --git a/rust/prime-factors/README.md b/rust/prime-factors/README.md new file mode 100644 index 0000000..1d530ed --- /dev/null +++ b/rust/prime-factors/README.md @@ -0,0 +1,68 @@ +# Prime Factors + +Welcome to Prime Factors on Exercism's Rust Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Instructions + +Compute the prime factors of a given natural number. + +A prime number is only evenly divisible by itself and 1. + +Note that 1 is not a prime number. + +## Example + +What are the prime factors of 60? + +- Our first divisor is 2. + 2 goes into 60, leaving 30. +- 2 goes into 30, leaving 15. + - 2 doesn't go cleanly into 15. + So let's move on to our next divisor, 3. +- 3 goes cleanly into 15, leaving 5. + - 3 does not go cleanly into 5. + The next possible factor is 4. + - 4 does not go cleanly into 5. + The next possible factor is 5. +- 5 does go cleanly into 5. +- We're left only with 1, so now, we're done. + +Our successful divisors in that computation represent the list of prime factors of 60: 2, 2, 3, and 5. + +You can check this yourself: + +```text +2 * 2 * 3 * 5 += 4 * 15 += 60 +``` + +Success! + +## Source + +### Created by + +- @sacherjj + +### Contributed to by + +- @attilahorvath +- @coriolinus +- @cwhakes +- @eddyp +- @efx +- @ErikSchierboom +- @lutostag +- @nathanielknight +- @nfiles +- @petertseng +- @rofrol +- @stringparser +- @xakon +- @ZapAnton + +### Based on + +The Prime Factors Kata by Uncle Bob - https://web.archive.org/web/20221026171801/http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata \ No newline at end of file diff --git a/rust/prime-factors/src/lib.rs b/rust/prime-factors/src/lib.rs new file mode 100644 index 0000000..30d06a2 --- /dev/null +++ b/rust/prime-factors/src/lib.rs @@ -0,0 +1,3 @@ +pub fn factors(n: u64) -> Vec { + todo!("This should calculate the prime factors of {n}") +} diff --git a/rust/prime-factors/tests/prime_factors.rs b/rust/prime-factors/tests/prime_factors.rs new file mode 100644 index 0000000..119c9c8 --- /dev/null +++ b/rust/prime-factors/tests/prime_factors.rs @@ -0,0 +1,96 @@ +use prime_factors::*; + +#[test] +fn no_factors() { + let factors = factors(1); + let expected = []; + assert_eq!(factors, expected); +} + +#[test] +#[ignore] +fn prime_number() { + let factors = factors(2); + let expected = [2]; + assert_eq!(factors, expected); +} + +#[test] +#[ignore] +fn another_prime_number() { + let factors = factors(3); + let expected = [3]; + assert_eq!(factors, expected); +} + +#[test] +#[ignore] +fn square_of_a_prime() { + let factors = factors(9); + let expected = [3, 3]; + assert_eq!(factors, expected); +} + +#[test] +#[ignore] +fn product_of_first_prime() { + let factors = factors(4); + let expected = [2, 2]; + assert_eq!(factors, expected); +} + +#[test] +#[ignore] +fn cube_of_a_prime() { + let factors = factors(8); + let expected = [2, 2, 2]; + assert_eq!(factors, expected); +} + +#[test] +#[ignore] +fn product_of_second_prime() { + let factors = factors(27); + let expected = [3, 3, 3]; + assert_eq!(factors, expected); +} + +#[test] +#[ignore] +fn product_of_third_prime() { + let factors = factors(625); + let expected = [5, 5, 5, 5]; + assert_eq!(factors, expected); +} + +#[test] +#[ignore] +fn product_of_first_and_second_prime() { + let factors = factors(6); + let expected = [2, 3]; + assert_eq!(factors, expected); +} + +#[test] +#[ignore] +fn product_of_primes_and_non_primes() { + let factors = factors(12); + let expected = [2, 2, 3]; + assert_eq!(factors, expected); +} + +#[test] +#[ignore] +fn product_of_primes() { + let factors = factors(901_255); + let expected = [5, 17, 23, 461]; + assert_eq!(factors, expected); +} + +#[test] +#[ignore] +fn factors_include_a_large_prime() { + let factors = factors(93_819_012_551); + let expected = [11, 9_539, 894_119]; + assert_eq!(factors, expected); +} diff --git a/rust/sieve/.exercism/config.json b/rust/sieve/.exercism/config.json new file mode 100644 index 0000000..caeb218 --- /dev/null +++ b/rust/sieve/.exercism/config.json @@ -0,0 +1,37 @@ +{ + "authors": [ + "IanWhitney" + ], + "contributors": [ + "ashleygwilliams", + "ClashTheBunny", + "coriolinus", + "cwhakes", + "efx", + "ErikSchierboom", + "IanWhitney", + "lutostag", + "mkantor", + "nfiles", + "petertseng", + "rofrol", + "stringparser", + "xakon", + "ZapAnton" + ], + "files": { + "solution": [ + "src/lib.rs", + "Cargo.toml" + ], + "test": [ + "tests/sieve.rs" + ], + "example": [ + ".meta/example.rs" + ] + }, + "blurb": "Use the Sieve of Eratosthenes to find all the primes from 2 up to a given number.", + "source": "Sieve of Eratosthenes at Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes" +} diff --git a/rust/sieve/.gitignore b/rust/sieve/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/rust/sieve/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/rust/sieve/Cargo.toml b/rust/sieve/Cargo.toml new file mode 100644 index 0000000..bb52d8f --- /dev/null +++ b/rust/sieve/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "sieve" +version = "0.1.0" +edition = "2024" + +# Not all libraries from crates.io are available in Exercism's test runner. +# The full list of available libraries is here: +# https://github.com/exercism/rust-test-runner/blob/main/local-registry/Cargo.toml +[dependencies] diff --git a/rust/sieve/HELP.md b/rust/sieve/HELP.md new file mode 100644 index 0000000..22a6c00 --- /dev/null +++ b/rust/sieve/HELP.md @@ -0,0 +1,89 @@ +# Help + +## Running the tests + +Execute the tests with: + +```bash +$ cargo test +``` + +All but the first test have been ignored. After you get the first test to +pass, open the tests source file which is located in the `tests` directory +and remove the `#[ignore]` flag from the next test and get the tests to pass +again. Each separate test is a function with `#[test]` flag above it. +Continue, until you pass every test. + +If you wish to run _only ignored_ tests without editing the tests source file, use: + +```bash +$ cargo test -- --ignored +``` + +If you are using Rust 1.51 or later, you can run _all_ tests with + +```bash +$ cargo test -- --include-ignored +``` + +To run a specific test, for example `some_test`, you can use: + +```bash +$ cargo test some_test +``` + +If the specific test is ignored, use: + +```bash +$ cargo test some_test -- --ignored +``` + +To learn more about Rust tests refer to the online [test documentation][rust-tests]. + +[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html + +## Submitting your solution + +You can submit your solution using the `exercism submit src/lib.rs Cargo.toml` command. +This command will upload your solution to the Exercism website and print the solution page's URL. + +It's possible to submit an incomplete solution which allows you to: + +- See how others have completed the exercise +- Request help from a mentor + +## Need to get help? + +If you'd like help solving the exercise, check the following pages: + +- The [Rust track's documentation](https://exercism.org/docs/tracks/rust) +- The [Rust track's programming category on the forum](https://forum.exercism.org/c/programming/rust) +- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5) +- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs) + +Should those resources not suffice, you could submit your (incomplete) solution to request mentoring. + +## Rust Installation + +Refer to the [exercism help page][help-page] for Rust installation and learning +resources. + +## Submitting the solution + +Generally you should submit all files in which you implemented your solution (`src/lib.rs` in most cases). If you are using any external crates, please consider submitting the `Cargo.toml` file. This will make the review process faster and clearer. + +## Feedback, Issues, Pull Requests + +Head to [the forum](https://forum.exercism.org/c/programming/rust/) and create a post to provide feedback about an exercise or if you want to help implement new exercises. +Members of the rust track team are happy to help! + +The GitHub [track repository][github] is the home for all of the Rust exercises. + +If you want to know more about Exercism, take a look at the [contribution guide]. + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. + +[help-page]: https://exercism.org/tracks/rust/learning +[github]: https://github.com/exercism/rust +[contribution guide]: https://exercism.org/docs/community/contributors \ No newline at end of file diff --git a/rust/sieve/README.md b/rust/sieve/README.md new file mode 100644 index 0000000..d5345da --- /dev/null +++ b/rust/sieve/README.md @@ -0,0 +1,142 @@ +# Sieve + +Welcome to Sieve on Exercism's Rust Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Introduction + +You bought a big box of random computer parts at a garage sale. +You've started putting the parts together to build custom computers. + +You want to test the performance of different combinations of parts, and decide to create your own benchmarking program to see how your computers compare. +You choose the famous "Sieve of Eratosthenes" algorithm, an ancient algorithm, but one that should push your computers to the limits. + +## Instructions + +Your task is to create a program that implements the Sieve of Eratosthenes algorithm to find all prime numbers less than or equal to a given number. + +A prime number is a number larger than 1 that is only divisible by 1 and itself. +For example, 2, 3, 5, 7, 11, and 13 are prime numbers. +By contrast, 6 is _not_ a prime number as it not only divisible by 1 and itself, but also by 2 and 3. + +To use the Sieve of Eratosthenes, first, write out all the numbers from 2 up to and including your given number. +Then, follow these steps: + +1. Find the next unmarked number (skipping over marked numbers). + This is a prime number. +2. Mark all the multiples of that prime number as **not** prime. + +Repeat the steps until you've gone through every number. +At the end, all the unmarked numbers are prime. + +~~~~exercism/note +The Sieve of Eratosthenes marks off multiples of each prime using addition (repeatedly adding the prime) or multiplication (directly computing its multiples), rather than checking each number for divisibility. + +The tests don't check that you've implemented the algorithm, only that you've come up with the correct primes. +~~~~ + +## Example + +Let's say you're finding the primes less than or equal to 10. + +- Write out 2, 3, 4, 5, 6, 7, 8, 9, 10, leaving them all unmarked. + + ```text + 2 3 4 5 6 7 8 9 10 + ``` + +- 2 is unmarked and is therefore a prime. + Mark 4, 6, 8 and 10 as "not prime". + + ```text + 2 3 [4] 5 [6] 7 [8] 9 [10] + ↑ + ``` + +- 3 is unmarked and is therefore a prime. + Mark 6 and 9 as not prime _(marking 6 is optional - as it's already been marked)_. + + ```text + 2 3 [4] 5 [6] 7 [8] [9] [10] + ↑ + ``` + +- 4 is marked as "not prime", so we skip over it. + + ```text + 2 3 [4] 5 [6] 7 [8] [9] [10] + ↑ + ``` + +- 5 is unmarked and is therefore a prime. + Mark 10 as not prime _(optional - as it's already been marked)_. + + ```text + 2 3 [4] 5 [6] 7 [8] [9] [10] + ↑ + ``` + +- 6 is marked as "not prime", so we skip over it. + + ```text + 2 3 [4] 5 [6] 7 [8] [9] [10] + ↑ + ``` + +- 7 is unmarked and is therefore a prime. + + ```text + 2 3 [4] 5 [6] 7 [8] [9] [10] + ↑ + ``` + +- 8 is marked as "not prime", so we skip over it. + + ```text + 2 3 [4] 5 [6] 7 [8] [9] [10] + ↑ + ``` + +- 9 is marked as "not prime", so we skip over it. + + ```text + 2 3 [4] 5 [6] 7 [8] [9] [10] + ↑ + ``` + +- 10 is marked as "not prime", so we stop as there are no more numbers to check. + + ```text + 2 3 [4] 5 [6] 7 [8] [9] [10] + ↑ + ``` + +You've examined all the numbers and found that 2, 3, 5, and 7 are still unmarked, meaning they're the primes less than or equal to 10. + +## Source + +### Created by + +- @IanWhitney + +### Contributed to by + +- @ashleygwilliams +- @ClashTheBunny +- @coriolinus +- @cwhakes +- @efx +- @ErikSchierboom +- @IanWhitney +- @lutostag +- @mkantor +- @nfiles +- @petertseng +- @rofrol +- @stringparser +- @xakon +- @ZapAnton + +### Based on + +Sieve of Eratosthenes at Wikipedia - https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes \ No newline at end of file diff --git a/rust/sieve/src/lib.rs b/rust/sieve/src/lib.rs new file mode 100644 index 0000000..7825c55 --- /dev/null +++ b/rust/sieve/src/lib.rs @@ -0,0 +1,52 @@ +const PRIME_LEN: usize = 10_010; +const LIMIT: usize = 106_000; + +struct PrimeCache { + primes: [u64; PRIME_LEN], +} + +impl PrimeCache { + const fn new() -> Self { + let mut primes = [0; PRIME_LEN]; + let mut sieve = [true; LIMIT]; + + sieve[0] = false; + sieve[1] = false; + + let mut i = 2; + while i * i < LIMIT { + if sieve[i] { + let mut j = i * i; + while j < LIMIT { + sieve[j] = false; + j += i; + } + } + i += 1; + } + let mut num = 0; + let mut j = 0; + while num < LIMIT && j < PRIME_LEN { + if sieve[num] { + primes[j] = num as u64; + j += 1; + } + num += 1; + } + Self { primes } + } +} + +static CACHE: PrimeCache = PrimeCache::new(); + +pub fn primes_up_to(upper_bound: u64) -> Vec { + let mut nth = 0; + if upper_bound < 2 { + return vec![]; + } + while CACHE.primes[nth] <= upper_bound { + nth += 1; + } + let slice = &CACHE.primes[0..nth]; + slice.to_vec() +} diff --git a/rust/sieve/tests/sieve.rs b/rust/sieve/tests/sieve.rs new file mode 100644 index 0000000..fb53dfc --- /dev/null +++ b/rust/sieve/tests/sieve.rs @@ -0,0 +1,51 @@ +use sieve::*; + +#[test] +fn no_primes_under_two() { + let input = 1; + let output = primes_up_to(input); + let expected = []; + assert_eq!(output, expected); +} + +#[test] +fn find_first_prime() { + let input = 2; + let output = primes_up_to(input); + let expected = [2]; + assert_eq!(output, expected); +} + +#[test] +fn find_primes_up_to_10() { + let input = 10; + let output = primes_up_to(input); + let expected = [2, 3, 5, 7]; + assert_eq!(output, expected); +} + +#[test] +fn limit_is_prime() { + let input = 13; + let output = primes_up_to(input); + let expected = [2, 3, 5, 7, 11, 13]; + assert_eq!(output, expected); +} + +#[test] +fn find_primes_up_to_1000() { + let input = 1000; + let output = primes_up_to(input); + let expected = [ + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, + 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, + 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, + 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, + 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, + 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, + 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, + 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, + ]; + assert_eq!(output, expected); +}