diff --git a/config.json b/config.json index 6affe65..cec1686 100644 --- a/config.json +++ b/config.json @@ -322,6 +322,14 @@ "prerequisites": [], "difficulty": 3 }, + { + "slug": "perfect-numbers", + "name": "Perfect Numbers", + "uuid": "ad78ef27-70a9-4625-b432-742f75cae29c", + "practices": [], + "prerequisites": [], + "difficulty": 3 + }, { "slug": "phone-number", "name": "Phone Number", diff --git a/exercises/practice/perfect-numbers/.busted b/exercises/practice/perfect-numbers/.busted new file mode 100644 index 0000000..86b84e7 --- /dev/null +++ b/exercises/practice/perfect-numbers/.busted @@ -0,0 +1,5 @@ +return { + default = { + ROOT = { '.' } + } +} diff --git a/exercises/practice/perfect-numbers/.docs/instructions.md b/exercises/practice/perfect-numbers/.docs/instructions.md new file mode 100644 index 0000000..b2bc82c --- /dev/null +++ b/exercises/practice/perfect-numbers/.docs/instructions.md @@ -0,0 +1,39 @@ +# 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](#perfect), [abundant](#abundant), or [deficient](#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 + +A number is perfect when it equals its aliquot sum. +For example: + +- `6` is a perfect number because `1 + 2 + 3 = 6` +- `28` is a perfect number because `1 + 2 + 4 + 7 + 14 = 28` + +## Abundant + +A number is abundant when it is less than its aliquot sum. +For example: + +- `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 + +A number is deficient when it is greater than its aliquot sum. +For example: + +- `8` is a deficient number because `1 + 2 + 4 = 7` +- Prime numbers are deficient + +## Task + +Implement a way to determine whether a given number is [perfect](#perfect). +Depending on your language track, you may also need to implement a way to determine whether a given number is [abundant](#abundant) or [deficient](#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..7502e8f --- /dev/null +++ b/exercises/practice/perfect-numbers/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "glennj" + ], + "files": { + "solution": [ + "perfect_numbers.moon" + ], + "test": [ + "perfect_numbers_spec.moon" + ], + "example": [ + ".meta/example.moon" + ] + }, + "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.moon b/exercises/practice/perfect-numbers/.meta/example.moon new file mode 100644 index 0000000..f1259cc --- /dev/null +++ b/exercises/practice/perfect-numbers/.meta/example.moon @@ -0,0 +1,28 @@ +import fold from require 'moon' + +aliquot_sum = (number) -> + factors = {} + f = 1 + while f * f <= number + g = number // f + if g * f == number + table.insert factors, f + if g != f + table.insert factors, g + f += 1 + -- the sum of the factors not including the number + fold(factors, (sum, num) -> sum + num) - number + +{ + classify: (number) -> + assert number > 0, 'Classification is only possible for positive integers.' + + sum = aliquot_sum number + if sum == number + 'perfect' + elseif sum < number + 'deficient' + else + 'abundant' +} + diff --git a/exercises/practice/perfect-numbers/.meta/spec_generator.moon b/exercises/practice/perfect-numbers/.meta/spec_generator.moon new file mode 100644 index 0000000..ef2f14c --- /dev/null +++ b/exercises/practice/perfect-numbers/.meta/spec_generator.moon @@ -0,0 +1,15 @@ +{ + module_imports: {'classify'}, + + generate_test: (case, level) -> + lines = if case.expected.error + { + "func = -> #{case.property} #{case.input.number}", + "assert.has.error func, #{quote case.expected.error}" + } + else + { + "assert.are.equal #{quote case.expected}, #{case.property} #{case.input.number}" + } + table.concat [indent line, level for line in *lines], '\n' +} diff --git a/exercises/practice/perfect-numbers/.meta/tests.toml b/exercises/practice/perfect-numbers/.meta/tests.toml new file mode 100644 index 0000000..81d4840 --- /dev/null +++ b/exercises/practice/perfect-numbers/.meta/tests.toml @@ -0,0 +1,52 @@ +# 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" + +[05f15b93-849c-45e9-9c7d-1ea131ef7d10] +description = "Abundant numbers -> Perfect square 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.moon b/exercises/practice/perfect-numbers/perfect_numbers.moon new file mode 100644 index 0000000..904812a --- /dev/null +++ b/exercises/practice/perfect-numbers/perfect_numbers.moon @@ -0,0 +1,4 @@ +{ + classify: (number) -> + error 'Implement me' +} diff --git a/exercises/practice/perfect-numbers/perfect_numbers_spec.moon b/exercises/practice/perfect-numbers/perfect_numbers_spec.moon new file mode 100644 index 0000000..e579a46 --- /dev/null +++ b/exercises/practice/perfect-numbers/perfect_numbers_spec.moon @@ -0,0 +1,50 @@ +import classify from require 'perfect_numbers' + +describe 'perfect-numbers', -> + describe 'Perfect numbers', -> + it 'Smallest perfect number is classified correctly', -> + assert.are.equal 'perfect', classify 6 + + pending 'Medium perfect number is classified correctly', -> + assert.are.equal 'perfect', classify 28 + + pending 'Large perfect number is classified correctly', -> + assert.are.equal 'perfect', classify 33550336 + + describe 'Abundant numbers', -> + pending 'Smallest abundant number is classified correctly', -> + assert.are.equal 'abundant', classify 12 + + pending 'Medium abundant number is classified correctly', -> + assert.are.equal 'abundant', classify 30 + + pending 'Large abundant number is classified correctly', -> + assert.are.equal 'abundant', classify 33550335 + + pending 'Perfect square abundant number is classified correctly', -> + assert.are.equal 'abundant', classify 196 + + describe 'Deficient numbers', -> + pending 'Smallest prime deficient number is classified correctly', -> + assert.are.equal 'deficient', classify 2 + + pending 'Smallest non-prime deficient number is classified correctly', -> + assert.are.equal 'deficient', classify 4 + + pending 'Medium deficient number is classified correctly', -> + assert.are.equal 'deficient', classify 32 + + pending 'Large deficient number is classified correctly', -> + assert.are.equal 'deficient', classify 33550337 + + pending 'Edge case (no factors other than itself) is classified correctly', -> + assert.are.equal 'deficient', classify 1 + + describe 'Invalid inputs', -> + pending 'Zero is rejected (as it is not a positive integer)', -> + func = -> classify 0 + assert.has.error func, 'Classification is only possible for positive integers.' + + pending 'Negative integer is rejected (as it is not a positive integer)', -> + func = -> classify -1 + assert.has.error func, 'Classification is only possible for positive integers.'