Skip to content

Commit d31ec0a

Browse files
Notherynekeon
authored andcommitted
add atbash, crout, hosoya triangle algorithms (keon#470)
* add atbash, crout, hosoya triangle algorithms * add tests, update readmes
1 parent c3bfeab commit d31ec0a

14 files changed

+235
-4
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ If you want to uninstall algorithms, it is as simple as:
140140
- [rod_cut](algorithms/dp/rod_cut.py)
141141
- [word_break](algorithms/dp/word_break.py)
142142
- [fibonacci](algorithms/dp/fib.py)
143+
- [hosoya triangle](algorithms/dp/hosoya_triangle.py)
143144
- [graph](algorithms/graph)
144145
- [check_bipartite](algorithms/graph/check_bipartite.py)
145146
- [strongly_connected](algorithms/graph/check_digraph_strongly_connected.py)
@@ -216,6 +217,7 @@ If you want to uninstall algorithms, it is as simple as:
216217
- [sparse_dot_vector](algorithms/matrix/sparse_dot_vector.py)
217218
- [sparse_mul](algorithms/matrix/sparse_mul.py)
218219
- [spiral_traversal](algorithms/matrix/spiral_traversal.py)
220+
- [crout_matrix_decomposition](algorithms/matrix/crout_matrix_decomposition.py
219221
- [queues](algorithms/queues)
220222
- [max_sliding_window](algorithms/queues/max_sliding_window.py)
221223
- [moving_average](algorithms/queues/moving_average.py)
@@ -306,6 +308,7 @@ If you want to uninstall algorithms, it is as simple as:
306308
- [rotate](algorithms/strings/rotate.py)
307309
- [first_unique_char](algorithms/strings/first_unique_char.py)
308310
- [repeat_substring](algorithms/strings/repeat_substring.py)
311+
- [atbash_cipher](algorithms/strings/atbash_cipher.py)
309312
- [tree](algorithms/tree)
310313
- [bst](algorithms/tree/bst)
311314
- [array_to_bst](algorithms/tree/bst/array_to_bst.py)

README_ES.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ Si desea desinstalar algorithms, es tan simple como:
140140
- [rod_cut](algorithms/dp/rod_cut.py)
141141
- [word_break](algorithms/dp/word_break.py)
142142
- [fibonacci](algorithms/dp/fib.py)
143+
- [hosoya triangle](algorithms/dp/hosoya_triangle.py)
143144
- [graph](algorithms/graph)
144145
- [check_bipartite](algorithms/graph/check_bipartite.py)
145146
- [strongly_connected](algorithms/graph/check_digraph_strongly_connected.py)
@@ -214,6 +215,7 @@ Si desea desinstalar algorithms, es tan simple como:
214215
- [sparse_dot_vector](algorithms/matrix/sparse_dot_vector.py)
215216
- [sparse_mul](algorithms/matrix/sparse_mul.py)
216217
- [spiral_traversal](algorithms/matrix/spiral_traversal.py)
218+
- [crout_matrix_decomposition](algorithms/matrix/crout_matrix_decomposition.py
217219
- [queues](algorithms/queues)
218220
- [max_sliding_window](algorithms/queues/max_sliding_window.py)
219221
- [moving_average](algorithms/queues/moving_average.py)
@@ -303,7 +305,8 @@ Si desea desinstalar algorithms, es tan simple como:
303305
- [longest_common_prefix](algorithms/strings/longest_common_prefix.py)
304306
- [rotate](algorithms/strings/rotate.py)
305307
- [first_unique_char](algorithms/strings/first_unique_char.py)
306-
- [repeat_substring](algorithms/strings/repeat_substring.py)
308+
- [repeat_substring](algorithms/strings/repeat_substring.py)
309+
- [atbash_cipher](algorithms/strings/atbash_cipher.py)
307310
- [tree](algorithms/tree)
308311
- [bst](algorithms/tree/bst)
309312
- [array_to_bst](algorithms/tree/bst/array_to_bst.py)

README_FR.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ Si vous voulez désinstaller le paquet algorithms, il suffit de procéder comme
139139
- [rod_cut](algorithms/dp/rod_cut.py)
140140
- [word_break](algorithms/dp/word_break.py)
141141
- [fibonacci](algorithms/dp/fib.py)
142+
- [hosoya triangle](algorithms/dp/hosoya_triangle.py)
142143
- [graph](algorithms/graph)
143144
- [check_bipartite](algorithms/graph/check_bipartite.py)
144145
- [strongly_connected](algorithms/graph/checkDiGraphStronglyConnected.py)
@@ -212,6 +213,7 @@ Si vous voulez désinstaller le paquet algorithms, il suffit de procéder comme
212213
- [sparse_dot_vector](algorithms/matrix/sparse_dot_vector.py)
213214
- [sparse_mul](algorithms/matrix/sparse_mul.py)
214215
- [spiral_traversal](algorithms/matrix/spiral_traversal.py)
216+
- [crout_matrix_decomposition](algorithms/matrix/crout_matrix_decomposition.py
215217
- [queues](algorithms/queues)
216218
- [max_sliding_window](algorithms/queues/max_sliding_window.py)
217219
- [moving_average](algorithms/queues/moving_average.py)
@@ -301,7 +303,8 @@ Si vous voulez désinstaller le paquet algorithms, il suffit de procéder comme
301303
- [longest_common_prefix](algorithms/strings/longest_common_prefix.py)
302304
- [rotate](algorithms/strings/rotate.py)
303305
- [first_unique_char](algorithms/strings/first_unique_char.py)
304-
- [repeat_substring](algorithms/strings/repeat_substring.py)
306+
- [repeat_substring](algorithms/strings/repeat_substring.py)
307+
- [atbash_cipher](algorithms/strings/atbash_cipher.py)
305308
- [tree](algorithms/tree)
306309
- [bst](algorithms/tree/tree/bst)
307310
- [array2bst](algorithms/tree/bst/array2bst.py)

README_GE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ Um das Projekt zu deinstallieren tippen Sie folgendes:
146146
- [rod_cut](algorithms/dp/rod_cut.py)
147147
- [word_break](algorithms/dp/word_break.py)
148148
- [fibonacci](algorithms/dp/fib.py)
149+
- [hosoya triangle](algorithms/dp/hosoya_triangle.py)
149150
- [graph](algorithms/graph)
150151
- [check_bipartite](algorithms/graph/check_bipartite.py)
151152
- [strongly_connected](algorithms/graph/checkDiGraphStronglyConnected.py)
@@ -215,6 +216,7 @@ Um das Projekt zu deinstallieren tippen Sie folgendes:
215216
- [sparse_dot_vector](algorithms/matrix/sparse_dot_vector.py)
216217
- [sparse_mul](algorithms/matrix/sparse_mul.py)
217218
- [spiral_traversal](algorithms/matrix/spiral_traversal.py)
219+
- [crout_matrix_decomposition](algorithms/matrix/crout_matrix_decomposition.py
218220
- [queues](algorithms/queues)
219221
- [max_sliding_window](algorithms/queues/max_sliding_window.py)
220222
- [moving_average](algorithms/queues/moving_average.py)
@@ -291,6 +293,7 @@ Um das Projekt zu deinstallieren tippen Sie folgendes:
291293
- [reverse_words](algorithms/strings/reverse_words.py)
292294
- [roman_to_int](algorithms/strings/roman_to_int.py)
293295
- [word_squares](algorithms/strings/word_squares.py)
296+
- [atbash_cipher](algorithms/strings/atbash_cipher.py)
294297
- [tree](algorithms/tree)
295298
- [bst](algorithms/tree/tree/bst)
296299
- [array2bst](algorithms/tree/bst/array2bst.py)

README_JP.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ if __name__ == "__main__":
140140
- [rod_cut](algorithms/dp/rod_cut.py)
141141
- [word_break](algorithms/dp/word_break.py)
142142
- [fibonacci](algorithms/dp/fib.py)
143+
- [hosoya triangle](algorithms/dp/hosoya_triangle.py)
143144
- [graph : グラフ](algorithms/graph)
144145
- [check_bipartite](algorithms/graph/check_bipartite.py)
145146
- [strongly_connected](algorithms/graph/checkDiGraphStronglyConnected.py)
@@ -209,6 +210,7 @@ if __name__ == "__main__":
209210
- [sparse_dot_vector](algorithms/matrix/sparse_dot_vector.py)
210211
- [sparse_mul](algorithms/matrix/sparse_mul.py)
211212
- [spiral_traversal](algorithms/matrix/spiral_traversal.py)
213+
- [crout_matrix_decomposition](algorithms/matrix/crout_matrix_decomposition.py
212214
- [queues : キュー](algorithms/queues)
213215
- [max_sliding_window](algorithms/queues/max_sliding_window.py)
214216
- [moving_average](algorithms/queues/moving_average.py)
@@ -285,6 +287,7 @@ if __name__ == "__main__":
285287
- [reverse_words](algorithms/strings/reverse_words.py)
286288
- [roman_to_int](algorithms/strings/roman_to_int.py)
287289
- [word_squares](algorithms/strings/word_squares.py)
290+
- [atbash_cipher](algorithms/strings/atbash_cipher.py)
288291
- [tree : 木構造](algorithms/tree)
289292
- [bst](algorithms/tree/tree/bst)
290293
- [array2bst](algorithms/tree/bst/array2bst.py)

README_KR.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ if __name__ == "__main__":
136136
- [rod_cut](algorithms/dp/rod_cut.py)
137137
- [word_break](algorithms/dp/word_break.py)
138138
- [fibonacci](algorithms/dp/fib.py)
139+
- [hosoya triangle](algorithms/dp/hosoya_triangle.py)
139140
- [graph : 그래프](algorithms/graph)
140141
- [check_bipartite](algorithms/graph/check_bipartite.py)
141142
- [strongly_connected](algorithms/graph/checkDiGraphStronglyConnected.py)
@@ -205,6 +206,7 @@ if __name__ == "__main__":
205206
- [sparse_dot_vector](algorithms/matrix/sparse_dot_vector.py)
206207
- [sparse_mul](algorithms/matrix/sparse_mul.py)
207208
- [spiral_traversal](algorithms/matrix/spiral_traversal.py)
209+
- [crout_matrix_decomposition](algorithms/matrix/crout_matrix_decomposition.py
208210
- [queues : 큐](algorithms/queues)
209211
- [max_sliding_window](algorithms/queues/max_sliding_window.py)
210212
- [moving_average](algorithms/queues/moving_average.py)
@@ -279,6 +281,7 @@ if __name__ == "__main__":
279281
- [reverse_words](algorithms/strings/reverse_words.py)
280282
- [roman_to_int](algorithms/strings/roman_to_int.py)
281283
- [word_squares](algorithms/strings/word_squares.py)
284+
- [atbash_cipher](algorithms/strings/atbash_cipher.py)
282285
- [tree : 트리](algorithms/tree)
283286
- [bst : 이진 탐색 트리](algorithms/tree/tree/bst)
284287
- [array2bst](algorithms/tree/bst/array2bst.py)

README_PTBR.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ Se você deseja desinstalar os algoritmos, é tão simples quanto:
138138
- [rod_cut](algorithms/dp/rod_cut.py)
139139
- [word_break](algorithms/dp/word_break.py)
140140
- [fibonacci](algorithms/dp/fib.py)
141+
- [hosoya triangle](algorithms/dp/hosoya_triangle.py)
141142
- [graph](algorithms/graph)
142143
- [check_bipartite](algorithms/graph/check_bipartite.py)
143144
- [strongly_connected](algorithms/graph/checkDiGraphStronglyConnected.py)
@@ -207,6 +208,7 @@ Se você deseja desinstalar os algoritmos, é tão simples quanto:
207208
- [sparse_dot_vector](algorithms/matrix/sparse_dot_vector.py)
208209
- [sparse_mul](algorithms/matrix/sparse_mul.py)
209210
- [spiral_traversal](algorithms/matrix/spiral_traversal.py)
211+
- [crout_matrix_decomposition](algorithms/matrix/crout_matrix_decomposition.py
210212
- [queues](algorithms/queues)
211213
- [max_sliding_window](algorithms/queues/max_sliding_window.py)
212214
- [moving_average](algorithms/queues/moving_average.py)
@@ -289,6 +291,7 @@ Se você deseja desinstalar os algoritmos, é tão simples quanto:
289291
- [caesar_cipher](algorithms/strings/caesar_cipher.py)
290292
- [contain_string](algorithms/strings/contain_string.py)
291293
- [count_binary_substring](algorithms/strings/count_binary_substring.py)
294+
- [atbash_cipher](algorithms/strings/atbash_cipher.py)
292295
- [tree](algorithms/tree)
293296
- [bst](algorithms/tree/tree/bst)
294297
- [array2bst](algorithms/tree/bst/array2bst.py)

algorithms/dp/hosoya_triangle.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""
2+
Hosoya triangle (originally Fibonacci triangle) is a triangular arrangement
3+
of numbers, where if you take any number it is the sum of 2 numbers above.
4+
First line is always 1, and second line is always {1 1}.
5+
6+
This printHosoya function takes argument n which is the height of the triangle
7+
(number of lines).
8+
9+
For example:
10+
printHosoya( 6 ) would return:
11+
1
12+
1 1
13+
2 1 2
14+
3 2 2 3
15+
5 3 4 3 5
16+
8 5 6 6 5 8
17+
18+
The complexity is O(n^3).
19+
20+
"""
21+
22+
23+
def hosoya(n, m):
24+
if ((n == 0 and m == 0) or (n == 1 and m == 0) or
25+
(n == 1 and m == 1) or (n == 2 and m == 1)):
26+
return 1
27+
if n > m:
28+
return hosoya(n - 1, m) + hosoya(n - 2, m)
29+
elif m == n:
30+
return hosoya(n - 1, m - 1) + hosoya(n - 2, m - 2)
31+
else:
32+
return 0
33+
34+
def print_hosoya(n):
35+
for i in range(n):
36+
for j in range(i + 1):
37+
print(hosoya(i, j) , end = " ")
38+
print ("\n", end = "")
39+
40+
def hosoya_testing(n):
41+
x = []
42+
for i in range(n):
43+
for j in range(i + 1):
44+
x.append(hosoya(i, j))
45+
return x
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""
2+
Crout matrix decomposition is used to find two matrices that, when multiplied
3+
give our input matrix, so L * U = A.
4+
L stands for lower and L has non-zero elements only on diagonal and below.
5+
U stands for upper and U has non-zero elements only on diagonal and above.
6+
7+
This can for example be used to solve systems of linear equations.
8+
The last if is used if to avoid dividing by zero.
9+
10+
Example:
11+
We input the A matrix:
12+
[[1,2,3],
13+
[3,4,5],
14+
[6,7,8]]
15+
16+
We get:
17+
L = [1.0, 0.0, 0.0]
18+
[3.0, -2.0, 0.0]
19+
[6.0, -5.0, 0.0]
20+
U = [1.0, 2.0, 3.0]
21+
[0.0, 1.0, 2.0]
22+
[0.0, 0.0, 1.0]
23+
24+
We can check that L * U = A.
25+
26+
I think the complexity should be O(n^3).
27+
"""
28+
29+
def crout_matrix_decomposition(A):
30+
n = len(A)
31+
L = [[0.0] * n for i in range(n)]
32+
U = [[0.0] * n for i in range(n)]
33+
for j in range(n):
34+
U[j][j] = 1.0
35+
for i in range(j, n):
36+
alpha = float(A[i][j])
37+
for k in range(j):
38+
alpha -= L[i][k]*U[k][j]
39+
L[i][j] = float(alpha)
40+
for i in range(j+1, n):
41+
tempU = float(A[j][i])
42+
for k in range(j):
43+
tempU -= float(L[j][k]*U[k][i])
44+
if int(L[j][j]) == 0:
45+
L[j][j] = float(0.1**40)
46+
U[j][i] = float(tempU/L[j][j])
47+
return (L,U)

algorithms/strings/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@
3434
from .rotate import *
3535
from .first_unique_char import *
3636
from .repeat_substring import *
37+
from .atbash_cipher import *

algorithms/strings/atbash_cipher.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""
2+
Atbash cipher is mapping the alphabet to it's reverse.
3+
So if we take "a" as it is the first letter, we change it to the last - z.
4+
5+
Example:
6+
Attack at dawn --> Zggzxp zg wzdm
7+
8+
Complexity: O(n)
9+
"""
10+
11+
def atbash(s):
12+
translated = ""
13+
for i in range(len(s)):
14+
n = ord(s[i])
15+
16+
if s[i].isalpha():
17+
18+
if s[i].isupper():
19+
x = n - ord('A')
20+
translated += chr(ord('Z') - x)
21+
22+
if s[i].islower():
23+
x = n - ord('a')
24+
translated += chr(ord('z') - x)
25+
else:
26+
translated += s[i]
27+
return translated

tests/test_dp.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from algorithms.dp import (
2-
edit_distance
2+
edit_distance,
3+
hosoya_triangle
34
)
45

56

@@ -11,6 +12,35 @@ def test_edit_distance(self):
1112
self.assertEqual(edit_distance('food', 'money'), 4)
1213
self.assertEqual(edit_distance('horse', 'ros'), 3)
1314

15+
class TestHosoyaTriangle(unittest.TestCase):
16+
"""[summary]
17+
Test for the file hosoya_triangle
18+
19+
Arguments:
20+
unittest {[type]} -- [description]
21+
"""
22+
23+
def test_hosoya(self):
24+
self.assertEqual([1], hosoya_testing(1))
25+
self.assertEqual([1,
26+
1, 1,
27+
2, 1, 2,
28+
3, 2, 2, 3,
29+
5, 3, 4, 3, 5,
30+
8, 5, 6, 6, 5, 8],
31+
hosoya_testing(6))
32+
self.assertEqual([1,
33+
1, 1,
34+
2, 1, 2,
35+
3, 2, 2, 3,
36+
5, 3, 4, 3, 5,
37+
8, 5, 6, 6, 5, 8,
38+
13, 8, 10, 9, 10, 8, 13,
39+
21, 13, 16, 15, 15, 16, 13, 21,
40+
34, 21, 26, 24, 25, 24, 26, 21, 34,
41+
55, 34, 42, 39, 40, 40, 39, 42, 34, 55],
42+
hosoya_testing(10))
43+
1444

1545
if __name__ == '__main__':
1646
unittest.main()

tests/test_matrix.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from algorithms.matrix import (
2+
crout_matrix_decomposition
3+
)
4+
5+
6+
import unittest
7+
8+
9+
class TestCroutMatrixDecomposition(unittest.TestCase):
10+
"""[summary]
11+
Test for the file crout_matrix_decomposition.py
12+
13+
Arguments:
14+
unittest {[type]} -- [description]
15+
"""
16+
17+
def test_crout_matrix_decomposition(self):
18+
self.assertEqual(([[9.0, 0.0], [7.0, 0.0]],
19+
[[1.0, 1.0], [0.0, 1.0]]),
20+
crout_matrix_decomposition([[9,9], [7,7]]))
21+
22+
self.assertEqual(([[1.0, 0.0, 0.0],
23+
[3.0, -2.0, 0.0],
24+
[6.0, -5.0, 0.0]],
25+
[[1.0, 2.0, 3.0],
26+
[0.0, 1.0, 2.0],
27+
[0.0, 0.0, 1.0]]),
28+
crout_matrix_decomposition([[1,2,3],[3,4,5],[6,7,8]]))
29+
30+
self.assertEqual(([[2.0, 0, 0, 0],
31+
[4.0, -1.0, 0, 0],
32+
[6.0, -2.0, 2.0, 0],
33+
[8.0, -3.0, 3.0, 0.0]],
34+
[[1.0, 0.5, 1.5, 0.5],
35+
[0, 1.0, 2.0, 1.0],
36+
[0, 0, 1.0, 0.0],
37+
[0, 0, 0, 1.0]]),
38+
crout_matrix_decomposition([[2,1,3,1],
39+
[4,1,4,1],
40+
[6,1,7,1],
41+
[8,1,9,1]]))
42+
43+
44+
45+
if __name__ == "__main__":
46+
unittest.main()

0 commit comments

Comments
 (0)