From e5131342a2fb695ae0c8e913dd92e6420f46729f Mon Sep 17 00:00:00 2001 From: Eric Willigers Date: Sat, 11 May 2024 05:00:35 +1000 Subject: [PATCH] Add sieve exercise (#376) * Add sieve exercise * reformat across multiple lines, set difficulty 3 --- config.json | 12 ++++++ .../practice/sieve/.docs/instructions.md | 42 ++++++++++++++++++ .../practice/sieve/.docs/introduction.md | 7 +++ exercises/practice/sieve/.meta/config.json | 19 ++++++++ exercises/practice/sieve/.meta/example.el | 25 +++++++++++ exercises/practice/sieve/.meta/tests.toml | 25 +++++++++++ exercises/practice/sieve/sieve-test.el | 43 +++++++++++++++++++ exercises/practice/sieve/sieve.el | 14 ++++++ 8 files changed, 187 insertions(+) create mode 100644 exercises/practice/sieve/.docs/instructions.md create mode 100644 exercises/practice/sieve/.docs/introduction.md create mode 100644 exercises/practice/sieve/.meta/config.json create mode 100644 exercises/practice/sieve/.meta/example.el create mode 100644 exercises/practice/sieve/.meta/tests.toml create mode 100644 exercises/practice/sieve/sieve-test.el create mode 100644 exercises/practice/sieve/sieve.el diff --git a/config.json b/config.json index 5a903088..6c3ca65a 100644 --- a/config.json +++ b/config.json @@ -476,6 +476,18 @@ "strings" ] }, + { + "slug": "sieve", + "name": "Sieve", + "uuid": "21172aa9-a155-493c-ad9f-ab4884596488", + "practices": [], + "prerequisites": [], + "difficulty": 3, + "topics": [ + "control_flow_loops", + "math" + ] + }, { "slug": "largest-series-product", "name": "Largest Series Product", diff --git a/exercises/practice/sieve/.docs/instructions.md b/exercises/practice/sieve/.docs/instructions.md new file mode 100644 index 00000000..085c0a57 --- /dev/null +++ b/exercises/practice/sieve/.docs/instructions.md @@ -0,0 +1,42 @@ +# 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, you first create a list of all the numbers between 2 and your given number. +Then you repeat the following steps: + +1. Find the next unmarked number in your list (skipping over marked numbers). + This is a prime number. +2. Mark all the multiples of that prime number as **not** prime. + +You keep repeating these steps until you've gone through every number in your list. +At the end, all the unmarked numbers are prime. + +~~~~exercism/note +The tests don't check that you've implemented the algorithm, only that you've come up with the correct list of primes. +To check you are implementing the Sieve correctly, a good first test is to check that you do not use division or remainder operations. +~~~~ + +## Example + +Let's say you're finding the primes less than or equal to 10. + +- List out 2, 3, 4, 5, 6, 7, 8, 9, 10, leaving them all unmarked. +- 2 is unmarked and is therefore a prime. + Mark 4, 6, 8 and 10 as "not prime". +- 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)_. +- 4 is marked as "not prime", so we skip over it. +- 5 is unmarked and is therefore a prime. + Mark 10 as not prime _(optional - as it's already been marked)_. +- 6 is marked as "not prime", so we skip over it. +- 7 is unmarked and is therefore a prime. +- 8 is marked as "not prime", so we skip over it. +- 9 is marked as "not prime", so we skip over it. +- 10 is marked as "not prime", so we stop as there are no more numbers to check. + +You've examined all numbers and found 2, 3, 5, and 7 are still unmarked, which means they're the primes less than or equal to 10. diff --git a/exercises/practice/sieve/.docs/introduction.md b/exercises/practice/sieve/.docs/introduction.md new file mode 100644 index 00000000..f6c1cf79 --- /dev/null +++ b/exercises/practice/sieve/.docs/introduction.md @@ -0,0 +1,7 @@ +# 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. diff --git a/exercises/practice/sieve/.meta/config.json b/exercises/practice/sieve/.meta/config.json new file mode 100644 index 00000000..c98915f1 --- /dev/null +++ b/exercises/practice/sieve/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "keiravillekode" + ], + "files": { + "solution": [ + "sieve.el" + ], + "test": [ + "sieve-test.el" + ], + "example": [ + ".meta/example.el" + ] + }, + "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/exercises/practice/sieve/.meta/example.el b/exercises/practice/sieve/.meta/example.el new file mode 100644 index 00000000..fdd454ed --- /dev/null +++ b/exercises/practice/sieve/.meta/example.el @@ -0,0 +1,25 @@ +;;; sieve.el --- Sieve (exercism) -*- lexical-binding: t; -*- + +;;; Commentary: + +;;; Code: + +(require 'cl-lib) + +(defun primes (limit) + (let ((table (make-bool-vector (1+ limit) t)) + (result nil)) + (cl-loop for p from 2 + for psq = (* p p) + until (< limit psq) + do (when (aref table p) + (cl-loop for m from psq to limit by p + do (aset table m nil)))) + (cl-loop for p from limit downto 2 + do (when (aref table p) + (setq result (cons p result)))) + result)) + +(provide 'sieve) +;;; sieve.el ends here + diff --git a/exercises/practice/sieve/.meta/tests.toml b/exercises/practice/sieve/.meta/tests.toml new file mode 100644 index 00000000..fec5e1a1 --- /dev/null +++ b/exercises/practice/sieve/.meta/tests.toml @@ -0,0 +1,25 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[88529125-c4ce-43cc-bb36-1eb4ddd7b44f] +description = "no primes under two" + +[4afe9474-c705-4477-9923-840e1024cc2b] +description = "find first prime" + +[974945d8-8cd9-4f00-9463-7d813c7f17b7] +description = "find primes up to 10" + +[2e2417b7-3f3a-452a-8594-b9af08af6d82] +description = "limit is prime" + +[92102a05-4c7c-47de-9ed0-b7d5fcd00f21] +description = "find primes up to 1000" diff --git a/exercises/practice/sieve/sieve-test.el b/exercises/practice/sieve/sieve-test.el new file mode 100644 index 00000000..eb96b595 --- /dev/null +++ b/exercises/practice/sieve/sieve-test.el @@ -0,0 +1,43 @@ +;;; sieve-test.el --- Tests for Sieve (exercism) -*- lexical-binding: t; -*- + +;;; Commentary: + +;;; Code: + +(load-file "sieve.el") +(declare-function primes "sieve.el" (limit)) + + +(ert-deftest no-primes-under-two () + (should (equal '() (primes 1)))) + + +(ert-deftest find-first-prime () + (should (equal '(2) (primes 2)))) + + +(ert-deftest find-primes-up-to-10 () + (should (equal '(2 3 5 7) (primes 10)))) + + +(ert-deftest limit-is-prime () + (should (equal '(2 3 5 7 11 13) (primes 13)))) + + +(ert-deftest find-primes-up-to-1000 () + (should (equal '(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) + (primes 1000)))) + + +(provide 'sieve-test) +;;; sieve-test.el ends here diff --git a/exercises/practice/sieve/sieve.el b/exercises/practice/sieve/sieve.el new file mode 100644 index 00000000..89858dda --- /dev/null +++ b/exercises/practice/sieve/sieve.el @@ -0,0 +1,14 @@ +;;; sieve.el --- Sieve (exercism) -*- lexical-binding: t; -*- + +;;; Commentary: + +;;; Code: + + +(defun primes (limit) + (error "Delete this S-Expression and write your own implementation")) + + +(provide 'sieve) +;;; sieve.el ends here +