From 5841dbcc0cb56b4864efcd46a512bca9115643f6 Mon Sep 17 00:00:00 2001 From: Dimitri LESNOFF Date: Tue, 14 Mar 2023 14:19:47 +0100 Subject: [PATCH 01/20] Add a sample of maths basic algorithms --- maths/abs.nim | 87 +++++++++++++++++++++++++++ maths/addition_without_arithmetic.nim | 36 +++++++++++ maths/aliquot_sum.nim | 31 ++++++++++ maths/allocation_number.nim | 52 ++++++++++++++++ 4 files changed, 206 insertions(+) create mode 100644 maths/abs.nim create mode 100644 maths/addition_without_arithmetic.nim create mode 100644 maths/aliquot_sum.nim create mode 100644 maths/allocation_number.nim diff --git a/maths/abs.nim b/maths/abs.nim new file mode 100644 index 00000000..71d734dc --- /dev/null +++ b/maths/abs.nim @@ -0,0 +1,87 @@ +## Absolute value +{.push raises: [].} +import std/algorithm + +runnableExamples: + doAssert absVal(-5.1) == 5.1 + doAssert absMin(@[-1, 2, -3]) == 1 + doAssert absMax(@[-1, 2, -3]) == 3 + doAssert absMaxSort(@[3, -10, -2]) == -10 + +func absVal(num: float): float = + ## Returns the absolute value of a number. + return if num < 0.0: -num else: num + +# Same for integers but return a Natural +func absVal(num: int): Natural = (if num < 0: -num else: num) + +func absMin(x: seq[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") + result = absVal(x[0]) + for i in 1 ..< x.len: + if absVal(x[i]) < result: + result = absVal(x[i]) + +func absMax(x: seq[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") + result = absVal(x[0]) + for i in 1 ..< x.len: + if absVal(x[i]) > result: + result = absVal(x[i]) + +func absMaxSort(x: seq[int]): int {.raises: [ValueError].} = + ## Returns the signed element whose absolute value is the largest in a sequence. + var x: seq[int] = x + if x.len == 0: + raise newException(ValueError, "Cannot find absolute maximum of an empty sequence") + sort(x, proc (a, b: int): int = int(absVal(b)) - int(absVal(a))) + return x[0] + +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) == abs_val(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 + + 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 `absMaxSort`": + test "Check `absMaxSort`": + check: + absMaxSort(@[3, -2, 1, -4, 5, -6]) == -6 + absMaxSort(@[0, 5, 1, 11]) == 11 + + test "`absMaxSort` on empty sequence raises ValueError": + doAssertRaises(ValueError): + discard absMaxSort(@[]) \ No newline at end of file diff --git a/maths/addition_without_arithmetic.nim b/maths/addition_without_arithmetic.nim new file mode 100644 index 00000000..6c545129 --- /dev/null +++ b/maths/addition_without_arithmetic.nim @@ -0,0 +1,36 @@ +## Illustrate how to add the integer without arithmetic operation +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 \ No newline at end of file diff --git a/maths/aliquot_sum.nim b/maths/aliquot_sum.nim new file mode 100644 index 00000000..f5fc57fa --- /dev/null +++ b/maths/aliquot_sum.nim @@ -0,0 +1,31 @@ +{.push raises: [].} + +runnableExamples: + import std/strformat + for number in [12, 100]: + echo fmt"The sum of all the proper divisors of {number} is {aliquotSum(number)}" + +func aliquotSum(number: Natural): Natural {.raises: [ValueError].} = + ## Returns the sum of all the proper divisors of the number + ## Example: aliquotSum(12) = 1 + 2 + 3 + 4 + 6 = 16 + if number == 0: + raise newException(ValueError, "Input number must be strictly positive") + 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] + + test "`aliquotSum` raises ValueError on non-positive entries": + doAssertRaises(ValueError): + discard aliquotSum(0) \ No newline at end of file diff --git a/maths/allocation_number.nim b/maths/allocation_number.nim new file mode 100644 index 00000000..47e38486 --- /dev/null +++ b/maths/allocation_number.nim @@ -0,0 +1,52 @@ +## In a multi-threaded download, this algorithmm could be used to provide +## each worker thread with a block of non-overlapping bytes to download. + +runnableExamples: + let numBytes = 100 + let numPartitions = 5 + let allocations = allocationNum(numBytes, numPartitions) + doAssert allocations == @[ + 0 .. 19, + 20 .. 39, + 40 .. 59, + 60 .. 79, + 80 .. 100 + ] + +func allocationNum(numBytes: Natural, numPartitions: Natural): seq[Slice[Natural]] = + ## Divide `numBytes` bytes into `numPartitions` non-overlapping partitions. + if numPartitions <= 0: + raise newException(ValueError, "numPartitions must be > 0") + if numPartitions > numBytes: + raise newException(ValueError, "numPartitions must be <= numBytes") + var + bytesPerPartition = numBytes div numPartitions + allocation_list: seq[Slice[Natural]] = @[] + for i in Natural(0) ..< numPartitions: + if i == numPartitions-1: + allocation_list.add(Natural(i*bytesPerPartition) .. numBytes) + else: + allocation_list.add(Natural(i*bytesPerPartition) .. Natural((i+1)*bytesPerPartition-1)) + return allocation_list + +when isMainModule: + import std/unittest + + suite "Test `allocationNum`": + test "Test `allocationNum`": + let allocations: seq[Slice[Natural]] = allocationNum(100, 5) + check allocations == @[ + Natural(0) .. 19, + Natural(20) .. 39, + Natural(40) .. 59, + Natural(60) .. 79, + Natural(80) .. 100 + ] + + test "`allocationNum` on 0 partitions": + doAssertRaises(ValueError): discard allocationNum(5, 0) + + test "`allocationNum` on more partitions than bytes": + doAssertRaises(ValueError): discard allocationNum(0, 5) + + echo allocationNum(0, 5) \ No newline at end of file From 2e1b30cf5409020fc8d9fbeba36371c526dbc697 Mon Sep 17 00:00:00 2001 From: dlesnoff <54949944+dlesnoff@users.noreply.github.com> Date: Fri, 17 Mar 2023 16:28:17 +0100 Subject: [PATCH 02/20] Update maths/abs.nim Co-authored-by: Zoom --- maths/abs.nim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/maths/abs.nim b/maths/abs.nim index 71d734dc..b0f29619 100644 --- a/maths/abs.nim +++ b/maths/abs.nim @@ -8,8 +8,9 @@ runnableExamples: doAssert absMax(@[-1, 2, -3]) == 3 doAssert absMaxSort(@[3, -10, -2]) == -10 -func absVal(num: float): float = - ## Returns the absolute value of a number. +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 return a Natural From ec85c68ba625ffcd5b64502c124b25347ddce938 Mon Sep 17 00:00:00 2001 From: dlesnoff <54949944+dlesnoff@users.noreply.github.com> Date: Fri, 17 Mar 2023 16:29:00 +0100 Subject: [PATCH 03/20] Use openArray in absMaxSort Co-authored-by: Zoom --- maths/abs.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maths/abs.nim b/maths/abs.nim index b0f29619..cc7b53cd 100644 --- a/maths/abs.nim +++ b/maths/abs.nim @@ -34,9 +34,9 @@ func absMax(x: seq[int]): Natural {.raises: [ValueError].} = if absVal(x[i]) > result: result = absVal(x[i]) -func absMaxSort(x: seq[int]): int {.raises: [ValueError].} = +func absMaxSort(x: openArray[int]): int {.raises: [ValueError].} = ## Returns the signed element whose absolute value is the largest in a sequence. - var x: seq[int] = x + var x: seq[int] = @x if x.len == 0: raise newException(ValueError, "Cannot find absolute maximum of an empty sequence") sort(x, proc (a, b: int): int = int(absVal(b)) - int(absVal(a))) From 3abe706c6e7de884365d24981cce91a0457bd226 Mon Sep 17 00:00:00 2001 From: Dimitri LESNOFF Date: Fri, 17 Mar 2023 16:38:16 +0100 Subject: [PATCH 04/20] Fix seq->openArray and int->SomeInteger --- maths/abs.nim | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/maths/abs.nim b/maths/abs.nim index cc7b53cd..74b76c25 100644 --- a/maths/abs.nim +++ b/maths/abs.nim @@ -9,14 +9,14 @@ runnableExamples: doAssert absMaxSort(@[3, -10, -2]) == -10 func absVal[T: SomeFloat](num: T): T = -## Returns the absolute value of a number. -## Use `math.abs `_ instead! + ## Returns the absolute value of a number. + ## Use `math.abs `_ instead! return if num < 0.0: -num else: num -# Same for integers but return a Natural -func absVal(num: int): Natural = (if num < 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: seq[int]): Natural {.raises: [ValueError].} = +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") @@ -25,7 +25,7 @@ func absMin(x: seq[int]): Natural {.raises: [ValueError].} = if absVal(x[i]) < result: result = absVal(x[i]) -func absMax(x: seq[int]): Natural {.raises: [ValueError].} = +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") @@ -61,28 +61,31 @@ when isMainModule: 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 `absMaxSort`": test "Check `absMaxSort`": check: absMaxSort(@[3, -2, 1, -4, 5, -6]) == -6 absMaxSort(@[0, 5, 1, 11]) == 11 - + test "`absMaxSort` on empty sequence raises ValueError": doAssertRaises(ValueError): - discard absMaxSort(@[]) \ No newline at end of file + discard absMaxSort(@[]) From 934cc5aa755d2add1d9300ce960034114317e14b Mon Sep 17 00:00:00 2001 From: Dimitri LESNOFF Date: Fri, 17 Mar 2023 16:41:45 +0100 Subject: [PATCH 05/20] Use Positive as input instead --- maths/aliquot_sum.nim | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/maths/aliquot_sum.nim b/maths/aliquot_sum.nim index f5fc57fa..ac1236d1 100644 --- a/maths/aliquot_sum.nim +++ b/maths/aliquot_sum.nim @@ -5,11 +5,9 @@ runnableExamples: for number in [12, 100]: echo fmt"The sum of all the proper divisors of {number} is {aliquotSum(number)}" -func aliquotSum(number: Natural): Natural {.raises: [ValueError].} = +func aliquotSum(number: Positive): Natural {.raises: [ValueError].} = ## Returns the sum of all the proper divisors of the number ## Example: aliquotSum(12) = 1 + 2 + 3 + 4 + 6 = 16 - if number == 0: - raise newException(ValueError, "Input number must be strictly positive") result = 0 for divisor in 1 .. (number div 2) : if number mod divisor == 0: @@ -25,7 +23,3 @@ when isMainModule: for i in 0 ..< input.len: check: aliquotSum(input[i]) == expected[i] - - test "`aliquotSum` raises ValueError on non-positive entries": - doAssertRaises(ValueError): - discard aliquotSum(0) \ No newline at end of file From 682b5405304adbc8f16f23a9ac5460504028afd7 Mon Sep 17 00:00:00 2001 From: dlesnoff <54949944+dlesnoff@users.noreply.github.com> Date: Fri, 24 Mar 2023 01:40:29 +0100 Subject: [PATCH 06/20] Update maths/addition_without_arithmetic.nim Co-authored-by: Pietro Peterlongo --- maths/addition_without_arithmetic.nim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/maths/addition_without_arithmetic.nim b/maths/addition_without_arithmetic.nim index 6c545129..b4388a05 100644 --- a/maths/addition_without_arithmetic.nim +++ b/maths/addition_without_arithmetic.nim @@ -1,4 +1,5 @@ -## Illustrate how to add the integer without arithmetic operation +## Illustrate how to implement addition of integers using bitwise operations +## See https://en.wikipedia.org/wiki/Bitwise_operation#Applications runnableExamples: import std/strformat var From 1bf17070d253de57cf7b1c3b57e581066d108f2e Mon Sep 17 00:00:00 2001 From: Dimitri LESNOFF Date: Fri, 24 Mar 2023 23:10:19 +0100 Subject: [PATCH 07/20] Name allocation number --- maths/allocation_number.nim | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/maths/allocation_number.nim b/maths/allocation_number.nim index 47e38486..bd36982f 100644 --- a/maths/allocation_number.nim +++ b/maths/allocation_number.nim @@ -1,5 +1,6 @@ -## In a multi-threaded download, this algorithmm could be used to provide -## each worker thread with a block of non-overlapping bytes to download. +# Non-overlapping Partitioning +## In a multi-threaded program, this algorithmm could be used to provide +## each worker thread with a block of non-overlapping bytes to work on. runnableExamples: let numBytes = 100 @@ -13,10 +14,8 @@ runnableExamples: 80 .. 100 ] -func allocationNum(numBytes: Natural, numPartitions: Natural): seq[Slice[Natural]] = +func allocationNum(numBytes: Natural, numPartitions: Positive): seq[Slice[Natural]] = ## Divide `numBytes` bytes into `numPartitions` non-overlapping partitions. - if numPartitions <= 0: - raise newException(ValueError, "numPartitions must be > 0") if numPartitions > numBytes: raise newException(ValueError, "numPartitions must be <= numBytes") var @@ -33,20 +32,26 @@ when isMainModule: import std/unittest suite "Test `allocationNum`": - test "Test `allocationNum`": + test "Test `allocationNum` on a divisor of bytes (same partition sizes)": let allocations: seq[Slice[Natural]] = allocationNum(100, 5) check allocations == @[ - Natural(0) .. 19, - Natural(20) .. 39, - Natural(40) .. 59, - Natural(60) .. 79, - Natural(80) .. 100 + Natural(0) .. Natural(19), + Natural(20) .. Natural(39), + Natural(40) .. Natural(59), + Natural(60) .. Natural(79), + Natural(80) .. Natural(100) ] - test "`allocationNum` on 0 partitions": - doAssertRaises(ValueError): discard allocationNum(5, 0) + test "`allocationNum` on a non-divisor of bytes": + let allocations: seq[Slice[Natural]] = allocationNum(104, 5) + check allocations == @[ + Natural(0) .. Natural(19), + Natural(20) .. Natural(39), + Natural(40) .. Natural(59), + Natural(60) .. Natural(79), + Natural(80) .. Natural(104) + ] test "`allocationNum` on more partitions than bytes": doAssertRaises(ValueError): discard allocationNum(0, 5) - - echo allocationNum(0, 5) \ No newline at end of file + doAssertRaises(ValueError): discard allocationNum(1, 5) \ No newline at end of file From dbf73d7e5705cd3bf5d8e18412c36fc6ab5701e5 Mon Sep 17 00:00:00 2001 From: Dimitri LESNOFF Date: Mon, 24 Apr 2023 14:37:16 +0200 Subject: [PATCH 08/20] [maths/abs] Replace maxAbsSort by signed[Min/Max]Abs --- maths/abs.nim | 59 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/maths/abs.nim b/maths/abs.nim index 74b76c25..074b02c1 100644 --- a/maths/abs.nim +++ b/maths/abs.nim @@ -1,6 +1,6 @@ ## Absolute value {.push raises: [].} -import std/algorithm +import std/strutils runnableExamples: doAssert absVal(-5.1) == 5.1 @@ -19,7 +19,8 @@ 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") + 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: @@ -28,19 +29,36 @@ func absMin(x: openArray[int]): Natural {.raises: [ValueError].} = 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") + 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 absMaxSort(x: openArray[int]): int {.raises: [ValueError].} = - ## Returns the signed element whose absolute value is the largest in a sequence. - var x: seq[int] = @x +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") - sort(x, proc (a, b: int): int = int(absVal(b)) - int(absVal(a))) - return x[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] @@ -80,12 +98,23 @@ when isMainModule: doAssertRaises(ValueError): discard absMax(@[]) - suite "Check `absMaxSort`": - test "Check `absMaxSort`": + 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: - absMaxSort(@[3, -2, 1, -4, 5, -6]) == -6 - absMaxSort(@[0, 5, 1, 11]) == 11 + signedMaxAbs(@[3, -2, 1, -4, 5, -6]) == -6 + signedMaxAbs(@[0, 5, 1, 11]) == 11 - test "`absMaxSort` on empty sequence raises ValueError": + test "`signedMaxAbs` on empty sequence raises ValueError": doAssertRaises(ValueError): - discard absMaxSort(@[]) + discard signedMaxAbs(@[]) From d88cc3c7d561970403914a7f0da8813aff4feae8 Mon Sep 17 00:00:00 2001 From: Dimitri LESNOFF Date: Mon, 24 Apr 2023 17:28:08 +0200 Subject: [PATCH 09/20] [Aliquot Sum] Add header --- maths/aliquot_sum.nim | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/maths/aliquot_sum.nim b/maths/aliquot_sum.nim index ac1236d1..592e2a56 100644 --- a/maths/aliquot_sum.nim +++ b/maths/aliquot_sum.nim @@ -1,3 +1,7 @@ +# 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 {.push raises: [].} runnableExamples: From 9c76b50a2a6ac7ded99774b74d411a570a8c8c16 Mon Sep 17 00:00:00 2001 From: Dimitri LESNOFF Date: Tue, 25 Apr 2023 16:57:46 +0200 Subject: [PATCH 10/20] Add empty line at end of file --- maths/addition_without_arithmetic.nim | 2 +- maths/allocation_number.nim | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/maths/addition_without_arithmetic.nim b/maths/addition_without_arithmetic.nim index b4388a05..b9f07d20 100644 --- a/maths/addition_without_arithmetic.nim +++ b/maths/addition_without_arithmetic.nim @@ -34,4 +34,4 @@ when isMainModule: check: add(-7, 2) == -5 add(-13, 5) == -8 - add(13, -5) == 8 \ No newline at end of file + add(13, -5) == 8 diff --git a/maths/allocation_number.nim b/maths/allocation_number.nim index bd36982f..f7c74d38 100644 --- a/maths/allocation_number.nim +++ b/maths/allocation_number.nim @@ -54,4 +54,4 @@ when isMainModule: test "`allocationNum` on more partitions than bytes": doAssertRaises(ValueError): discard allocationNum(0, 5) - doAssertRaises(ValueError): discard allocationNum(1, 5) \ No newline at end of file + doAssertRaises(ValueError): discard allocationNum(1, 5) From b86c2ef892538e9deb964d0c5098a806d6d9b7bf Mon Sep 17 00:00:00 2001 From: Dimitri Lesnoff Date: Mon, 19 Jun 2023 21:56:44 +0200 Subject: [PATCH 11/20] Remove Allocation number since it is a non standard algorithm --- maths/allocation_number.nim | 57 ------------------------------------- 1 file changed, 57 deletions(-) delete mode 100644 maths/allocation_number.nim diff --git a/maths/allocation_number.nim b/maths/allocation_number.nim deleted file mode 100644 index f7c74d38..00000000 --- a/maths/allocation_number.nim +++ /dev/null @@ -1,57 +0,0 @@ -# Non-overlapping Partitioning -## In a multi-threaded program, this algorithmm could be used to provide -## each worker thread with a block of non-overlapping bytes to work on. - -runnableExamples: - let numBytes = 100 - let numPartitions = 5 - let allocations = allocationNum(numBytes, numPartitions) - doAssert allocations == @[ - 0 .. 19, - 20 .. 39, - 40 .. 59, - 60 .. 79, - 80 .. 100 - ] - -func allocationNum(numBytes: Natural, numPartitions: Positive): seq[Slice[Natural]] = - ## Divide `numBytes` bytes into `numPartitions` non-overlapping partitions. - if numPartitions > numBytes: - raise newException(ValueError, "numPartitions must be <= numBytes") - var - bytesPerPartition = numBytes div numPartitions - allocation_list: seq[Slice[Natural]] = @[] - for i in Natural(0) ..< numPartitions: - if i == numPartitions-1: - allocation_list.add(Natural(i*bytesPerPartition) .. numBytes) - else: - allocation_list.add(Natural(i*bytesPerPartition) .. Natural((i+1)*bytesPerPartition-1)) - return allocation_list - -when isMainModule: - import std/unittest - - suite "Test `allocationNum`": - test "Test `allocationNum` on a divisor of bytes (same partition sizes)": - let allocations: seq[Slice[Natural]] = allocationNum(100, 5) - check allocations == @[ - Natural(0) .. Natural(19), - Natural(20) .. Natural(39), - Natural(40) .. Natural(59), - Natural(60) .. Natural(79), - Natural(80) .. Natural(100) - ] - - test "`allocationNum` on a non-divisor of bytes": - let allocations: seq[Slice[Natural]] = allocationNum(104, 5) - check allocations == @[ - Natural(0) .. Natural(19), - Natural(20) .. Natural(39), - Natural(40) .. Natural(59), - Natural(60) .. Natural(79), - Natural(80) .. Natural(104) - ] - - test "`allocationNum` on more partitions than bytes": - doAssertRaises(ValueError): discard allocationNum(0, 5) - doAssertRaises(ValueError): discard allocationNum(1, 5) From 89feb5d4b6282df3fdde68f49855056517a50b32 Mon Sep 17 00:00:00 2001 From: Dimitri Lesnoff Date: Mon, 19 Jun 2023 21:57:48 +0200 Subject: [PATCH 12/20] Fix titles --- maths/addition_without_arithmetic.nim | 1 + maths/aliquot_sum.nim | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/maths/addition_without_arithmetic.nim b/maths/addition_without_arithmetic.nim index b9f07d20..94746232 100644 --- a/maths/addition_without_arithmetic.nim +++ b/maths/addition_without_arithmetic.nim @@ -1,3 +1,4 @@ +## Bitwise Addition ## Illustrate how to implement addition of integers using bitwise operations ## See https://en.wikipedia.org/wiki/Bitwise_operation#Applications runnableExamples: diff --git a/maths/aliquot_sum.nim b/maths/aliquot_sum.nim index 592e2a56..254db15e 100644 --- a/maths/aliquot_sum.nim +++ b/maths/aliquot_sum.nim @@ -1,4 +1,4 @@ -# Aliquot sum +## 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 From 26255f8c10caeed5baa1f072f486d670ec1c89d9 Mon Sep 17 00:00:00 2001 From: Dimitri Lesnoff Date: Mon, 19 Jun 2023 21:59:04 +0200 Subject: [PATCH 13/20] Run nimpretty on the files --- maths/abs.nim | 4 ++-- maths/aliquot_sum.nim | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/maths/abs.nim b/maths/abs.nim index 074b02c1..b64eaaab 100644 --- a/maths/abs.nim +++ b/maths/abs.nim @@ -105,9 +105,9 @@ when isMainModule: 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 + check signedMinAbs(@[3, -2, 1, -4, 5, -6, -1]) == 1 suite "Check `signedMaxAbs`": test "Check `signedMaxAbs`": diff --git a/maths/aliquot_sum.nim b/maths/aliquot_sum.nim index 254db15e..9fba536e 100644 --- a/maths/aliquot_sum.nim +++ b/maths/aliquot_sum.nim @@ -13,7 +13,7 @@ func aliquotSum(number: Positive): Natural {.raises: [ValueError].} = ## 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) : + for divisor in 1 .. (number div 2): if number mod divisor == 0: result += divisor From 05ca7bf87c4e4a5eb384cd77a59e18ef58303205 Mon Sep 17 00:00:00 2001 From: Dimitri Lesnoff Date: Mon, 19 Jun 2023 22:04:41 +0200 Subject: [PATCH 14/20] Rename file and add DIRECTORY.md --- DIRECTORY.md | 6 ++++++ ...addition_without_arithmetic.nim => bitwise_addition.nim} | 0 2 files changed, 6 insertions(+) rename maths/{addition_without_arithmetic.nim => bitwise_addition.nim} (100%) diff --git a/DIRECTORY.md b/DIRECTORY.md index 6f296bd6..332ed5d3 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -6,5 +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/addition_without_arithmetic.nim b/maths/bitwise_addition.nim similarity index 100% rename from maths/addition_without_arithmetic.nim rename to maths/bitwise_addition.nim From 2605811e6aaf2f14a7b6f98cd3c2e9f23790c24d Mon Sep 17 00:00:00 2001 From: Dimitri Lesnoff Date: Mon, 19 Jun 2023 22:09:47 +0200 Subject: [PATCH 15/20] abs: Fix variable name --- maths/abs.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/abs.nim b/maths/abs.nim index b64eaaab..6a2702aa 100644 --- a/maths/abs.nim +++ b/maths/abs.nim @@ -70,7 +70,7 @@ when isMainModule: absVal(11.2) == 11.2 absVal(5) == 5 absVal(-5.1) == 5.1 - absVal(-5) == abs_val(5) + absVal(-5) == absVal(5) absVal(0) == 0 suite "Check `absMin`": From f13593e270fbc775f18dd3358f82a3c78563f648 Mon Sep 17 00:00:00 2001 From: dlesnoff <54949944+dlesnoff@users.noreply.github.com> Date: Mon, 19 Jun 2023 23:27:41 +0200 Subject: [PATCH 16/20] Add export marker Co-authored-by: Zoom --- maths/bitwise_addition.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/bitwise_addition.nim b/maths/bitwise_addition.nim index 94746232..e024f506 100644 --- a/maths/bitwise_addition.nim +++ b/maths/bitwise_addition.nim @@ -8,7 +8,7 @@ runnableExamples: b = 6 echo fmt"The sum of {a} and {b} is {add(a,b)}" -func add(first: int, second: int): int = +func add*(first: int, second: int): int = ## Implementation of addition of integer with `and`, `xor` and `shl` ## boolean operators. var first = first From 512c6bf90c132f52c5eff4cf2fbac8324bcb2cc1 Mon Sep 17 00:00:00 2001 From: dlesnoff <54949944+dlesnoff@users.noreply.github.com> Date: Mon, 19 Jun 2023 23:32:59 +0200 Subject: [PATCH 17/20] Add RE block in aliquot sum and improve RE Co-authored-by: Zoom --- maths/aliquot_sum.nim | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/maths/aliquot_sum.nim b/maths/aliquot_sum.nim index 9fba536e..f392d0e2 100644 --- a/maths/aliquot_sum.nim +++ b/maths/aliquot_sum.nim @@ -6,10 +6,13 @@ runnableExamples: import std/strformat - for number in [12, 100]: - echo fmt"The sum of all the proper divisors of {number} is {aliquotSum(number)}" + 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 {.raises: [ValueError].} = +func aliquotSum*(number: Positive): Natural {.raises: [ValueError].} = ## Returns the sum of all the proper divisors of the number ## Example: aliquotSum(12) = 1 + 2 + 3 + 4 + 6 = 16 result = 0 From b8e0c8d05f5a5470dd01359aacbea94ed00db278 Mon Sep 17 00:00:00 2001 From: dlesnoff <54949944+dlesnoff@users.noreply.github.com> Date: Mon, 19 Jun 2023 23:40:51 +0200 Subject: [PATCH 18/20] Remove MD quotation marks for inline code --- maths/abs.nim | 24 ++++++++++++------------ maths/aliquot_sum.nim | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/maths/abs.nim b/maths/abs.nim index 6a2702aa..eca6f0d8 100644 --- a/maths/abs.nim +++ b/maths/abs.nim @@ -64,8 +64,8 @@ when isMainModule: import std/[unittest, random] randomize() - suite "Check `absVal`": - test "Check `absVal`": + suite "Check absVal": + test "Check absVal": check: absVal(11.2) == 11.2 absVal(5) == 5 @@ -73,8 +73,8 @@ when isMainModule: absVal(-5) == absVal(5) absVal(0) == 0 - suite "Check `absMin`": - test "Check `absMin`": + suite "Check absMin": + test "Check absMin": check: absMin(@[-1, 2, -3]) == 1 absMin(@[0, 5, 1, 11]) == 0 @@ -83,12 +83,12 @@ when isMainModule: absMin([0, 5, 1, 11]) == 0 absMin([3, -10, -2]) == 2 - test "`absMin` on empty sequence raises ValueError": + test "absMin on empty sequence raises ValueError": doAssertRaises(ValueError): discard absMin(@[]) - suite "Check `absMax`": - test "Check `absMax`": + suite "Check absMax": + test "Check absMax": check: absMax(@[0, 5, 1, 11]) == 11 absMax(@[3, -10, -2]) == 10 @@ -98,8 +98,8 @@ when isMainModule: doAssertRaises(ValueError): discard absMax(@[]) - suite "Check `signedMinAbs`": - test "Check `signedMinAbs`": + suite "Check signedMinAbs": + test "Check signedMinAbs": check: signedMinAbs(@[0, 5, 1, 11]) == 0 signedMinAbs(@[3, -2, 1, -4, 5, -6]) == 1 @@ -109,12 +109,12 @@ when isMainModule: 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`": + 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": + test "signedMaxAbs on empty sequence raises ValueError": doAssertRaises(ValueError): discard signedMaxAbs(@[]) diff --git a/maths/aliquot_sum.nim b/maths/aliquot_sum.nim index f392d0e2..c244da57 100644 --- a/maths/aliquot_sum.nim +++ b/maths/aliquot_sum.nim @@ -22,8 +22,8 @@ func aliquotSum*(number: Positive): Natural {.raises: [ValueError].} = when isMainModule: import std/unittest - suite "Check `aliquotSum`": - test "`aliquotSum` on small values": + suite "Check aliquotSum": + test "aliquotSum on small values": var input = @[1, 2, 9, 12, 27, 100] expected = @[0, 1, 4, 16, 13, 117] From 3cf3fdf18c6af964695f68e6d4da7681ad0adab1 Mon Sep 17 00:00:00 2001 From: Dimitri LESNOFF Date: Tue, 20 Jun 2023 11:45:58 +0200 Subject: [PATCH 19/20] Add export marker for RE block --- maths/abs.nim | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/maths/abs.nim b/maths/abs.nim index eca6f0d8..ed111faa 100644 --- a/maths/abs.nim +++ b/maths/abs.nim @@ -3,20 +3,21 @@ import std/strutils runnableExamples: - doAssert absVal(-5.1) == 5.1 - doAssert absMin(@[-1, 2, -3]) == 1 - doAssert absMax(@[-1, 2, -3]) == 3 - doAssert absMaxSort(@[3, -10, -2]) == -10 + 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 = +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 absVal*[T: SomeInteger](num: T): Natural = (if num < 0: -num else: num) -func absMin(x: openArray[int]): Natural {.raises: [ValueError].} = +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 @@ -26,7 +27,7 @@ func absMin(x: openArray[int]): Natural {.raises: [ValueError].} = if absVal(x[i]) < result: result = absVal(x[i]) -func absMax(x: openArray[int]): Natural {.raises: [ValueError].} = +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 @@ -36,7 +37,7 @@ func absMax(x: openArray[int]): Natural {.raises: [ValueError].} = if absVal(x[i]) > result: result = absVal(x[i]) -func signedMinAbs(x: openArray[int]): int {.raises: [ValueError].} = +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: @@ -48,7 +49,7 @@ func signedMinAbs(x: openArray[int]): int {.raises: [ValueError].} = if nAbs < minAbs: (min, minAbs) = (n, nAbs) min -func signedMaxAbs(x: openArray[int]): int {.raises: [ValueError].} = +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: @@ -105,7 +106,6 @@ when isMainModule: 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 From e6cf67a33f79360f3df0e8dbc44e3c835a18c347 Mon Sep 17 00:00:00 2001 From: Dimitri LESNOFF Date: Tue, 20 Jun 2023 11:55:25 +0200 Subject: [PATCH 20/20] Remove extra ValueError --- maths/aliquot_sum.nim | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/maths/aliquot_sum.nim b/maths/aliquot_sum.nim index c244da57..711e24d6 100644 --- a/maths/aliquot_sum.nim +++ b/maths/aliquot_sum.nim @@ -2,7 +2,6 @@ ## 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 -{.push raises: [].} runnableExamples: import std/strformat @@ -12,7 +11,7 @@ runnableExamples: assert sum == expected[i] echo fmt"The sum of all the proper divisors of {number} is {sum}" -func aliquotSum*(number: Positive): Natural {.raises: [ValueError].} = +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