From b1e4ac99f809d09ecd02e84f5daba9e0224638f1 Mon Sep 17 00:00:00 2001 From: Kah Goh Date: Wed, 27 Mar 2024 16:08:47 +0800 Subject: [PATCH] Add sieve exercise (#206) --- config.json | 8 +++++ .../practice/sieve/.docs/instructions.md | 28 ++++++++++++++++ .../practice/sieve/.docs/introduction.md | 7 ++++ exercises/practice/sieve/.meta/config.json | 19 +++++++++++ exercises/practice/sieve/.meta/example.lfe | 19 +++++++++++ exercises/practice/sieve/.meta/tests.toml | 25 +++++++++++++++ exercises/practice/sieve/Makefile | 21 ++++++++++++ exercises/practice/sieve/rebar.config | 11 +++++++ exercises/practice/sieve/rebar.lock | 8 +++++ exercises/practice/sieve/src/sieve.app.src | 11 +++++++ exercises/practice/sieve/src/sieve.lfe | 6 ++++ exercises/practice/sieve/test/sieve-tests.lfe | 32 +++++++++++++++++++ 12 files changed, 195 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.lfe create mode 100644 exercises/practice/sieve/.meta/tests.toml create mode 100644 exercises/practice/sieve/Makefile create mode 100644 exercises/practice/sieve/rebar.config create mode 100644 exercises/practice/sieve/rebar.lock create mode 100644 exercises/practice/sieve/src/sieve.app.src create mode 100644 exercises/practice/sieve/src/sieve.lfe create mode 100644 exercises/practice/sieve/test/sieve-tests.lfe diff --git a/config.json b/config.json index d1d7c11b..a31c4bd0 100644 --- a/config.json +++ b/config.json @@ -380,6 +380,14 @@ "practices": [], "prerequisites": [], "difficulty": 1 + }, + { + "slug": "sieve", + "name": "Sieve", + "uuid": "50f4505d-c82a-46a7-bfeb-0100c5f2d45f", + "practices": [], + "prerequisites": [], + "difficulty": 1 } ] }, 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..a361411b --- /dev/null +++ b/exercises/practice/sieve/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "kahgoh" + ], + "files": { + "solution": [ + "src/sieve.lfe" + ], + "test": [ + "test/sieve-tests.lfe" + ], + "example": [ + ".meta/example.lfe" + ] + }, + "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.lfe b/exercises/practice/sieve/.meta/example.lfe new file mode 100644 index 00000000..6f8860e5 --- /dev/null +++ b/exercises/practice/sieve/.meta/example.lfe @@ -0,0 +1,19 @@ +(defmodule sieve + (export (primes 1))) + +(defun mark (n limit composite) + (sets:union composite (sets:from_list (lists:seq (* n 2) limit n)))) + +(defun do-primes + ((limit limit primes composite) + (if (sets:is_element limit composite) + primes + (cons limit primes))) + ((n limit primes composite) + (if (sets:is_element n composite) + (do-primes (+ n 1) limit primes composite) + (do-primes (+ n 1) limit (cons n primes) (mark n limit composite))))) + +(defun primes + ((limit) (when (< limit 2)) '()) + ((limit) (lists:reverse (do-primes 2 limit '() (sets:new))))) 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/Makefile b/exercises/practice/sieve/Makefile new file mode 100644 index 00000000..fbb5a7de --- /dev/null +++ b/exercises/practice/sieve/Makefile @@ -0,0 +1,21 @@ +ERL := $(shell which erl) +REBAR3 := $(shell which rebar3) + +null := +space := $(null) # +comma := , + +ifeq ($(ERL),) + $(error Can't find Erlang executable 'erl') +else ifeq ($(REBAR3),) + $(error Can't find rebar3) +endif + +compile: ; $(REBAR3) compile + +clean: ; $(REBAR3) clean + +.PHONY: test +test: + $(REBAR3) eunit \ + -m $(subst $(space),$(comma),$(basename $(notdir $(wildcard test/*.lfe)))) diff --git a/exercises/practice/sieve/rebar.config b/exercises/practice/sieve/rebar.config new file mode 100644 index 00000000..d53487ac --- /dev/null +++ b/exercises/practice/sieve/rebar.config @@ -0,0 +1,11 @@ +{plugins, [{rebar3_lfe, "0.4.3"}]}. + +{provider_hooks, [{post, [{compile, {lfe, compile}}]}]}. + +{deps, [{lfe, "2.1.1"}]}. + +{profiles, + [{test, + [{eunit_compile_opts, [{src_dirs, ["src", "test"]}]}, + {deps, + [{ltest, "0.13.3"}]}]}]}. diff --git a/exercises/practice/sieve/rebar.lock b/exercises/practice/sieve/rebar.lock new file mode 100644 index 00000000..d5a6b3b9 --- /dev/null +++ b/exercises/practice/sieve/rebar.lock @@ -0,0 +1,8 @@ +{"1.2.0", +[{<<"lfe">>,{pkg,<<"lfe">>,<<"2.1.1">>},0}]}. +[ +{pkg_hash,[ + {<<"lfe">>, <<"4A888B26172D198DC7A5AFEB897E8248AF7D56E1638D9C8249AAF933AE811B96">>}]}, +{pkg_hash_ext,[ + {<<"lfe">>, <<"C484D3B655D40DED58BC41B17B22F173711C681BF36063A234A9BAA9506947E1">>}]} +]. diff --git a/exercises/practice/sieve/src/sieve.app.src b/exercises/practice/sieve/src/sieve.app.src new file mode 100644 index 00000000..a47624e8 --- /dev/null +++ b/exercises/practice/sieve/src/sieve.app.src @@ -0,0 +1,11 @@ +%% -*- erlang -*- +{application, 'sieve', + [{description, "Use the Sieve of Eratosthenes to find all the primes from 2 up to a given number."}, + {vsn, "0.0.1"}, + {modules, + ['sieve']}, + {registered, []}, + {applications, + [kernel, stdlib]}, + {included_applications, []}, + {env, []}]}. diff --git a/exercises/practice/sieve/src/sieve.lfe b/exercises/practice/sieve/src/sieve.lfe new file mode 100644 index 00000000..6ca7da15 --- /dev/null +++ b/exercises/practice/sieve/src/sieve.lfe @@ -0,0 +1,6 @@ +(defmodule sieve + (export (primes 1))) + +(defun primes (limit) + ; Please implement the primes function +) diff --git a/exercises/practice/sieve/test/sieve-tests.lfe b/exercises/practice/sieve/test/sieve-tests.lfe new file mode 100644 index 00000000..26db929f --- /dev/null +++ b/exercises/practice/sieve/test/sieve-tests.lfe @@ -0,0 +1,32 @@ +(defmodule sieve-tests + (behaviour ltest-unit) + (export all)) + +(include-lib "ltest/include/ltest-macros.lfe") + +(deftest test-no-primes-under-two + (is-equal (sieve:primes 1) '())) + +(deftest test-find-first-prime + (is-equal (sieve:primes 2) '(2))) + +(deftest test-find-primes-up-to-10 + (is-equal (sieve:primes 10) '(2 3 5 7))) + +(deftest test-limit-is-a-prime + (is-equal (sieve:primes 13) '(2 3 5 7 11 13))) + +(deftest test-find-primes-up-to-1000 + (is-equal (sieve:primes 1000) '( + 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)))