Skip to content

Commit cf013f1

Browse files
dlesnoffZoomRmcpietroppeterPanquesito7
authored
Create and populate the Maths directory (#4)
* 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]>
1 parent c83ceae commit cf013f1

File tree

4 files changed

+194
-0
lines changed

4 files changed

+194
-0
lines changed

DIRECTORY.md

+5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
* [Catalan Numbers](dynamic_programming/catalan_numbers.nim)
77
* [Viterbi](dynamic_programming/viterbi.nim)
88

9+
## Maths
10+
* [Absolute value](maths/abs.nim)
11+
* [Aliquot sum](maths/aliquot_sum.nim)
12+
* [Bitwise Addition](maths/bitwise_addition.nim)
13+
914
## Strings
1015
* [Check Anagram](strings/check_anagram.nim)
1116

maths/abs.nim

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
## Absolute value
2+
{.push raises: [].}
3+
import std/strutils
4+
5+
runnableExamples:
6+
assert absVal(-5.1) == 5.1
7+
assert absMin(@[-1, 2, -3]) == 1
8+
assert absMax(@[-1, 2, -3]) == 3
9+
assert signedMinAbs(@[3, -10, -2]) == -2
10+
assert signedMaxAbs(@[3, -10, -2]) == -10
11+
12+
func absVal*[T: SomeFloat](num: T): T =
13+
## Returns the absolute value of a number.
14+
## Use `math.abs <https://nim-lang.org/docs/system.html#abs%2CT>`_ instead!
15+
return if num < 0.0: -num else: num
16+
17+
# Same for Integers but returns a Natural
18+
func absVal*[T: SomeInteger](num: T): Natural = (if num < 0: -num else: num)
19+
20+
func absMin*(x: openArray[int]): Natural {.raises: [ValueError].} =
21+
## Returns the smallest element in absolute value in a sequence.
22+
if x.len == 0:
23+
raise newException(ValueError, """Cannot find absolute minimum
24+
of an empty sequence""".unindent)
25+
result = absVal(x[0])
26+
for i in 1 ..< x.len:
27+
if absVal(x[i]) < result:
28+
result = absVal(x[i])
29+
30+
func absMax*(x: openArray[int]): Natural {.raises: [ValueError].} =
31+
## Returns the largest element in absolute value in a sequence.
32+
if x.len == 0:
33+
raise newException(ValueError, """Cannot find absolute maximum of an empty
34+
sequence""".unindent)
35+
result = absVal(x[0])
36+
for i in 1 ..< x.len:
37+
if absVal(x[i]) > result:
38+
result = absVal(x[i])
39+
40+
func signedMinAbs*(x: openArray[int]): int {.raises: [ValueError].} =
41+
## Returns the first signed element whose absolute value
42+
## is the smallest in a sequence.
43+
if x.len == 0:
44+
raise newException(ValueError, """Cannot find absolute maximum of an empty
45+
sequence""".unindent)
46+
var (min, minAbs) = (x[0], absVal(x[0]))
47+
for n in x:
48+
let nAbs = absVal(n)
49+
if nAbs < minAbs: (min, minAbs) = (n, nAbs)
50+
min
51+
52+
func signedMaxAbs*(x: openArray[int]): int {.raises: [ValueError].} =
53+
## Returns the first signed element whose absolute value
54+
## is the largest in a sequence.
55+
if x.len == 0:
56+
raise newException(ValueError, """Cannot find absolute maximum of an empty
57+
sequence""".unindent)
58+
var (max, maxAbs) = (x[0], absVal(x[0]))
59+
for n in x:
60+
let nAbs = absVal(n)
61+
if nAbs > maxAbs: (max, maxAbs) = (n, nAbs)
62+
max
63+
64+
when isMainModule:
65+
import std/[unittest, random]
66+
randomize()
67+
68+
suite "Check absVal":
69+
test "Check absVal":
70+
check:
71+
absVal(11.2) == 11.2
72+
absVal(5) == 5
73+
absVal(-5.1) == 5.1
74+
absVal(-5) == absVal(5)
75+
absVal(0) == 0
76+
77+
suite "Check absMin":
78+
test "Check absMin":
79+
check:
80+
absMin(@[-1, 2, -3]) == 1
81+
absMin(@[0, 5, 1, 11]) == 0
82+
absMin(@[3, -10, -2]) == 2
83+
absMin([-1, 2, -3]) == 1
84+
absMin([0, 5, 1, 11]) == 0
85+
absMin([3, -10, -2]) == 2
86+
87+
test "absMin on empty sequence raises ValueError":
88+
doAssertRaises(ValueError):
89+
discard absMin(@[])
90+
91+
suite "Check absMax":
92+
test "Check absMax":
93+
check:
94+
absMax(@[0, 5, 1, 11]) == 11
95+
absMax(@[3, -10, -2]) == 10
96+
absMax(@[-1, 2, -3]) == 3
97+
98+
test "`absMax` on empty sequence raises ValueError":
99+
doAssertRaises(ValueError):
100+
discard absMax(@[])
101+
102+
suite "Check signedMinAbs":
103+
test "Check signedMinAbs":
104+
check:
105+
signedMinAbs(@[0, 5, 1, 11]) == 0
106+
signedMinAbs(@[3, -2, 1, -4, 5, -6]) == 1
107+
signedMinAbs(@[3, -2, -1, -4, 5, -6]) == -1
108+
109+
test "Among two minimal elements, the first one is returned":
110+
check signedMinAbs(@[3, -2, 1, -4, 5, -6, -1]) == 1
111+
112+
suite "Check signedMaxAbs":
113+
test "Check signedMaxAbs":
114+
check:
115+
signedMaxAbs(@[3, -2, 1, -4, 5, -6]) == -6
116+
signedMaxAbs(@[0, 5, 1, 11]) == 11
117+
118+
test "signedMaxAbs on empty sequence raises ValueError":
119+
doAssertRaises(ValueError):
120+
discard signedMaxAbs(@[])

maths/aliquot_sum.nim

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
## Aliquot sum
2+
## In number theory, the aliquot sum s(n) of a positive integer n is the sum of
3+
## all proper divisors of n, that is, all divisors of n other than n itself.
4+
## https://en.wikipedia.org/wiki/Aliquot_sum
5+
6+
runnableExamples:
7+
import std/strformat
8+
const expected = [16, 117]
9+
for i, number in [12, 100].pairs():
10+
let sum = aliquotSum(number)
11+
assert sum == expected[i]
12+
echo fmt"The sum of all the proper divisors of {number} is {sum}"
13+
14+
func aliquotSum*(number: Positive): Natural =
15+
## Returns the sum of all the proper divisors of the number
16+
## Example: aliquotSum(12) = 1 + 2 + 3 + 4 + 6 = 16
17+
result = 0
18+
for divisor in 1 .. (number div 2):
19+
if number mod divisor == 0:
20+
result += divisor
21+
22+
when isMainModule:
23+
import std/unittest
24+
suite "Check aliquotSum":
25+
test "aliquotSum on small values":
26+
var
27+
input = @[1, 2, 9, 12, 27, 100]
28+
expected = @[0, 1, 4, 16, 13, 117]
29+
for i in 0 ..< input.len:
30+
check:
31+
aliquotSum(input[i]) == expected[i]

maths/bitwise_addition.nim

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
## Bitwise Addition
2+
## Illustrate how to implement addition of integers using bitwise operations
3+
## See https://en.wikipedia.org/wiki/Bitwise_operation#Applications
4+
runnableExamples:
5+
import std/strformat
6+
var
7+
a = 5
8+
b = 6
9+
echo fmt"The sum of {a} and {b} is {add(a,b)}"
10+
11+
func add*(first: int, second: int): int =
12+
## Implementation of addition of integer with `and`, `xor` and `shl`
13+
## boolean operators.
14+
var first = first
15+
var second = second
16+
while second != 0:
17+
var c = first and second
18+
first = first xor second
19+
second = c shl 1
20+
return first
21+
22+
when isMainModule:
23+
import std/unittest
24+
25+
suite "Check addition":
26+
test "Addition of two positive numbers":
27+
check:
28+
add(3, 5) == 8
29+
add(13, 5) == 18
30+
test "Addition of two negative numbers":
31+
check:
32+
add(-7, -2) == -9
33+
add(-321, -0) == -321
34+
test "Addition of one positive and one negative number":
35+
check:
36+
add(-7, 2) == -5
37+
add(-13, 5) == -8
38+
add(13, -5) == 8

0 commit comments

Comments
 (0)