From 11e3f84ddbd365a4c34d595daa5a2a74690afed0 Mon Sep 17 00:00:00 2001 From: Satin Wuker <74630829+SatinWuker@users.noreply.github.com> Date: Tue, 20 Jun 2023 03:55:52 -0700 Subject: [PATCH 01/12] Update CONTRIBUTING.md Fixing grammatical mistakes --- CONTRIBUTING.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 548fc570..9ae75ca6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ Welcome to [TheAlgorithms/Nim](https://github.com/TheAlgorithms/Nim)! -We are very happy that you are considering working on algorithm and data structure implementations in Nim! This repository is meant to be referenced and used by learners from all over the globe, and we aspire to maintain the highest possible quality of the code presented here. This is why we ask you to **read all of the following guidelines beforehand** to know what we expect of your contributions. If you have any doubts about this guide, please feel free to [state them clearly in an issue](https://github.com/TheAlgorithms/Nim/issues/new) or ask the community in [Discord](https://the-algorithms.com/discord). +We are very happy that you are considering working on the algorithm and data structure implementations in Nim! This repository is meant to be referenced and used by learners from all over the globe, and we aspire to maintain the highest possible quality of the code presented here. This is why we ask you to **read all of the following guidelines beforehand** to know what we expect of your contributions. If you have any doubts about this guide, please feel free to [state them clearly in an issue](https://github.com/TheAlgorithms/Nim/issues/new) or ask the community in [Discord](https://the-algorithms.com/discord). ## Table Of Contents @@ -29,7 +29,7 @@ An Algorithm is one or more functions that: - return one or more outputs, - have minimal side effects (Examples of side effects: `echo()`, `rand()`, `read()`, `write()`). -## Contributor agreement +## Contributor Agreement Being one of our contributors, you agree and confirm that: @@ -40,7 +40,7 @@ Being one of our contributors, you agree and confirm that: We appreciate any contribution, from fixing a grammar mistake in a comment to implementing complex algorithms. Please check the [directory](directory.md) and [issues](https://github.com/TheAlgorithms/Nim/issues/) for an existing (or declined) implementation of your algorithm and relevant discussions. -**New implementations** are welcome! This includes: new solutions for a problem, different representations for a data structure, algorithm design with a different complexity or features. +**New implementations** are welcome! This includes: new solutions for a problem, different representations for a data structure, and algorithm design with different complexity or features. **Improving documentation and comments** and **adding tests** is also highly welcome. @@ -48,20 +48,20 @@ We appreciate any contribution, from fixing a grammar mistake in a comment to im ### Implementation requirements -- The unit of an implementation we expect is a [**Nim module**](https://nim-lang.org/docs/manual.html#modules). Although the main goals of this repository are educational, the module form mirrors a real world scenario and makes it easy to use the code from this repository in other projects. -- First line must contain the canonical title of the module prefixed by double hashes (`## Title Of The Module`). This title is used in this repository's automation for populating the [Directory](directory.md). +- The unit of implementation we expect is a [**Nim module**](https://nim-lang.org/docs/manual.html#modules). Although the main goals of this repository are educational, the module form mirrors a real-world scenario and makes it easy to use the code from this repository in other projects. +- The first line must contain the canonical title of the module prefixed by double hashes (`## Title Of The Module`). This title is used in this repository's automation for populating the [Directory](directory.md). - The module should be thoroughly documented with doc comments. Follow the [Nim documentation style](https://nim-lang.org/docs/docstyle.html). - The file begins with the module-level documentation with the general description and explanation of the algorithm/data-structure. If possible, please include: * Any restrictions of the implementation and any constraints for the input data. - * An overview of the use-cases. + * An overview of the use cases. * Recommendations for when to use or avoid using it. * Comparison with the alternatives. * Links to source materials and further reading. - Use intuitive and descriptive names for objects, functions, and variables. - Return all calculation results instead of printing or plotting them. -- This repository is not simply a compilation of *how-to* examples for existing Nim packages and routines. Each algorithm implementation should add unique value. It is fine to leverage the standard library or third-party packages as long as it doesn't substitute writing the algorithm itself. In other words, you don't need to reimplement a basic hash table ([`std/tables`](https://nim-lang.org/docs/tables.html)) each time you need to use it, unless it is the goal of the module. +- This repository is not simply a compilation of *how-to* examples for existing Nim packages and routines. Each algorithm implementation should add unique value. It is fine to leverage the standard library or third-party packages as long as it doesn't substitute writing the algorithm itself. In other words, you don't need to reimplement a basic hash table ([`std/tables`](https://nim-lang.org/docs/tables.html)) each time you need to use it unless it is the goal of the module. - Avoid importing third-party libraries. Only use those for complicated algorithms and only if the alternatives of relying on the standard library or including a short amount of the appropriately-licensed external code are not feasible. -- The module has to include tests that check valid and erroneous input values and the appropriate edge-cases. See [Documentation, examples and tests](#documentation-examples-and-tests) below. +- The module has to include tests that check valid and erroneous input values and the appropriate edge cases. See [Documentation, examples and tests](#documentation-examples-and-tests) below. ### Nim Coding Style @@ -71,7 +71,7 @@ We want your work to be readable by others; therefore, we encourage you to follo - Help your readers by using **descriptive names** that eliminate the need for redundant comments. - Follow Nim conventions for naming: camelCase for variables and functions, PascalCase for types and objects, PascalCase or UPPERCASE for constants. -- Avoid single-letter variable names, unless it has a minimal lifespan. If your variable comes from a mathematical context or no confusion is possible with another variable, you may use single-letter variables. Generally, single-letter variables stop being OK if there's more than just a couple of them in a scope. Some examples: +- Avoid single-letter variable names, unless it has a minimal lifespan. If your variable comes from a mathematical context or no confusion is possible with another variable, you may use single-letter variables. Generally, single-letter variables stop being OK if there are more than just a couple of them in scope. Some examples: * Prefer `index` or `idx` to `i` for loops. * Prefer `src` and `dst` to `a` and `b`. * Prefer `remainder` to `r` and `prefix` to `p`. @@ -83,9 +83,9 @@ We want your work to be readable by others; therefore, we encourage you to follo #### Types -- Use the strictest types possible for the input, output and object fields. Prefer `Natural`, `Positive` or custom [subrange types](https://nim-lang.org/docs/manual.html#types-subrange-types) to unconstrained `int` where applicable, use `Natural` for indexing. +- Use the strictest types possible for the input, output, and object fields. Prefer `Natural`, `Positive` or custom [subrange types](https://nim-lang.org/docs/manual.html#types-subrange-types) to unconstrained `int` where applicable, use `Natural` for indexing. - On the other hand, write generic code where appropriate. Do not impose arbitrary limitations if the code can work on a wider range of data types. -- Don't use unsigned numerical types (`uint` and its sized variants), unless wrapping behaviour or binary manipulation is required for the algorithm. +- Don't use unsigned numerical types (`uint` and its sized variants), unless wrapping behavior or binary manipulation is required for the algorithm. - Prefer the [`Option[T]`](https://nim-lang.org/docs/options.html) to encode an [optional value](https://en.wikipedia.org/wiki/Option_type) instead of using an invalid value (like the `-1` or an empty string `""`), unless it is critical for the algorithm. It may be also fitting if you are looking for the equivalent of "NULL" (default value for pointers)[^null]. #### Exceptions and side-effects @@ -93,7 +93,7 @@ We want your work to be readable by others; therefore, we encourage you to follo - Raise Nim exceptions (`ValueError`, etc.) on erroneous input values. - Use [exception tracking](https://nim-lang.org/docs/manual.html#effect-system-exception-tracking). Right after the module-level documentation, add a `{.push raises: [].}` module pragma. This enforces that all `func`s don't raise any exceptions. If they do raise at least one, list them all with the `raises` pragma after the return type and before the `=` sign like this: `func foo(bar: int) {.raises: [IOError].} =`. -#### Documentation, examples and tests +#### Documentation, examples, and tests - It is incited to give a usage example after the module documentation and the `push raises` pragma in the top-level `runnableExamples` block. - Use the [`std/unittest` module](https://nim-lang.org/docs/unittest.html) to test your program. @@ -135,11 +135,11 @@ when isMainModule: ### Submissions Requirements - Make sure the code compiles before submitting. -- Look up the name of your algorithm in other active repositories of [TheAlgorithms](https://github.com/TheAlgorithms/), like [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python). By reusing the same name, your implementation will be appropriately grouped alongside other implementations on the [project's web site](https://the-algorithms.com/). +- Look up the name of your algorithm in other active repositories of [TheAlgorithms](https://github.com/TheAlgorithms/), like [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python). By reusing the same name, your implementation will be appropriately grouped alongside other implementations on the [project's website](https://the-algorithms.com/). - Please help us keep our issue list small by adding fixes: Add the number of the issue you solved — even if only partially — to the commit message of your pull request. - Use *snake_case* (words separated with an underscore `_`) for the filename. - Try to fit your work into the existing directory structure as much as possible. Please open an issue first if you want to create a new subdirectory. -- Writing documentation, be concise and check your spelling and grammar. +- Writing documentation, be concise, and check your spelling and grammar. - Add a corresponding explanation to [Algorithms-Explanation](https://github.com/TheAlgorithms/Algorithms-Explanation) (optional but recommended). - Most importantly, **be consistent in the use of these guidelines**. From 51558e61b9a42e08de3147385b3351f90737d0f9 Mon Sep 17 00:00:00 2001 From: Satin Wuker <74630829+SatinWuker@users.noreply.github.com> Date: Tue, 20 Jun 2023 04:16:04 -0700 Subject: [PATCH 02/12] Update check_anagram.nim, fixing grammar By Grammarly --- strings/check_anagram.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/strings/check_anagram.nim b/strings/check_anagram.nim index 9a3ef7ba..433ce0e3 100644 --- a/strings/check_anagram.nim +++ b/strings/check_anagram.nim @@ -9,7 +9,7 @@ ## - They are not the same word (a word is not an anagram of itself). ## ## A word is any string of characters `{'A'..'Z', 'a'..'z'}`. Other characters, -## including whitespace, numbers and punctuation, are considered invalid and +## including whitespace, numbers, and punctuation, are considered invalid and ## raise a `ValueError` exception. ## ## Note: Generate full doc with `nim doc --docinternal check_anagram.nim` @@ -56,7 +56,7 @@ func toLowerUnchecked(c: char): char {.inline.} = assert c in UpperAlpha # The difference between numerical values for chars of uppercase and # lowercase alphabets in the ASCII table is 32. Uppercase letters start from - # 0b100_0001, so setting the sixth bit to 1 gives letter's lowercase pair. + # 0b100_0001, so setting the sixth bit to 1 gives the letter's lowercase pair. char(uint8(c) or 0b0010_0000'u8) template normalizeChar(c: char) = From 56ae4c79d2c0de16c2588d17a43be07a6a98e133 Mon Sep 17 00:00:00 2001 From: Satin Wuker <74630829+SatinWuker@users.noreply.github.com> Date: Tue, 20 Jun 2023 04:18:38 -0700 Subject: [PATCH 03/12] Update catalan_numbers.nim, fixing typos --- dynamic_programming/catalan_numbers.nim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dynamic_programming/catalan_numbers.nim b/dynamic_programming/catalan_numbers.nim index 84eaa990..24ced1fb 100644 --- a/dynamic_programming/catalan_numbers.nim +++ b/dynamic_programming/catalan_numbers.nim @@ -1,7 +1,7 @@ # Catalan Numbers #[ The Catalan numbers are a sequence of natural numbers that occur in the - most large set of combinatorial problems. + the largest set of combinatorial problems. For example, it describes: - the number of ways to parenthesize a product of n factors - the number of ways to form a binary search tree with n+1 leaves @@ -96,13 +96,13 @@ when isMainModule: doAssert (CatalanNumbersList[i] == createCatalanTable(36)[i]) suite "Catalan Numbers": - test "The seventeen first Catalan numbers recursively, first formula": + test "The seventeen first Catalan numbers recursively, the first formula": let limit = RecursiveLimit for index in 0 .. limit: let catalanNumber = catalanNumbersRecursive(index) check catalanNumber == CatalanNumbersList[index] - test "The thirty-one first Catalan numbers recursively, second formula": + test "The thirty-one first Catalan numbers recursively, the second formula": let limit = LowerLimit for index in 0 .. limit: let catalanNumber = catalanNumbersRecursive2(index) @@ -124,7 +124,7 @@ when isMainModule: check catalanNumber == CatalanNumbersList[index] inc index - test "Test the catalan number function with binomials": + test "Test the Catalan number function with binomials": let limit = LowerLimit for index in 0 .. limit: check catalanNumbers2(index) == CatalanNumbersList[index] From c72bb732bf755424c5c6ddd95a4c8ad6c6fc2ff0 Mon Sep 17 00:00:00 2001 From: Satin Wuker <74630829+SatinWuker@users.noreply.github.com> Date: Tue, 20 Jun 2023 04:25:57 -0700 Subject: [PATCH 04/12] Update viterbi.nim Adding description and reference to the Viterbi Algorithm --- dynamic_programming/viterbi.nim | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dynamic_programming/viterbi.nim b/dynamic_programming/viterbi.nim index d15e3f78..16f1d526 100644 --- a/dynamic_programming/viterbi.nim +++ b/dynamic_programming/viterbi.nim @@ -1,4 +1,14 @@ # Viterbi +## The Viterbi algorithm is a dynamic programming algorithm +## for obtaining the maximum a posteriori probability estimate +## of the most likely sequence of hidden states +## https://en.wikipedia.org/wiki/Viterbi_algorithm +## +## Time Complexity: O(K2n) +## Space Complexity: O(Kn) +## https://www.cs.cmu.edu/~epxing/Class/10708-20/scribe/lec4_scribe.pdf + + {.push raises: [].} type From 521f853725070ad53cb7b73105b16e36ede68ca7 Mon Sep 17 00:00:00 2001 From: dlesnoff <54949944+dlesnoff@users.noreply.github.com> Date: Fri, 23 Jun 2023 22:16:52 +0200 Subject: [PATCH 05/12] Create and populate the Maths directory (#4) * Add a sample of maths basic algorithms * Update maths/abs.nim Co-authored-by: Zoom * Use openArray in absMaxSort Co-authored-by: Zoom * Fix seq->openArray and int->SomeInteger * Use Positive as input instead * Update maths/addition_without_arithmetic.nim Co-authored-by: Pietro Peterlongo * Name allocation number * [maths/abs] Replace maxAbsSort by signed[Min/Max]Abs * [Aliquot Sum] Add header * Add empty line at end of file * Remove Allocation number since it is a non standard algorithm * Fix titles * Run nimpretty on the files * Rename file and add DIRECTORY.md * abs: Fix variable name * Add export marker Co-authored-by: Zoom * Add RE block in aliquot sum and improve RE Co-authored-by: Zoom * Remove MD quotation marks for inline code * Add export marker for RE block * Remove extra ValueError --------- Co-authored-by: Dimitri LESNOFF Co-authored-by: Zoom Co-authored-by: Pietro Peterlongo Co-authored-by: David Leal --- DIRECTORY.md | 5 ++ maths/abs.nim | 120 +++++++++++++++++++++++++++++++++++++ maths/aliquot_sum.nim | 31 ++++++++++ maths/bitwise_addition.nim | 38 ++++++++++++ 4 files changed, 194 insertions(+) create mode 100644 maths/abs.nim create mode 100644 maths/aliquot_sum.nim create mode 100644 maths/bitwise_addition.nim diff --git a/DIRECTORY.md b/DIRECTORY.md index 3f37dde1..a3259a7b 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -6,6 +6,11 @@ * [Catalan Numbers](dynamic_programming/catalan_numbers.nim) * [Viterbi](dynamic_programming/viterbi.nim) +## Maths + * [Absolute value](maths/abs.nim) + * [Aliquot sum](maths/aliquot_sum.nim) + * [Bitwise Addition](maths/bitwise_addition.nim) + ## Strings * [Check Anagram](strings/check_anagram.nim) diff --git a/maths/abs.nim b/maths/abs.nim new file mode 100644 index 00000000..ed111faa --- /dev/null +++ b/maths/abs.nim @@ -0,0 +1,120 @@ +## Absolute value +{.push raises: [].} +import std/strutils + +runnableExamples: + assert absVal(-5.1) == 5.1 + assert absMin(@[-1, 2, -3]) == 1 + assert absMax(@[-1, 2, -3]) == 3 + assert signedMinAbs(@[3, -10, -2]) == -2 + assert signedMaxAbs(@[3, -10, -2]) == -10 + +func absVal*[T: SomeFloat](num: T): T = + ## Returns the absolute value of a number. + ## Use `math.abs `_ instead! + return if num < 0.0: -num else: num + +# Same for Integers but returns a Natural +func absVal*[T: SomeInteger](num: T): Natural = (if num < 0: -num else: num) + +func absMin*(x: openArray[int]): Natural {.raises: [ValueError].} = + ## Returns the smallest element in absolute value in a sequence. + if x.len == 0: + raise newException(ValueError, """Cannot find absolute minimum + of an empty sequence""".unindent) + result = absVal(x[0]) + for i in 1 ..< x.len: + if absVal(x[i]) < result: + result = absVal(x[i]) + +func absMax*(x: openArray[int]): Natural {.raises: [ValueError].} = + ## Returns the largest element in absolute value in a sequence. + if x.len == 0: + raise newException(ValueError, """Cannot find absolute maximum of an empty + sequence""".unindent) + result = absVal(x[0]) + for i in 1 ..< x.len: + if absVal(x[i]) > result: + result = absVal(x[i]) + +func signedMinAbs*(x: openArray[int]): int {.raises: [ValueError].} = + ## Returns the first signed element whose absolute value + ## is the smallest in a sequence. + if x.len == 0: + raise newException(ValueError, """Cannot find absolute maximum of an empty + sequence""".unindent) + var (min, minAbs) = (x[0], absVal(x[0])) + for n in x: + let nAbs = absVal(n) + if nAbs < minAbs: (min, minAbs) = (n, nAbs) + min + +func signedMaxAbs*(x: openArray[int]): int {.raises: [ValueError].} = + ## Returns the first signed element whose absolute value + ## is the largest in a sequence. + if x.len == 0: + raise newException(ValueError, """Cannot find absolute maximum of an empty + sequence""".unindent) + var (max, maxAbs) = (x[0], absVal(x[0])) + for n in x: + let nAbs = absVal(n) + if nAbs > maxAbs: (max, maxAbs) = (n, nAbs) + max + +when isMainModule: + import std/[unittest, random] + randomize() + + suite "Check absVal": + test "Check absVal": + check: + absVal(11.2) == 11.2 + absVal(5) == 5 + absVal(-5.1) == 5.1 + absVal(-5) == absVal(5) + absVal(0) == 0 + + suite "Check absMin": + test "Check absMin": + check: + absMin(@[-1, 2, -3]) == 1 + absMin(@[0, 5, 1, 11]) == 0 + absMin(@[3, -10, -2]) == 2 + absMin([-1, 2, -3]) == 1 + absMin([0, 5, 1, 11]) == 0 + absMin([3, -10, -2]) == 2 + + test "absMin on empty sequence raises ValueError": + doAssertRaises(ValueError): + discard absMin(@[]) + + suite "Check absMax": + test "Check absMax": + check: + absMax(@[0, 5, 1, 11]) == 11 + absMax(@[3, -10, -2]) == 10 + absMax(@[-1, 2, -3]) == 3 + + test "`absMax` on empty sequence raises ValueError": + doAssertRaises(ValueError): + discard absMax(@[]) + + suite "Check signedMinAbs": + test "Check signedMinAbs": + check: + signedMinAbs(@[0, 5, 1, 11]) == 0 + signedMinAbs(@[3, -2, 1, -4, 5, -6]) == 1 + signedMinAbs(@[3, -2, -1, -4, 5, -6]) == -1 + + test "Among two minimal elements, the first one is returned": + check signedMinAbs(@[3, -2, 1, -4, 5, -6, -1]) == 1 + + suite "Check signedMaxAbs": + test "Check signedMaxAbs": + check: + signedMaxAbs(@[3, -2, 1, -4, 5, -6]) == -6 + signedMaxAbs(@[0, 5, 1, 11]) == 11 + + test "signedMaxAbs on empty sequence raises ValueError": + doAssertRaises(ValueError): + discard signedMaxAbs(@[]) diff --git a/maths/aliquot_sum.nim b/maths/aliquot_sum.nim new file mode 100644 index 00000000..711e24d6 --- /dev/null +++ b/maths/aliquot_sum.nim @@ -0,0 +1,31 @@ +## Aliquot sum +## In number theory, the aliquot sum s(n) of a positive integer n is the sum of +## all proper divisors of n, that is, all divisors of n other than n itself. +## https://en.wikipedia.org/wiki/Aliquot_sum + +runnableExamples: + import std/strformat + const expected = [16, 117] + for i, number in [12, 100].pairs(): + let sum = aliquotSum(number) + assert sum == expected[i] + echo fmt"The sum of all the proper divisors of {number} is {sum}" + +func aliquotSum*(number: Positive): Natural = + ## Returns the sum of all the proper divisors of the number + ## Example: aliquotSum(12) = 1 + 2 + 3 + 4 + 6 = 16 + result = 0 + for divisor in 1 .. (number div 2): + if number mod divisor == 0: + result += divisor + +when isMainModule: + import std/unittest + suite "Check aliquotSum": + test "aliquotSum on small values": + var + input = @[1, 2, 9, 12, 27, 100] + expected = @[0, 1, 4, 16, 13, 117] + for i in 0 ..< input.len: + check: + aliquotSum(input[i]) == expected[i] diff --git a/maths/bitwise_addition.nim b/maths/bitwise_addition.nim new file mode 100644 index 00000000..e024f506 --- /dev/null +++ b/maths/bitwise_addition.nim @@ -0,0 +1,38 @@ +## Bitwise Addition +## Illustrate how to implement addition of integers using bitwise operations +## See https://en.wikipedia.org/wiki/Bitwise_operation#Applications +runnableExamples: + import std/strformat + var + a = 5 + b = 6 + echo fmt"The sum of {a} and {b} is {add(a,b)}" + +func add*(first: int, second: int): int = + ## Implementation of addition of integer with `and`, `xor` and `shl` + ## boolean operators. + var first = first + var second = second + while second != 0: + var c = first and second + first = first xor second + second = c shl 1 + return first + +when isMainModule: + import std/unittest + + suite "Check addition": + test "Addition of two positive numbers": + check: + add(3, 5) == 8 + add(13, 5) == 18 + test "Addition of two negative numbers": + check: + add(-7, -2) == -9 + add(-321, -0) == -321 + test "Addition of one positive and one negative number": + check: + add(-7, 2) == -5 + add(-13, 5) == -8 + add(13, -5) == 8 From 41915d6273c5d8b92b706415dfc33aeee7058d4d Mon Sep 17 00:00:00 2001 From: dlesnoff <54949944+dlesnoff@users.noreply.github.com> Date: Fri, 23 Jun 2023 22:18:51 +0200 Subject: [PATCH 06/12] Add arc length (#10) --- maths/arc_length.nim | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 maths/arc_length.nim diff --git a/maths/arc_length.nim b/maths/arc_length.nim new file mode 100644 index 00000000..60385d50 --- /dev/null +++ b/maths/arc_length.nim @@ -0,0 +1,34 @@ +# Arc Length of a Circle +## https://en.wikipedia.org/wiki/Arc_length +import std/math +{.push raises: [].} + +func arcLengthDegree(radius: float, angle: float): float = + ## Calculate the length of an arc given the `radius` and `angle` in degrees. + return PI * radius * (angle / 180) + +func arcLengthRadian(radius: float, angle: float): float = + ## Calculate the length of an arc given the `radius` and `angle` in radians. + return radius * angle + +when isMainModule: + import std/unittest + const UnitsInLastPlace = 1 + suite "Arc Length": + test "radius 5, angle 45": + check almostEqual(arcLengthDegree(5, 45), 3.926990816987241, UnitsInLastPlace) + test "radius 15, angle 120": + check almostEqual(arcLengthDegree(15, 120), 31.41592653589793, UnitsInLastPlace) + test "radius 10, angle 90": + check almostEqual(arcLengthDegree(10, 90), 15.70796326794897, UnitsInLastPlace) + + suite "Arc Length": + test "radius 5, angle 45": + check almostEqual(arcLengthRadian(5, degToRad(45.0)), 3.926990816987241, + UnitsInLastPlace) + test "radius 15, angle 120": + check almostEqual(arcLengthRadian(15, degToRad(120.0)), 31.41592653589793, + UnitsInLastPlace) + test "radius 10, angle 90": + check almostEqual(arcLengthRadian(10, degToRad(90.0)), 15.70796326794897, + UnitsInLastPlace) From 6e2a92621d9e6c93fc12e6bbd877cd73c9954ffb Mon Sep 17 00:00:00 2001 From: dlesnoff <54949944+dlesnoff@users.noreply.github.com> Date: Fri, 23 Jun 2023 22:22:05 +0200 Subject: [PATCH 07/12] Fix linear search (#33) * Use a dynamic allocated array (sequence) for strings * Run nimpretty * Add requested changes * Fix documentation generation * Fix test title according to changes Co-authored-by: Satin Wuker <74630829+SatinWuker@users.noreply.github.com> * Update comments to warn about indexing issues Modified a bit the suggestions of comments. Please check them before approving. Co-authored-by: Zoom --------- Co-authored-by: Dimitri LESNOFF Co-authored-by: Satin Wuker <74630829+SatinWuker@users.noreply.github.com> Co-authored-by: Zoom --- searches/linear_search.nim | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/searches/linear_search.nim b/searches/linear_search.nim index ae2a7484..0b7298fe 100644 --- a/searches/linear_search.nim +++ b/searches/linear_search.nim @@ -16,6 +16,8 @@ ## Therefore the recursive linear search is less efficient than the for-loop-based one. runnableExamples: + import std/options + var arr1 = [0, 3, 1, 4, 5, 6] doAssert linearSearch(arr1, 5) == some(Natural(4)) doAssert recursiveLinearSearch(arr1, 5) == some(Natural(4)) @@ -28,23 +30,25 @@ runnableExamples: doAssert linearSearch(arr3, 7) == none(Natural) doAssert recursiveLinearSearch(arr3, 7) == none(Natural) - import std/options -type - Nat = Natural - OptNat = Option[Natural] - -func linearSearch*[T](arr: openArray[T], key: T): OptNat = - # key is the value we are searching for in the array. +func linearSearch*[T](arr: openArray[T], key: T): Option[Natural] = + ## Searches for the `key` in the array `arr` and returns its absolute index (counting from 0) + ## in the array. + ## .. Note:: For arrays indexed with a range type or an enum the returned value + ## may not be consistent with the indexing of the initial array. for i, val in arr.pairs(): if val == key: return some(Natural(i)) none(Natural) # `key` not found -func recursiveLinearSearch*[T](arr: openArray[T], key: T, idx: Nat = arr.low.Nat): OptNat= - # Recursion is another method for linear search. - # Recursive calls replace the for loop. +func recursiveLinearSearch*[T]( + arr: openArray[T], key: T, idx: Natural = Natural(0)): Option[Natural] = + ## Searches for the `key` in `arr` and returns its absolute index (counting from 0) + ## in the array. Search is performed in a recursive manner. + ## .. Note:: For arrays indexed with a range type or an enum the returned value + ## is not consistent with the indexing of the parameter array if `arr.low` is not 0. + # Recursive calls replace the `for` loop in `linearSearch`. # `none(Natural)` is returned when the array is traversed completely # and no key is matched, or when `arr` is empty. @@ -58,7 +62,8 @@ func recursiveLinearSearch*[T](arr: openArray[T], key: T, idx: Nat = arr.low.Nat when isMainModule: import unittest - template checkLinearSearch[T](arr: openArray[T], key: T, expectedIdx: OptNat): untyped = + template checkLinearSearch[T](arr: openArray[T], key: T, + expectedIdx: Option[Natural]): untyped = check linearSearch(arr, key) == expectedIdx check recursiveLinearSearch(arr, key) == expectedIdx @@ -79,8 +84,8 @@ when isMainModule: var arr = ['0', 'c', 'a', 'u', '5', '7'] checkLinearSearch(arr, '5', some(Natural(4))) - test "Search in a string array matching with a string matching value": - var arr = ["0", "c", "a", "u", "5", "7"] + test "Search in a string sequence matching with a string matching value": + var arr = @["0", "c", "a", "u", "5", "7"] checkLinearSearch(arr, "5", some(Natural(4))) test "Search in an int array with a valid key at the end": From 07bfb638620ba2a610786037ea75569c84131737 Mon Sep 17 00:00:00 2001 From: David Leal Date: Fri, 23 Jun 2023 14:44:26 -0600 Subject: [PATCH 08/12] chore: run `apt-get update` before running other commands (#41) This will run `sudo apt-get update` before running any other commands on the Gitpod prebuild image (`.gitpod.dockerfile`). --- .gitpod.dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitpod.dockerfile b/.gitpod.dockerfile index 5c33d0ac..c14b2bb8 100644 --- a/.gitpod.dockerfile +++ b/.gitpod.dockerfile @@ -1,6 +1,6 @@ FROM gitpod/workspace-base -RUN curl https://nim-lang.org/choosenim/init.sh -sSf -o install_nim.sh \ +RUN sudo apt-get update && curl https://nim-lang.org/choosenim/init.sh -sSf -o install_nim.sh \ && chmod +x ./install_nim.sh \ && ./install_nim.sh -y \ && rm install_nim.sh \ From 8e5530da1e28b077d12825a914cc2aba6f3c90a4 Mon Sep 17 00:00:00 2001 From: Zoom Date: Fri, 23 Jun 2023 22:35:27 +0000 Subject: [PATCH 09/12] Readme: fix gitter link, add Nim logo, formatting fixes (#42) * Update README.md Use more extended markdown syntax instead of HTML, Add Matrix links Superseed PR #40 * Actually fix gitter! Move img src links to footer. Also changed the TheAlgorithms logo image link. * Restore TheAlgorithms logo link * More link fixes --------- Co-authored-by: dlesnoff <54949944+dlesnoff@users.noreply.github.com> --- README.md | 58 +++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index d075c6c4..1cd9af41 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,14 @@ -
- - - - -

The Algorithms - Nim

- - - - Gitpod Ready-to-Code - - - Contributions Welcome - - - - Discord chat - - - Gitter chat - - -
- -

Algorithms collection implemented in Nim - for education

-
+# The Algorithms – Nim  + +[![Gitpod Ready-to-Code][badge-gitpod]](https://gitpod.io/#https://github.com/TheAlgorithms/Nim) +[![Contributions Welcome][badge-contributions]](https://github.com/TheAlgorithms/Nim/blob/master/CONTRIBUTING.md) +![Repo size][badge-reposize] +
+[![Discord chat][badge-discord]][chat-discord] +[![Gitter chat][badge-gitter]][chat-gitter] +[![Matrix room][badge-matrix]][chat-matrix] + +## Algorithms collection implemented in Nim - for education Implementations are for learning purposes only. They may be less efficient than the implementations in the [Nim standard library](https://nim-lang.org/docs/lib.html) or [Nimble packages](https://nimble.directory/). Use them at your discretion. @@ -31,10 +16,25 @@ Implementations are for learning purposes only. They may be less efficient than Read through our [Contribution Guidelines](CONTRIBUTING.md) before you contribute. +## List of Algorithms + +See our [directory](DIRECTORY.md) for easier navigation and a better overview of the project. + +You can also browse the implementations on [the website](https://the-algorithms.com/language/nim). + ## Community Channels -We are on [Discord](https://the-algorithms.com/discord) and [Gitter](https://gitter.im/TheAlgorithms)! Community channels are a great way for you to ask questions and get help. Please join us! +We are on [Discord](https://the-algorithms.com/discord) and [Gitter][chat-gitter]/[Matrix][chat-matrix]! -## List of Algorithms +Community channels are a great way for you to ask questions and get help. Please join us! -See our [directory](DIRECTORY.md) for easier navigation and a better overview of the project. + +[chat-discord]: https://the-algorithms.com/discord +[chat-gitter]: https://gitter.im/#TheAlgorithms_community:gitter.im +[chat-matrix]: https://matrix.to/#/#TheAlgorithms_community:gitter.im +[badge-contributions]: https://img.shields.io/static/v1.svg?label=Contributions&message=Welcome&color=0059b3&style=flat-square +[badge-discord]: https://img.shields.io/discord/808045925556682782.svg?logo=discord&colorB=7289DA&style=flat-square +[badge-matrix]: https://img.shields.io/badge/matrix-TheAlgorithms_community-0dbd8b?logo=matrix +[badge-gitpod]: https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod&style=flat-square +[badge-gitter]: https://img.shields.io/badge/Chat-Gitter-ff69b4.svg?label=Chat&logo=gitter&style=flat-square +[badge-reposize]: https://img.shields.io/github/repo-size/TheAlgorithms/Nim.svg?label=Repo%20size&style=flat-square From 4dac6037f9de9c905e2faf2ded7cd2c17171f4f8 Mon Sep 17 00:00:00 2001 From: Zoom Date: Fri, 23 Jun 2023 22:51:35 +0000 Subject: [PATCH 10/12] fix: nimpretty for `arc_length.nim` (#43) --- maths/arc_length.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/arc_length.nim b/maths/arc_length.nim index 60385d50..6e79765e 100644 --- a/maths/arc_length.nim +++ b/maths/arc_length.nim @@ -21,7 +21,7 @@ when isMainModule: check almostEqual(arcLengthDegree(15, 120), 31.41592653589793, UnitsInLastPlace) test "radius 10, angle 90": check almostEqual(arcLengthDegree(10, 90), 15.70796326794897, UnitsInLastPlace) - + suite "Arc Length": test "radius 5, angle 45": check almostEqual(arcLengthRadian(5, degToRad(45.0)), 3.926990816987241, From 1fb03e81fcafcfa3936e88db78d71a8f182fbb3a Mon Sep 17 00:00:00 2001 From: Zoom Date: Tue, 27 Jun 2023 07:11:49 +0000 Subject: [PATCH 11/12] chore: `gc`->`mm`, move back to `config.nims` (#47) --- config.nims | 5 ++++- nim.cfg | 2 -- 2 files changed, 4 insertions(+), 3 deletions(-) delete mode 100644 nim.cfg diff --git a/config.nims b/config.nims index ead07a02..0075968e 100644 --- a/config.nims +++ b/config.nims @@ -13,6 +13,8 @@ import std/[os, sequtils] from std/strutils import startsWith, endsWith from std/strformat import `&` +--mm:arc # TODO: check if still needs to be below imports on Nim > 1.6.12 + const IgnorePathPrefixes = ["."] func isIgnored(path: string): bool = @@ -27,12 +29,13 @@ iterator modules(dir: string = getCurrentDir()): string = ############ Tasks task test, "Test everything": + --warning: "BareExcept:off" --hints: off var failedUnits: seq[string] for path in modules(): echo &"Testing {path}:" - try: exec(&"nim --hints:off r \"{path}\"") + try: selfExec(&"-f --warning[BareExcept]:off --hints:off r \"{path}\"") except OSError: failedUnits.add(path) if failedUnits.len > 0: diff --git a/nim.cfg b/nim.cfg deleted file mode 100644 index bba14f1b..00000000 --- a/nim.cfg +++ /dev/null @@ -1,2 +0,0 @@ -# Nim compilation defaults for the whole repository ---gc: arc From 8e618296d64e3a453c0eed795d06a5587447b1c0 Mon Sep 17 00:00:00 2001 From: Piotr Idzik <65706193+vil02@users.noreply.github.com> Date: Tue, 27 Jun 2023 09:18:07 +0200 Subject: [PATCH 12/12] chore: revert #41 (#45) --- .gitpod.dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitpod.dockerfile b/.gitpod.dockerfile index c14b2bb8..5c33d0ac 100644 --- a/.gitpod.dockerfile +++ b/.gitpod.dockerfile @@ -1,6 +1,6 @@ FROM gitpod/workspace-base -RUN sudo apt-get update && curl https://nim-lang.org/choosenim/init.sh -sSf -o install_nim.sh \ +RUN curl https://nim-lang.org/choosenim/init.sh -sSf -o install_nim.sh \ && chmod +x ./install_nim.sh \ && ./install_nim.sh -y \ && rm install_nim.sh \