diff --git a/config.json b/config.json index e30100c71..028d40a81 100644 --- a/config.json +++ b/config.json @@ -622,6 +622,14 @@ "practices": [], "prerequisites": [], "difficulty": 4 + }, + { + "slug": "sum-of-multiples", + "name": "Sum of Multiples", + "uuid": "e127a984-ebb1-4709-9cc9-a740bceda94c", + "practices": [], + "prerequisites": [], + "difficulty": 4 } ] }, diff --git a/exercises/practice/sum-of-multiples/.docs/instructions.md b/exercises/practice/sum-of-multiples/.docs/instructions.md new file mode 100644 index 000000000..d69f890e9 --- /dev/null +++ b/exercises/practice/sum-of-multiples/.docs/instructions.md @@ -0,0 +1,27 @@ +# Instructions + +Your task is to write the code that calculates the energy points that get awarded to players when they complete a level. + +The points awarded depend on two things: + +- The level (a number) that the player completed. +- The base value of each magical item collected by the player during that level. + +The energy points are awarded according to the following rules: + +1. For each magical item, take the base value and find all the multiples of that value that are less than the level number. +2. Combine the sets of numbers. +3. Remove any duplicates. +4. Calculate the sum of all the numbers that are left. + +Let's look at an example: + +**The player completed level 20 and found two magical items with base values of 3 and 5.** + +To calculate the energy points earned by the player, we need to find all the unique multiples of these base values that are less than level 20. + +- Multiples of 3 less than 20: `{3, 6, 9, 12, 15, 18}` +- Multiples of 5 less than 20: `{5, 10, 15}` +- Combine the sets and remove duplicates: `{3, 5, 6, 9, 10, 12, 15, 18}` +- Sum the unique multiples: `3 + 5 + 6 + 9 + 10 + 12 + 15 + 18 = 78` +- Therefore, the player earns **78** energy points for completing level 20 and finding the two magical items with base values of 3 and 5. diff --git a/exercises/practice/sum-of-multiples/.docs/introduction.md b/exercises/practice/sum-of-multiples/.docs/introduction.md new file mode 100644 index 000000000..69cabeed5 --- /dev/null +++ b/exercises/practice/sum-of-multiples/.docs/introduction.md @@ -0,0 +1,6 @@ +# Introduction + +You work for a company that makes an online, fantasy-survival game. + +When a player finishes a level, they are awarded energy points. +The amount of energy awarded depends on which magical items the player found while exploring that level. diff --git a/exercises/practice/sum-of-multiples/.meta/config.json b/exercises/practice/sum-of-multiples/.meta/config.json new file mode 100644 index 000000000..244af6bec --- /dev/null +++ b/exercises/practice/sum-of-multiples/.meta/config.json @@ -0,0 +1,20 @@ +{ + "authors": ["therealowenrees"], + "files": { + "solution": [ + "sum_of_multiples.ml" + ], + "test": [ + "test.ml" + ], + "example": [ + ".meta/example.ml" + ], + "editor": [ + "sum_of_multiples.mli" + ] + }, + "blurb": "Given a number, find the sum of all the multiples of particular numbers up to but not including that number.", + "source": "A variation on Problem 1 at Project Euler", + "source_url": "https://projecteuler.net/problem=1" +} diff --git a/exercises/practice/sum-of-multiples/.meta/example.ml b/exercises/practice/sum-of-multiples/.meta/example.ml new file mode 100644 index 000000000..e1f075c36 --- /dev/null +++ b/exercises/practice/sum-of-multiples/.meta/example.ml @@ -0,0 +1,4 @@ +let sum factors limit = + List.init (limit - 1) ((+) 1) + |> List.filter (fun i -> List.exists (fun f -> f <> 0 && i mod f = 0) factors) + |> List.fold_left ( + ) 0 diff --git a/exercises/practice/sum-of-multiples/.meta/tests.toml b/exercises/practice/sum-of-multiples/.meta/tests.toml new file mode 100644 index 000000000..1e9b1241d --- /dev/null +++ b/exercises/practice/sum-of-multiples/.meta/tests.toml @@ -0,0 +1,58 @@ +# 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. + +[54aaab5a-ce86-4edc-8b40-d3ab2400a279] +description = "no multiples within limit" + +[361e4e50-c89b-4f60-95ef-5bc5c595490a] +description = "one factor has multiples within limit" + +[e644e070-040e-4ae0-9910-93c69fc3f7ce] +description = "more than one multiple within limit" + +[607d6eb9-535c-41ce-91b5-3a61da3fa57f] +description = "more than one factor with multiples within limit" + +[f47e8209-c0c5-4786-b07b-dc273bf86b9b] +description = "each multiple is only counted once" + +[28c4b267-c980-4054-93e9-07723db615ac] +description = "a much larger limit" + +[09c4494d-ff2d-4e0f-8421-f5532821ee12] +description = "three factors" + +[2d0d5faa-f177-4ad6-bde9-ebb865083751] +description = "factors not relatively prime" + +[ece8f2e8-96aa-4166-bbb7-6ce71261e354] +description = "some pairs of factors relatively prime and some not" + +[624fdade-6ffb-400e-8472-456a38c171c0] +description = "one factor is a multiple of another" + +[949ee7eb-db51-479c-b5cb-4a22b40ac057] +description = "much larger factors" + +[41093673-acbd-482c-ab80-d00a0cbedecd] +description = "all numbers are multiples of 1" + +[1730453b-baaa-438e-a9c2-d754497b2a76] +description = "no factors means an empty sum" + +[214a01e9-f4bf-45bb-80f1-1dce9fbb0310] +description = "the only multiple of 0 is 0" + +[c423ae21-a0cb-4ec7-aeb1-32971af5b510] +description = "the factor 0 does not affect the sum of multiples of other factors" + +[17053ba9-112f-4ac0-aadb-0519dd836342] +description = "solutions using include-exclude must extend to cardinality greater than 3" diff --git a/exercises/practice/sum-of-multiples/Makefile b/exercises/practice/sum-of-multiples/Makefile new file mode 100644 index 000000000..b71d6af2d --- /dev/null +++ b/exercises/practice/sum-of-multiples/Makefile @@ -0,0 +1,9 @@ +default: clean test + +test: + dune runtest + +clean: + dune clean + +.PHONY: clean diff --git a/exercises/practice/sum-of-multiples/dune b/exercises/practice/sum-of-multiples/dune new file mode 100644 index 000000000..9540297f2 --- /dev/null +++ b/exercises/practice/sum-of-multiples/dune @@ -0,0 +1,20 @@ +(executable + (name test) + (libraries base ounit2)) + +(alias + (name runtest) + (deps + (:x test.exe)) + (action + (run %{x}))) + +(alias + (name buildtest) + (deps + (:x test.exe))) + +(env + (dev + (flags + (:standard -warn-error -A)))) diff --git a/exercises/practice/sum-of-multiples/dune-project b/exercises/practice/sum-of-multiples/dune-project new file mode 100644 index 000000000..7655de077 --- /dev/null +++ b/exercises/practice/sum-of-multiples/dune-project @@ -0,0 +1 @@ +(lang dune 1.1) diff --git a/exercises/practice/sum-of-multiples/sum_of_multiples.ml b/exercises/practice/sum-of-multiples/sum_of_multiples.ml new file mode 100644 index 000000000..b4cdfbfd4 --- /dev/null +++ b/exercises/practice/sum-of-multiples/sum_of_multiples.ml @@ -0,0 +1 @@ +let sum _ _ = failwith "'sum' not implemented" \ No newline at end of file diff --git a/exercises/practice/sum-of-multiples/sum_of_multiples.mli b/exercises/practice/sum-of-multiples/sum_of_multiples.mli new file mode 100644 index 000000000..c79fd0509 --- /dev/null +++ b/exercises/practice/sum-of-multiples/sum_of_multiples.mli @@ -0,0 +1 @@ +val sum : int list -> int -> int \ No newline at end of file diff --git a/exercises/practice/sum-of-multiples/test.ml b/exercises/practice/sum-of-multiples/test.ml new file mode 100644 index 000000000..94bf70747 --- /dev/null +++ b/exercises/practice/sum-of-multiples/test.ml @@ -0,0 +1,43 @@ +open OUnit2 +open Sum_of_multiples + +let ae expected actual _test_ctxt = + assert_equal expected actual ~printer:string_of_int + +let tests = [ + "no multiples within limit" >:: + ae 0 (sum ([3; 5]) (1)); + "one factor has multiples within limit" >:: + ae 3 (sum ([3; 5]) (4)); + "more than one multiple within limit" >:: + ae 9 (sum ([3]) (7)); + "more than one factor with multiples within limit" >:: + ae 23 (sum ([3; 5]) (10)); + "each multiple is only counted once" >:: + ae 2318 (sum ([3; 5]) (100)); + "a much larger limit" >:: + ae 233168 (sum ([3; 5]) (1000)); + "three factors" >:: + ae 51 (sum ([7; 13; 17]) (20)); + "factors not relatively prime" >:: + ae 30 (sum ([4; 6]) (15)); + "some pairs of factors relatively prime and some not" >:: + ae 4419 (sum ([5; 6; 8]) (150)); + "one factor is a multiple of another" >:: + ae 275 (sum ([5; 25]) (51)); + "much larger factors" >:: + ae 2203160 (sum ([43; 47]) (10000)); + "all numbers are multiples of 1" >:: + ae 4950 (sum ([1]) (100)); + "no factors means an empty sum" >:: + ae 0 (sum ([]) (10000)); + "the only multiple of 0 is 0" >:: + ae 0 (sum ([0]) (1)); + "the factor 0 does not affect the sum of multiples of other factors" >:: + ae 3 (sum ([3; 0]) (4)); + "solutions using include-exclude must extend to cardinality greater than 3" >:: + ae 39614537 (sum ([2; 3; 5; 7; 11]) (10000)); +] + +let () = + run_test_tt_main ("sum-of-multiples tests" >::: tests) diff --git a/templates/sum-of-multiples/dune-project.tpl b/templates/sum-of-multiples/dune-project.tpl new file mode 100644 index 000000000..7655de077 --- /dev/null +++ b/templates/sum-of-multiples/dune-project.tpl @@ -0,0 +1 @@ +(lang dune 1.1) diff --git a/templates/sum-of-multiples/test.ml.tpl b/templates/sum-of-multiples/test.ml.tpl new file mode 100644 index 000000000..831aaf2e0 --- /dev/null +++ b/templates/sum-of-multiples/test.ml.tpl @@ -0,0 +1,15 @@ +open OUnit2 +open Sum_of_multiples + +let ae expected actual _test_ctxt = + assert_equal expected actual ~printer:string_of_int + +let tests = [ + {{#cases}} + "{{description}}" >:: + ae {{#input}}{{expected}} (sum ({{factors}}) ({{limit}})){{/input}}; + {{/cases}} +] + +let () = + run_test_tt_main ("sum-of-multiples tests" >::: tests)