Skip to content

Commit

Permalink
Create and populate the Maths directory (TheAlgorithms#4)
Browse files Browse the repository at this point in the history
* Add a sample of maths basic algorithms

* Update maths/abs.nim

Co-authored-by: Zoom <[email protected]>

* Use openArray in absMaxSort

Co-authored-by: Zoom <[email protected]>

* Fix seq->openArray and int->SomeInteger

* Use Positive as input instead

* Update maths/addition_without_arithmetic.nim

Co-authored-by: Pietro Peterlongo <[email protected]>

* 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 <[email protected]>

* Add RE block in aliquot sum and improve RE

Co-authored-by: Zoom <[email protected]>

* Remove MD quotation marks for inline code

* Add export marker for RE block

* Remove extra ValueError

---------

Co-authored-by: Dimitri LESNOFF <[email protected]>
Co-authored-by: Zoom <[email protected]>
Co-authored-by: Pietro Peterlongo <[email protected]>
Co-authored-by: David Leal <[email protected]>
  • Loading branch information
5 people committed Jul 4, 2023
1 parent 0456550 commit 8899dd8
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 0 deletions.
5 changes: 5 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
120 changes: 120 additions & 0 deletions maths/abs.nim
Original file line number Diff line number Diff line change
@@ -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 <https://nim-lang.org/docs/system.html#abs%2CT>`_ 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(@[])
31 changes: 31 additions & 0 deletions maths/aliquot_sum.nim
Original file line number Diff line number Diff line change
@@ -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]
38 changes: 38 additions & 0 deletions maths/bitwise_addition.nim
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 8899dd8

Please sign in to comment.