From aaf27bfff8895a1c7051c6ca3114f98b1fcaae22 Mon Sep 17 00:00:00 2001 From: Glenn Jackman Date: Tue, 26 Mar 2024 18:17:34 -0400 Subject: [PATCH 1/3] Add sieve exercise --- config.json | 8 ++ .../practice/sieve/.docs/instructions.md | 28 +++++++ .../practice/sieve/.docs/introduction.md | 7 ++ exercises/practice/sieve/.meta/config.json | 19 +++++ .../sieve/.meta/src/Sieve.example.elm | 75 +++++++++++++++++++ exercises/practice/sieve/.meta/tests.toml | 25 +++++++ exercises/practice/sieve/elm.json | 29 +++++++ exercises/practice/sieve/src/Sieve.elm | 6 ++ exercises/practice/sieve/tests/Tests.elm | 35 +++++++++ 9 files changed, 232 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/src/Sieve.example.elm create mode 100644 exercises/practice/sieve/.meta/tests.toml create mode 100644 exercises/practice/sieve/elm.json create mode 100644 exercises/practice/sieve/src/Sieve.elm create mode 100644 exercises/practice/sieve/tests/Tests.elm diff --git a/config.json b/config.json index 5a883652..bb989aeb 100644 --- a/config.json +++ b/config.json @@ -1234,6 +1234,14 @@ "result" ], "difficulty": 5 + }, + { + "slug": "sieve", + "name": "sieve", + "uuid": "d95a08ac-fe7a-4cd5-8c87-d6ac4a9fc90f", + "practices": ["lists"], + "prerequisites": ["lists", "pattern-matching", "array"], + "difficulty": 5 } ] }, diff --git a/exercises/practice/sieve/.docs/instructions.md b/exercises/practice/sieve/.docs/instructions.md new file mode 100644 index 00000000..3adf1d55 --- /dev/null +++ b/exercises/practice/sieve/.docs/instructions.md @@ -0,0 +1,28 @@ +# Instructions + +Your task is to create a program that implements the Sieve of Eratosthenes algorithm to find prime numbers. + +A prime number is a number that is only divisible by 1 and itself. +For example, 2, 3, 5, 7, 11, and 13 are prime numbers. + +The Sieve of Eratosthenes is an ancient algorithm that works by taking a list of numbers and crossing out all the numbers that aren't prime. + +A number that is **not** prime is called a "composite number". + +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. This is a prime number. +2. Mark all the multiples of that prime number as composite (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 +[Wikipedia's Sieve of Eratosthenes article][eratosthenes] has a useful graphic that explains the algorithm. + +The tests don't check that you've implemented the algorithm, only that you've come up with the correct list of primes. +A good first test is to check that you do not use division or remainder operations. + +[eratosthenes]: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes +~~~~ 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..a6e76cd1 --- /dev/null +++ b/exercises/practice/sieve/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "glennj" + ], + "files": { + "solution": [ + "src/Sieve.elm" + ], + "test": [ + "tests/Tests.elm" + ], + "example": [ + ".meta/src/Sieve.example.elm" + ] + }, + "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/src/Sieve.example.elm b/exercises/practice/sieve/.meta/src/Sieve.example.elm new file mode 100644 index 00000000..1f82c60c --- /dev/null +++ b/exercises/practice/sieve/.meta/src/Sieve.example.elm @@ -0,0 +1,75 @@ +module Sieve exposing (primes) + +import Array exposing (Array) + + +primes : Int -> List Int +primes limit = + makeCandidates limit + |> markMultiples limit + |> extractPrimes + + +makeCandidates : Int -> Array Bool +makeCandidates limit = + Array.repeat (limit + 1) True + |> Array.set 0 False + |> Array.set 1 False + + +extractPrimes : Array Bool -> List Int +extractPrimes candidates = + Array.indexedMap (\idx val -> ( idx, val )) candidates + |> Array.filter (\( idx, isPrime ) -> isPrime) + |> Array.map Tuple.first + |> Array.toList + + +markMultiples : Int -> Array Bool -> Array Bool +markMultiples limit candidates = + mark limit 2 candidates + + +mark limit candidate candidates = + if candidate > isqrt limit then + candidates + + else + case Array.get candidate candidates of + Nothing -> + -- should not happen + Array.empty + + Just True -> + mark + limit + (candidate + 1) + (markMultiplesOfPrime + limit + candidate + (candidate * candidate) + candidates + ) + + Just False -> + mark + limit + (candidate + 1) + candidates + + +markMultiplesOfPrime limit prime current candidates = + if current > limit then + candidates + + else + markMultiplesOfPrime + limit + prime + (current + prime) + (Array.set current False candidates) + + +isqrt : Int -> Int +isqrt = + toFloat >> sqrt >> floor 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/elm.json b/exercises/practice/sieve/elm.json new file mode 100644 index 00000000..22c9e137 --- /dev/null +++ b/exercises/practice/sieve/elm.json @@ -0,0 +1,29 @@ +{ + "type": "application", + "source-directories": [ + "src" + ], + "elm-version": "0.19.1", + "dependencies": { + "direct": { + "elm/core": "1.0.5", + "elm/json": "1.1.3", + "elm/parser": "1.1.0", + "elm/random": "1.0.0", + "elm/regex": "1.0.0", + "elm/time": "1.0.0" + }, + "indirect": {} + }, + "test-dependencies": { + "direct": { + "elm-explorations/test": "2.1.0", + "rtfeldman/elm-iso8601-date-strings": "1.1.4" + }, + "indirect": { + "elm/bytes": "1.0.8", + "elm/html": "1.0.0", + "elm/virtual-dom": "1.0.3" + } + } +} diff --git a/exercises/practice/sieve/src/Sieve.elm b/exercises/practice/sieve/src/Sieve.elm new file mode 100644 index 00000000..8b7d0190 --- /dev/null +++ b/exercises/practice/sieve/src/Sieve.elm @@ -0,0 +1,6 @@ +module Sieve exposing (primes) + + +primes : Int -> List Int +primes limit = + Debug.todo "Please implement this function" diff --git a/exercises/practice/sieve/tests/Tests.elm b/exercises/practice/sieve/tests/Tests.elm new file mode 100644 index 00000000..fa1ae9fd --- /dev/null +++ b/exercises/practice/sieve/tests/Tests.elm @@ -0,0 +1,35 @@ +module Tests exposing (tests) + +import Expect +import Sieve +import Test exposing (Test, describe, skip, test) + + +tests : Test +tests = + describe "Sieve" + [ test "no primes under two" <| + \() -> + Sieve.primes 1 + |> Expect.equal [] + , skip <| + test "find first prime" <| + \() -> + Sieve.primes 2 + |> Expect.equal [ 2 ] + , skip <| + test "find primes up to 10" <| + \() -> + Sieve.primes 10 + |> Expect.equal [ 2, 3, 5, 7 ] + , skip <| + test "limit is prime" <| + \() -> + Sieve.primes 13 + |> Expect.equal [ 2, 3, 5, 7, 11, 13 ] + , skip <| + test "find primes up to 1000" <| + \() -> + Sieve.primes 1000 + |> Expect.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 ] + ] From 7367145db17123d666920d01ae12cecb1fc6e77a Mon Sep 17 00:00:00 2001 From: Glenn Jackman Date: Tue, 26 Mar 2024 18:42:32 -0400 Subject: [PATCH 2/3] configlet fmt config.json --- config.json | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index bb989aeb..c8903d2c 100644 --- a/config.json +++ b/config.json @@ -1239,8 +1239,14 @@ "slug": "sieve", "name": "sieve", "uuid": "d95a08ac-fe7a-4cd5-8c87-d6ac4a9fc90f", - "practices": ["lists"], - "prerequisites": ["lists", "pattern-matching", "array"], + "practices": [ + "lists" + ], + "prerequisites": [ + "lists", + "pattern-matching", + "array" + ], "difficulty": 5 } ] From 64c94372b38df86db006281eb2829627001efc41 Mon Sep 17 00:00:00 2001 From: Glenn Jackman Date: Tue, 26 Mar 2024 19:09:59 -0400 Subject: [PATCH 3/3] elm-review --- exercises/practice/sieve/.meta/src/Sieve.example.elm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/sieve/.meta/src/Sieve.example.elm b/exercises/practice/sieve/.meta/src/Sieve.example.elm index 1f82c60c..6c0451c9 100644 --- a/exercises/practice/sieve/.meta/src/Sieve.example.elm +++ b/exercises/practice/sieve/.meta/src/Sieve.example.elm @@ -20,7 +20,7 @@ makeCandidates limit = extractPrimes : Array Bool -> List Int extractPrimes candidates = Array.indexedMap (\idx val -> ( idx, val )) candidates - |> Array.filter (\( idx, isPrime ) -> isPrime) + |> Array.filter (\( _, isPrime ) -> isPrime) |> Array.map Tuple.first |> Array.toList