diff --git a/config.json b/config.json index 38d7588..6aac915 100644 --- a/config.json +++ b/config.json @@ -197,6 +197,14 @@ "practices": [], "prerequisites": [], "difficulty": 3 + }, + { + "slug": "perfect-numbers", + "name": "Perfect Numbers", + "uuid": "dbf1655b-c3d3-4443-8862-db4e6c3136e4", + "practices": [], + "prerequisites": [], + "difficulty": 3 }, { "slug": "protein-translation", diff --git a/exercises/practice/perfect-numbers/.docs/instructions.md b/exercises/practice/perfect-numbers/.docs/instructions.md new file mode 100644 index 0000000..0dae886 --- /dev/null +++ b/exercises/practice/perfect-numbers/.docs/instructions.md @@ -0,0 +1,24 @@ +# Instructions + +Determine if a number is perfect, abundant, or deficient based on +Nicomachus' (60 - 120 CE) classification scheme for positive integers. + +The Greek mathematician [Nicomachus][nicomachus] devised a classification scheme for positive integers, identifying each as belonging uniquely to the categories of **perfect**, **abundant**, or **deficient** based on their [aliquot sum][aliquot-sum]. +The aliquot sum is defined as the sum of the factors of a number not including the number itself. +For example, the aliquot sum of 15 is (1 + 3 + 5) = 9 + +- **Perfect**: aliquot sum = number + - 6 is a perfect number because (1 + 2 + 3) = 6 + - 28 is a perfect number because (1 + 2 + 4 + 7 + 14) = 28 +- **Abundant**: aliquot sum > number + - 12 is an abundant number because (1 + 2 + 3 + 4 + 6) = 16 + - 24 is an abundant number because (1 + 2 + 3 + 4 + 6 + 8 + 12) = 36 +- **Deficient**: aliquot sum < number + - 8 is a deficient number because (1 + 2 + 4) = 7 + - Prime numbers are deficient + +Implement a way to determine whether a given number is **perfect**. +Depending on your language track, you may also need to implement a way to determine whether a given number is **abundant** or **deficient**. + +[nicomachus]: https://en.wikipedia.org/wiki/Nicomachus +[aliquot-sum]: https://en.wikipedia.org/wiki/Aliquot_sum diff --git a/exercises/practice/perfect-numbers/.meta/config.json b/exercises/practice/perfect-numbers/.meta/config.json new file mode 100644 index 0000000..d80b2f3 --- /dev/null +++ b/exercises/practice/perfect-numbers/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "perfect-numbers.arr" + ], + "test": [ + "perfect-numbers-test.arr" + ], + "example": [ + ".meta/example.arr" + ] + }, + "blurb": "Determine if a number is perfect, abundant, or deficient based on Nicomachus' (60 - 120 CE) classification scheme for positive integers.", + "source": "Taken from Chapter 2 of Functional Thinking by Neal Ford.", + "source_url": "https://www.oreilly.com/library/view/functional-thinking/9781449365509/" +} diff --git a/exercises/practice/perfect-numbers/.meta/example.arr b/exercises/practice/perfect-numbers/.meta/example.arr new file mode 100644 index 0000000..4ce9c70 --- /dev/null +++ b/exercises/practice/perfect-numbers/.meta/example.arr @@ -0,0 +1,38 @@ +provide: classify end + +import lists as L + +fun classify(number :: NumInteger) -> String: + if number <= 0: + raise("Classification is only possible for positive integers.") + else if number == 1: + "deficient" # Can't range from 2 to 1 + else: + stop = num-truncate(num-to-rational(num-sqrt(number))) + 1 + start = if stop < 2: stop else: 2 end + + aliquot-sum = L.range(start, stop).foldl( + lam(elt, acc): + if num-modulo(number, elt) == 0: + increment = + if (elt * elt) <> number: + elt + num-truncate(number / elt) + else: + elt + end + acc + increment + else: + acc + end + end, + 1) + + if aliquot-sum < number: + "deficient" + else if aliquot-sum == number: + "perfect" + else: + "abundant" + end + end +end diff --git a/exercises/practice/perfect-numbers/.meta/tests.toml b/exercises/practice/perfect-numbers/.meta/tests.toml new file mode 100644 index 0000000..ec28889 --- /dev/null +++ b/exercises/practice/perfect-numbers/.meta/tests.toml @@ -0,0 +1,49 @@ +# 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. + +[163e8e86-7bfd-4ee2-bd68-d083dc3381a3] +description = "Perfect numbers -> Smallest perfect number is classified correctly" + +[169a7854-0431-4ae0-9815-c3b6d967436d] +description = "Perfect numbers -> Medium perfect number is classified correctly" + +[ee3627c4-7b36-4245-ba7c-8727d585f402] +description = "Perfect numbers -> Large perfect number is classified correctly" + +[80ef7cf8-9ea8-49b9-8b2d-d9cb3db3ed7e] +description = "Abundant numbers -> Smallest abundant number is classified correctly" + +[3e300e0d-1a12-4f11-8c48-d1027165ab60] +description = "Abundant numbers -> Medium abundant number is classified correctly" + +[ec7792e6-8786-449c-b005-ce6dd89a772b] +description = "Abundant numbers -> Large abundant number is classified correctly" + +[e610fdc7-2b6e-43c3-a51c-b70fb37413ba] +description = "Deficient numbers -> Smallest prime deficient number is classified correctly" + +[0beb7f66-753a-443f-8075-ad7fbd9018f3] +description = "Deficient numbers -> Smallest non-prime deficient number is classified correctly" + +[1c802e45-b4c6-4962-93d7-1cad245821ef] +description = "Deficient numbers -> Medium deficient number is classified correctly" + +[47dd569f-9e5a-4a11-9a47-a4e91c8c28aa] +description = "Deficient numbers -> Large deficient number is classified correctly" + +[a696dec8-6147-4d68-afad-d38de5476a56] +description = "Deficient numbers -> Edge case (no factors other than itself) is classified correctly" + +[72445cee-660c-4d75-8506-6c40089dc302] +description = "Invalid inputs -> Zero is rejected (as it is not a positive integer)" + +[2d72ce2c-6802-49ac-8ece-c790ba3dae13] +description = "Invalid inputs -> Negative integer is rejected (as it is not a positive integer)" diff --git a/exercises/practice/perfect-numbers/perfect-numbers-test.arr b/exercises/practice/perfect-numbers/perfect-numbers-test.arr new file mode 100644 index 0000000..952b764 --- /dev/null +++ b/exercises/practice/perfect-numbers/perfect-numbers-test.arr @@ -0,0 +1,53 @@ +include file("perfect-numbers.arr") + +check "Perfect numbers -> Smallest perfect number is classified correctly": + classify(6) is "perfect" +end + +check "Perfect numbers -> Medium perfect number is classified correctly": + classify(28) is "perfect" +end + +check "Perfect numbers -> Large perfect number is classified correctly": + classify(33550336) is "perfect" +end + +check "Abundant numbers -> Smallest abundant number is classified correctly": + classify(12) is "abundant" +end + +check "Abundant numbers -> Medium abundant number is classified correctly": + classify(30) is "abundant" +end + +check "Abundant numbers -> Large abundant number is classified correctly": + classify(33550335) is "abundant" +end + +check "Deficient numbers -> Smallest prime deficient number is classified correctly": + classify(2) is "deficient" +end + +check "Deficient numbers -> Smallest non-prime deficient number is classified correctly": + classify(4) is "deficient" +end + +check "Deficient numbers -> Medium deficient number is classified correctly": + classify(32) is "deficient" +end + +check "Deficient numbers -> Large deficient number is classified correctly": + classify(33550337) is "deficient" +end + +check "Deficient numbers -> Edge case (no factors other than itself) is classified correctly": + classify(1) is "deficient" +end + +check "Invalid inputs -> Zero is rejected (as it is not a positive integer)": + classify(0) raises "Classification is only possible for positive integers." +end + +check "Invalid inputs -> Negative integer is rejected (as it is not a positive integer)": + classify(-1) raises "Classification is only possible for positive integers." +end diff --git a/exercises/practice/perfect-numbers/perfect-numbers.arr b/exercises/practice/perfect-numbers/perfect-numbers.arr new file mode 100644 index 0000000..a69aad0 --- /dev/null +++ b/exercises/practice/perfect-numbers/perfect-numbers.arr @@ -0,0 +1,5 @@ +provide: classify end + +fun classify(number): + raise("Please implement the classify function") +end