b else 0), # noqa: E501
+ [[[-9, 5], [8, 4]]]) # noqa: E501
+
+
+if __name__ == '__main__':
+
+ unittest.main()
diff --git a/tests/test_automata.py b/tests/test_automata.py
new file mode 100644
index 000000000..dbd766a3f
--- /dev/null
+++ b/tests/test_automata.py
@@ -0,0 +1,48 @@
+from algorithms.automata import DFA
+
+
+import unittest
+
+
+class TestDFA(unittest.TestCase):
+ def test_DFA(self):
+ transitions = {
+ 'a': {'1': 'a', '0': 'b'},
+ 'b': {'1': 'b', '0': 'a'}
+ }
+
+ final = ['a']
+ start = 'a'
+
+ self.assertEqual(False, DFA(transitions, start, final, "000111100"))
+ self.assertEqual(True, DFA(transitions, start, final, "111000011"))
+
+ transitions1 = {
+ '0': {'0': '1', '1': '0'},
+ '1': {'0': '2', '1': '0'},
+ '2': {'0': '2', '1': '3'},
+ '3': {'0': '3', '1': '3'}
+ }
+
+ final1 = ['0', '1', '2']
+ start1 = '0'
+
+ self.assertEqual(False, DFA(transitions1, start1, final1, "0001111"))
+ self.assertEqual(True, DFA(transitions1, start1, final1, "01010101"))
+
+ transitions2 = {
+ '0': {'a': '0', 'b': '1'},
+ '1': {'a': '0', 'b': '2'},
+ '2': {'a': '3', 'b': '2'},
+ '3': {'a': '3', 'b': '3'}
+ }
+
+ final2 = ['3']
+ start2 = '0'
+
+ self.assertEqual(False, DFA(transitions2, start2, final2, "aaabbb"))
+ self.assertEqual(True, DFA(transitions2, start2, final2, "baabba"))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_backtrack.py b/tests/test_backtrack.py
new file mode 100644
index 000000000..516ed6d2d
--- /dev/null
+++ b/tests/test_backtrack.py
@@ -0,0 +1,396 @@
+from algorithms.backtrack import (
+ add_operators,
+ permute_iter,
+ anagram,
+ array_sum_combinations,
+ unique_array_sum_combinations,
+ combination_sum,
+ get_factors,
+ recursive_get_factors,
+ find_words,
+ generate_abbreviations,
+ generate_parenthesis_v1,
+ generate_parenthesis_v2,
+ letter_combinations,
+ palindromic_substrings,
+ pattern_match,
+ permute_unique,
+ permute,
+ permute_recursive,
+ subsets_unique,
+ subsets,
+ subsets_v2,
+)
+
+import unittest
+
+
+class TestAddOperator(unittest.TestCase):
+ def test_add_operators(self):
+ # "123", 6 -> ["1+2+3", "1*2*3"]
+ s = "123"
+ target = 6
+ self.assertEqual(add_operators(s, target), ["1+2+3", "1*2*3"])
+ # "232", 8 -> ["2*3+2", "2+3*2"]
+ s = "232"
+ target = 8
+ self.assertEqual(add_operators(s, target), ["2+3*2", "2*3+2"])
+
+ s = "123045"
+ target = 3
+ answer = ['1+2+3*0*4*5',
+ '1+2+3*0*45',
+ '1+2-3*0*4*5',
+ '1+2-3*0*45',
+ '1-2+3+0-4+5',
+ '1-2+3-0-4+5',
+ '1*2+3*0-4+5',
+ '1*2-3*0-4+5',
+ '1*23+0-4*5',
+ '1*23-0-4*5',
+ '12+3*0-4-5',
+ '12-3*0-4-5']
+ self.assertEqual(add_operators(s, target), answer)
+
+
+class TestPermuteAndAnagram(unittest.TestCase):
+
+ def test_permute(self):
+ perms = ['abc', 'bac', 'bca', 'acb', 'cab', 'cba']
+ self.assertEqual(perms, permute("abc"))
+
+ def test_permute_iter(self):
+ it = permute_iter("abc")
+ perms = ['abc', 'bac', 'bca', 'acb', 'cab', 'cba']
+ for i in range(len(perms)):
+ self.assertEqual(perms[i], next(it))
+
+ def test_angram(self):
+ self.assertTrue(anagram('apple', 'pleap'))
+ self.assertFalse(anagram("apple", "cherry"))
+
+
+class TestArrayCombinationSum(unittest.TestCase):
+
+ def test_array_sum_combinations(self):
+ A = [1, 2, 3, 3]
+ B = [2, 3, 3, 4]
+ C = [2, 3, 3, 4]
+ target = 7
+ answer = [[1, 2, 4], [1, 3, 3], [1, 3, 3], [1, 3, 3],
+ [1, 3, 3], [1, 4, 2], [2, 2, 3], [2, 2, 3],
+ [2, 3, 2], [2, 3, 2], [3, 2, 2], [3, 2, 2]]
+ answer.sort()
+ self.assertListEqual(sorted(array_sum_combinations(A, B, C, target)),
+ answer)
+
+ def test_unique_array_sum_combinations(self):
+ A = [1, 2, 3, 3]
+ B = [2, 3, 3, 4]
+ C = [2, 3, 3, 4]
+ target = 7
+ answer = [(2, 3, 2), (3, 2, 2), (1, 2, 4),
+ (1, 4, 2), (2, 2, 3), (1, 3, 3)]
+ answer.sort()
+ self.assertListEqual(sorted(unique_array_sum_combinations(A, B, C,
+ target)),
+ answer)
+
+
+class TestCombinationSum(unittest.TestCase):
+
+ def check_sum(self, nums, target):
+ if sum(nums) == target:
+ return (True, nums)
+ else:
+ return (False, nums)
+
+ def test_combination_sum(self):
+ candidates1 = [2, 3, 6, 7]
+ target1 = 7
+ answer1 = [
+ [2, 2, 3],
+ [7]
+ ]
+ self.assertEqual(combination_sum(candidates1, target1), answer1)
+
+ candidates2 = [2, 3, 5]
+ target2 = 8
+ answer2 = [
+ [2, 2, 2, 2],
+ [2, 3, 3],
+ [3, 5]
+ ]
+ self.assertEqual(combination_sum(candidates2, target2), answer2)
+
+
+class TestFactorCombinations(unittest.TestCase):
+
+ def test_get_factors(self):
+ target1 = 32
+ answer1 = [
+ [2, 16],
+ [2, 2, 8],
+ [2, 2, 2, 4],
+ [2, 2, 2, 2, 2],
+ [2, 4, 4],
+ [4, 8]
+ ]
+ self.assertEqual(sorted(get_factors(target1)), sorted(answer1))
+
+ target2 = 12
+ answer2 = [
+ [2, 6],
+ [2, 2, 3],
+ [3, 4]
+ ]
+ self.assertEqual(sorted(get_factors(target2)), sorted(answer2))
+ self.assertEqual(sorted(get_factors(1)), [])
+ self.assertEqual(sorted(get_factors(37)), [])
+
+ def test_recursive_get_factors(self):
+ target1 = 32
+ answer1 = [
+ [2, 16],
+ [2, 2, 8],
+ [2, 2, 2, 4],
+ [2, 2, 2, 2, 2],
+ [2, 4, 4],
+ [4, 8]
+ ]
+ self.assertEqual(sorted(recursive_get_factors(target1)),
+ sorted(answer1))
+
+ target2 = 12
+ answer2 = [
+ [2, 6],
+ [2, 2, 3],
+ [3, 4]
+ ]
+ self.assertEqual(sorted(recursive_get_factors(target2)),
+ sorted(answer2))
+ self.assertEqual(sorted(recursive_get_factors(1)), [])
+ self.assertEqual(sorted(recursive_get_factors(37)), [])
+
+
+class TestFindWords(unittest.TestCase):
+
+ def test_normal(self):
+ board = [
+ ['o', 'a', 'a', 'n'],
+ ['e', 't', 'a', 'e'],
+ ['i', 'h', 'k', 'r'],
+ ['i', 'f', 'l', 'v']
+ ]
+
+ words = ["oath", "pea", "eat", "rain"]
+ result = find_words(board, words)
+ test_result = ['oath', 'eat']
+ self.assertEqual(sorted(result),sorted(test_result))
+
+ def test_none(self):
+ board = [
+ ['o', 'a', 'a', 'n'],
+ ['e', 't', 'a', 'e'],
+ ['i', 'h', 'k', 'r'],
+ ['i', 'f', 'l', 'v']
+ ]
+
+ words = ["chicken", "nugget", "hello", "world"]
+ self.assertEqual(find_words(board, words), [])
+
+ def test_empty(self):
+ board = []
+ words = []
+ self.assertEqual(find_words(board, words), [])
+
+ def test_uneven(self):
+ board = [
+ ['o', 'a', 'a', 'n'],
+ ['e', 't', 'a', 'e']
+ ]
+ words = ["oath", "pea", "eat", "rain"]
+ self.assertEqual(find_words(board, words), ['eat'])
+
+ def test_repeat(self):
+ board = [
+ ['a', 'a', 'a'],
+ ['a', 'a', 'a'],
+ ['a', 'a', 'a']
+ ]
+ words = ["a", "aa", "aaa", "aaaa", "aaaaa"]
+ self.assertTrue(len(find_words(board, words)) == 5)
+
+
+class TestGenerateAbbreviations(unittest.TestCase):
+ def test_generate_abbreviations(self):
+ word1 = "word"
+ answer1 = ['word', 'wor1', 'wo1d', 'wo2', 'w1rd', 'w1r1', 'w2d', 'w3',
+ '1ord', '1or1', '1o1d', '1o2', '2rd', '2r1', '3d', '4']
+ self.assertEqual(sorted(generate_abbreviations(word1)),
+ sorted(answer1))
+
+ word2 = "hello"
+ answer2 = ['hello', 'hell1', 'hel1o', 'hel2', 'he1lo', 'he1l1', 'he2o',
+ 'he3', 'h1llo', 'h1ll1', 'h1l1o', 'h1l2', 'h2lo', 'h2l1',
+ 'h3o', 'h4', '1ello', '1ell1', '1el1o', '1el2', '1e1lo',
+ '1e1l1', '1e2o', '1e3', '2llo', '2ll1', '2l1o', '2l2',
+ '3lo', '3l1', '4o', '5']
+ self.assertEqual(sorted(generate_abbreviations(word2)),
+ sorted(answer2))
+
+
+class TestPatternMatch(unittest.TestCase):
+
+ def test_pattern_match(self):
+ pattern1 = "abab"
+ string1 = "redblueredblue"
+ pattern2 = "aaaa"
+ string2 = "asdasdasdasd"
+ pattern3 = "aabb"
+ string3 = "xyzabcxzyabc"
+
+ self.assertTrue(pattern_match(pattern1, string1))
+ self.assertTrue(pattern_match(pattern2, string2))
+ self.assertFalse(pattern_match(pattern3, string3))
+
+
+class TestGenerateParenthesis(unittest.TestCase):
+
+ def test_generate_parenthesis(self):
+ self.assertEqual(generate_parenthesis_v1(2), ['()()', '(())'])
+ self.assertEqual(generate_parenthesis_v1(3), ['()()()', '()(())',
+ '(())()', '(()())', '((()))'])
+ self.assertEqual(generate_parenthesis_v2(2), ['(())', '()()'])
+ self.assertEqual(generate_parenthesis_v2(3), ['((()))', '(()())',
+ '(())()', '()(())', '()()()'])
+
+
+class TestLetterCombinations(unittest.TestCase):
+
+ def test_letter_combinations(self):
+ digit1 = "23"
+ answer1 = ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]
+ self.assertEqual(sorted(letter_combinations(digit1)), sorted(answer1))
+
+ digit2 = "34"
+ answer2 = ['dg', 'dh', 'di', 'eg', 'eh', 'ei', 'fg', 'fh', 'fi']
+ self.assertEqual(sorted(letter_combinations(digit2)), sorted(answer2))
+
+
+class TestPalindromicSubstrings(unittest.TestCase):
+
+ def test_palindromic_substrings(self):
+ string1 = "abc"
+ answer1 = [['a', 'b', 'c']]
+ self.assertEqual(palindromic_substrings(string1), sorted(answer1))
+
+ string2 = "abcba"
+ answer2 = [['abcba'], ['a', 'bcb', 'a'], ['a', 'b', 'c', 'b', 'a']]
+ self.assertEqual(sorted(palindromic_substrings(string2)),
+ sorted(answer2))
+
+ string3 = "abcccba"
+ answer3 = [['abcccba'], ['a', 'bcccb', 'a'],
+ ['a', 'b', 'ccc', 'b', 'a'],
+ ['a', 'b', 'cc', 'c', 'b', 'a'],
+ ['a', 'b', 'c', 'cc', 'b', 'a'],
+ ['a', 'b', 'c', 'c', 'c', 'b', 'a']]
+ self.assertEqual(sorted(palindromic_substrings(string3)),
+ sorted(answer3))
+
+
+class TestPermuteUnique(unittest.TestCase):
+
+ def test_permute_unique(self):
+ nums1 = [1, 1, 2]
+ answer1 = [[2, 1, 1], [1, 2, 1], [1, 1, 2]]
+ self.assertEqual(sorted(permute_unique(nums1)), sorted(answer1))
+
+ nums2 = [1, 2, 1, 3]
+ answer2 = [[3, 1, 2, 1], [1, 3, 2, 1], [1, 2, 3, 1], [1, 2, 1, 3],
+ [3, 2, 1, 1], [2, 3, 1, 1], [2, 1, 3, 1], [2, 1, 1, 3],
+ [3, 1, 1, 2], [1, 3, 1, 2], [1, 1, 3, 2], [1, 1, 2, 3]]
+ self.assertEqual(sorted(permute_unique(nums2)), sorted(answer2))
+
+ nums3 = [1, 2, 3]
+ answer3 = [[3, 2, 1], [2, 3, 1], [2, 1, 3], [3, 1, 2],
+ [1, 3, 2], [1, 2, 3]]
+ self.assertEqual(sorted(permute_unique(nums3)), sorted(answer3))
+
+
+class TestPermute(unittest.TestCase):
+
+ def test_permute(self):
+ nums1 = [1, 2, 3, 4]
+ answer1 = [[1, 2, 3, 4], [2, 1, 3, 4], [2, 3, 1, 4], [2, 3, 4, 1],
+ [1, 3, 2, 4], [3, 1, 2, 4], [3, 2, 1, 4], [3, 2, 4, 1],
+ [1, 3, 4, 2], [3, 1, 4, 2], [3, 4, 1, 2], [3, 4, 2, 1],
+ [1, 2, 4, 3], [2, 1, 4, 3], [2, 4, 1, 3], [2, 4, 3, 1],
+ [1, 4, 2, 3], [4, 1, 2, 3], [4, 2, 1, 3], [4, 2, 3, 1],
+ [1, 4, 3, 2], [4, 1, 3, 2], [4, 3, 1, 2], [4, 3, 2, 1]]
+ self.assertEqual(sorted(permute(nums1)), sorted(answer1))
+
+ nums2 = [1, 2, 3]
+ answer2 = [[3, 2, 1], [2, 3, 1], [2, 1, 3], [3, 1, 2],
+ [1, 3, 2], [1, 2, 3]]
+ self.assertEqual(sorted(permute(nums2)), sorted(answer2))
+
+ def test_permute_recursive(self):
+ nums1 = [1, 2, 3, 4]
+ answer1 = [[1, 2, 3, 4], [2, 1, 3, 4], [2, 3, 1, 4], [2, 3, 4, 1],
+ [1, 3, 2, 4], [3, 1, 2, 4], [3, 2, 1, 4], [3, 2, 4, 1],
+ [1, 3, 4, 2], [3, 1, 4, 2], [3, 4, 1, 2], [3, 4, 2, 1],
+ [1, 2, 4, 3], [2, 1, 4, 3], [2, 4, 1, 3], [2, 4, 3, 1],
+ [1, 4, 2, 3], [4, 1, 2, 3], [4, 2, 1, 3], [4, 2, 3, 1],
+ [1, 4, 3, 2], [4, 1, 3, 2], [4, 3, 1, 2], [4, 3, 2, 1]]
+ self.assertEqual(sorted(permute_recursive(nums1)), sorted(answer1))
+
+ nums2 = [1, 2, 3]
+ answer2 = [[3, 2, 1], [2, 3, 1], [2, 1, 3], [3, 1, 2],
+ [1, 3, 2], [1, 2, 3]]
+ self.assertEqual(sorted(permute_recursive(nums2)), sorted(answer2))
+
+
+class TestSubsetsUnique(unittest.TestCase):
+
+ def test_subsets_unique(self):
+ nums1 = [1, 2, 2]
+ answer1 = [(1, 2), (1,), (1, 2, 2), (2,), (), (2, 2)]
+ self.assertEqual(sorted(subsets_unique(nums1)), sorted(answer1))
+
+ nums2 = [1, 2, 3, 4]
+ answer2 = [(1, 2), (1, 3), (1, 2, 3, 4), (1,), (2,), (3,),
+ (1, 4), (1, 2, 3), (4,), (), (2, 3), (1, 2, 4),
+ (1, 3, 4), (2, 3, 4), (3, 4), (2, 4)]
+ self.assertEqual(sorted(subsets_unique(nums2)), sorted(answer2))
+
+
+class TestSubsets(unittest.TestCase):
+
+ def test_subsets(self):
+ nums1 = [1, 2, 3]
+ answer1 = [[1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3], []]
+ self.assertEqual(sorted(subsets(nums1)), sorted(answer1))
+
+ nums2 = [1, 2, 3, 4]
+ answer2 = [[1, 2, 3, 4], [1, 2, 3], [1, 2, 4], [1, 2], [1, 3, 4],
+ [1, 3], [1, 4], [1], [2, 3, 4], [2, 3], [2, 4], [2],
+ [3, 4], [3], [4], []]
+ self.assertEqual(sorted(subsets(nums2)), sorted(answer2))
+
+ def test_subsets_v2(self):
+ nums1 = [1, 2, 3]
+ answer1 = [[1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3], []]
+ self.assertEqual(sorted(subsets_v2(nums1)), sorted(answer1))
+
+ nums2 = [1, 2, 3, 4]
+ answer2 = [[1, 2, 3, 4], [1, 2, 3], [1, 2, 4], [1, 2], [1, 3, 4],
+ [1, 3], [1, 4], [1], [2, 3, 4], [2, 3], [2, 4], [2],
+ [3, 4], [3], [4], []]
+ self.assertEqual(sorted(subsets_v2(nums2)), sorted(answer2))
+
+
+if __name__ == '__main__':
+
+ unittest.main()
diff --git a/tests/test_bfs.py b/tests/test_bfs.py
new file mode 100644
index 000000000..f9b22f134
--- /dev/null
+++ b/tests/test_bfs.py
@@ -0,0 +1,62 @@
+from algorithms.bfs import (
+ count_islands,
+ maze_search,
+ ladder_length
+)
+
+import unittest
+
+
+class TestCountIslands(unittest.TestCase):
+
+ def test_count_islands(self):
+ grid_1 = [[1, 1, 1, 1, 0], [1, 1, 0, 1, 0], [1, 1, 0, 0, 0],
+ [0, 0, 0, 0, 0]]
+ self.assertEqual(1, count_islands(grid_1))
+ grid_2 = [[1, 1, 0, 0, 0], [1, 1, 0, 0, 0], [0, 0, 1, 0, 0],
+ [0, 0, 0, 1, 1]]
+ self.assertEqual(3, count_islands(grid_2))
+ grid_3 = [[1, 1, 1, 0, 0, 0], [1, 1, 0, 0, 0, 0], [1, 0, 0, 0, 0, 1],
+ [0, 0, 1, 1, 0, 1], [0, 0, 1, 1, 0, 0]]
+ self.assertEqual(3, count_islands(grid_3))
+ grid_4 = [[1, 1, 0, 0, 1, 1], [0, 0, 1, 1, 0, 0], [0, 0, 0, 0, 0, 1],
+ [1, 1, 1, 1, 0, 0]]
+ self.assertEqual(5, count_islands(grid_4))
+
+
+class TestMazeSearch(unittest.TestCase):
+
+ def test_maze_search(self):
+ grid_1 = [[1, 0, 1, 1, 1, 1], [1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 1],
+ [1, 1, 1, 0, 1, 1]]
+ self.assertEqual(14, maze_search(grid_1))
+ grid_2 = [[1, 0, 0], [0, 1, 1], [0, 1, 1]]
+ self.assertEqual(-1, maze_search(grid_2))
+
+
+class TestWordLadder(unittest.TestCase):
+
+ def test_ladder_length(self):
+
+ # hit -> hot -> dot -> dog -> cog
+ self.assertEqual(5, ladder_length('hit', 'cog', ["hot", "dot", "dog",
+ "lot", "log"]))
+
+ # pick -> sick -> sink -> sank -> tank == 5
+ self.assertEqual(5, ladder_length('pick', 'tank',
+ ['tock', 'tick', 'sank', 'sink',
+ 'sick']))
+
+ # live -> life == 1, no matter what is the word_list.
+ self.assertEqual(1, ladder_length('live', 'life', ['hoho', 'luck']))
+
+ # 0 length from ate -> ate
+ self.assertEqual(0, ladder_length('ate', 'ate', []))
+
+ # not possible to reach !
+ self.assertEqual(-1, ladder_length('rahul', 'coder', ['blahh',
+ 'blhah']))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_bit.py b/tests/test_bit.py
new file mode 100644
index 000000000..c494a9762
--- /dev/null
+++ b/tests/test_bit.py
@@ -0,0 +1,274 @@
+from algorithms.bit import (
+ add_bitwise_operator,
+ count_ones_iter, count_ones_recur,
+ count_flips_to_convert,
+ find_missing_number, find_missing_number2,
+ flip_bit_longest_seq,
+ is_power_of_two,
+ reverse_bits,
+ single_number,
+ single_number2,
+ single_number3,
+ subsets,
+ get_bit, set_bit, clear_bit, update_bit,
+ int_to_bytes_big_endian, int_to_bytes_little_endian,
+ bytes_big_endian_to_int, bytes_little_endian_to_int,
+ swap_pair,
+ find_difference,
+ has_alternative_bit, has_alternative_bit_fast,
+ insert_one_bit, insert_mult_bits,
+ remove_bit,
+ binary_gap
+)
+
+import unittest
+import random
+
+
+class TestSuite(unittest.TestCase):
+
+ def setUp(self):
+ """Initialize seed."""
+ random.seed("test")
+
+ def test_add_bitwise_operator(self):
+ self.assertEqual(5432 + 97823, add_bitwise_operator(5432, 97823))
+ self.assertEqual(0, add_bitwise_operator(0, 0))
+ self.assertEqual(10, add_bitwise_operator(10, 0))
+ self.assertEqual(10, add_bitwise_operator(0, 10))
+
+ def test_count_ones_recur(self):
+
+ # 8 -> 1000
+ self.assertEqual(1, count_ones_recur(8))
+
+ # 109 -> 1101101
+ self.assertEqual(5, count_ones_recur(109))
+
+ # 63 -> 111111
+ self.assertEqual(6, count_ones_recur(63))
+
+ # 0 -> 0
+ self.assertEqual(0, count_ones_recur(0))
+
+ def test_count_ones_iter(self):
+
+ # 8 -> 1000
+ self.assertEqual(1, count_ones_iter(8))
+
+ # 109 -> 1101101
+ self.assertEqual(5, count_ones_iter(109))
+
+ # 63 -> 111111
+ self.assertEqual(6, count_ones_iter(63))
+
+ # 0 -> 0
+ self.assertEqual(0, count_ones_iter(0))
+
+ def test_count_flips_to_convert(self):
+ # 29: 11101 and 15: 01111
+ self.assertEqual(2, count_flips_to_convert(29, 15))
+ # 45: 0000101101 and 987: 1111011011
+ self.assertEqual(8, count_flips_to_convert(45, 987))
+ # 34: 100010
+ self.assertEqual(0, count_flips_to_convert(34, 34))
+ # 34: 100010 and 53: 110101
+ self.assertEqual(4, count_flips_to_convert(34, 53))
+
+ def test_find_missing_number(self):
+
+ self.assertEqual(7, find_missing_number([4, 1, 3, 0, 6, 5, 2]))
+ self.assertEqual(0, find_missing_number([1]))
+ self.assertEqual(1, find_missing_number([0]))
+
+ nums = [i for i in range(100000) if i != 12345]
+ random.shuffle(nums)
+ self.assertEqual(12345, find_missing_number(nums))
+
+ def test_find_missing_number2(self):
+
+ self.assertEqual(7, find_missing_number2([4, 1, 3, 0, 6, 5, 2]))
+ self.assertEqual(0, find_missing_number2([1]))
+ self.assertEqual(1, find_missing_number2([0]))
+
+ nums = [i for i in range(100000) if i != 12345]
+ random.shuffle(nums)
+ self.assertEqual(12345, find_missing_number2(nums))
+
+ def test_flip_bit_longest_seq(self):
+ # 1775: 11011101111
+ self.assertEqual(8, flip_bit_longest_seq(1775))
+ # 5: 101
+ self.assertEqual(3, flip_bit_longest_seq(5))
+ # 71: 1000111
+ self.assertEqual(4, flip_bit_longest_seq(71))
+ # 0: 0
+ self.assertEqual(1, flip_bit_longest_seq(0))
+
+ def test_is_power_of_two(self):
+
+ self.assertTrue(is_power_of_two(64))
+ self.assertFalse(is_power_of_two(91))
+ self.assertTrue(is_power_of_two(2**1001))
+ self.assertTrue(is_power_of_two(1))
+ self.assertFalse(is_power_of_two(0))
+
+ def test_reverse_bits(self):
+
+ self.assertEqual(43261596, reverse_bits(964176192))
+ self.assertEqual(964176192, reverse_bits(43261596))
+ self.assertEqual(1, reverse_bits(2147483648))
+
+ # bin(0) => 00000000000000000000000000000000
+ self.assertEqual(0, reverse_bits(0))
+
+ # bin(2**32 - 1) => 11111111111111111111111111111111
+ self.assertEqual(2**32 - 1, reverse_bits(2**32 - 1))
+
+ def test_single_number(self):
+
+ random.seed('test')
+
+ self.assertEqual(0, single_number([1, 0, 2, 1, 2, 3, 3]))
+ self.assertEqual(101, single_number([101]))
+
+ single = random.randint(1, 100000)
+ nums = [random.randint(1, 100000) for _ in range(1000)]
+ nums *= 2 # nums contains pairs of random integers
+ nums.append(single)
+ random.shuffle(nums)
+
+ self.assertEqual(single, single_number(nums))
+
+ def test_single_number2(self):
+
+ self.assertEqual(3, single_number2([4, 2, 3, 2, 1, 1, 4, 2, 4, 1]))
+ single = random.randint(1, 100000)
+ nums = [random.randint(1, 100000) for _ in range(1000)]
+ nums *= 3 # nums contains triplets of random integers
+ nums.append(single)
+ random.shuffle(nums)
+ self.assertEqual(single, single_number2(nums))
+
+ def test_single_number3(self):
+ self.assertEqual(sorted([2, 5]),
+ sorted(single_number3([2, 1, 5, 6, 6, 1])))
+ self.assertEqual(sorted([4, 3]),
+ sorted(single_number3([9, 9, 4, 3])))
+
+ def test_subsets(self):
+
+ self.assertSetEqual(subsets([1, 2, 3]),
+ {(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3),
+ (1, 2, 3)})
+
+ self.assertSetEqual(subsets([10, 20, 30, 40]),
+ {(10, 40), (10, 20, 40), (10, 30),
+ (10, 20, 30, 40), (40,),
+ (10, 30, 40), (30,), (20, 30), (30, 40), (10,),
+ (),
+ (10, 20), (20, 40), (20, 30, 40), (10, 20, 30),
+ (20,)})
+
+ def test_get_bit(self):
+ # 22 = 10110
+ self.assertEqual(1, get_bit(22, 2))
+ self.assertEqual(0, get_bit(22, 3))
+
+ def test_set_bit(self):
+ # 22 = 10110 --> after set bit at 3th position: 30 = 11110
+ self.assertEqual(30, set_bit(22, 3))
+
+ def test_clear_bit(self):
+ # 22 = 10110 --> after clear bit at 2nd position: 20 = 10010
+ self.assertEqual(18, clear_bit(22, 2))
+
+ def test_update_bit(self):
+ # 22 = 10110 --> after update bit at 3th position with
+ # value 1: 30 = 11110
+ self.assertEqual(30, update_bit(22, 3, 1))
+ # 22 = 10110 --> after update bit at 2nd position with
+ # value 0: 20 = 10010
+ self.assertEqual(18, update_bit(22, 2, 0))
+
+ def test_int_to_bytes_big_endian(self):
+ self.assertEqual(b'\x11', int_to_bytes_big_endian(17))
+
+ def test_int_to_bytes_little_endian(self):
+ self.assertEqual(b'\x11', int_to_bytes_little_endian(17))
+
+ def test_bytes_big_endian_to_int(self):
+ self.assertEqual(17, bytes_big_endian_to_int(b'\x11'))
+
+ def test_bytes_little_endian_to_int(self):
+ self.assertEqual(17, bytes_little_endian_to_int(b'\x11'))
+
+ def test_swap_pair(self):
+ # 22: 10110 --> 41: 101001
+ self.assertEqual(41, swap_pair(22))
+ # 10: 1010 --> 5 : 0101
+ self.assertEqual(5, swap_pair(10))
+
+ def test_find_difference(self):
+ self.assertEqual('e', find_difference("abcd", "abecd"))
+
+ def test_has_alternative_bit(self):
+ self.assertTrue(has_alternative_bit(5))
+ self.assertFalse(has_alternative_bit(7))
+ self.assertFalse(has_alternative_bit(11))
+ self.assertTrue(has_alternative_bit(10))
+
+ def test_has_alternative_bit_fast(self):
+ self.assertTrue(has_alternative_bit_fast(5))
+ self.assertFalse(has_alternative_bit_fast(7))
+ self.assertFalse(has_alternative_bit_fast(11))
+ self.assertTrue(has_alternative_bit_fast(10))
+
+ def test_insert_one_bit(self):
+ """
+ Input: num = 10101 (21)
+ insert_one_bit(num, 1, 2): 101101 (45)
+ insert_one_bit(num, 0 ,2): 101001 (41)
+ insert_one_bit(num, 1, 5): 110101 (53)
+ insert_one_bit(num, 1, 0): 101010 (42)
+ """
+ self.assertEqual(45, insert_one_bit(21, 1, 2))
+ self.assertEqual(41, insert_one_bit(21, 0, 2))
+ self.assertEqual(53, insert_one_bit(21, 1, 5))
+ self.assertEqual(43, insert_one_bit(21, 1, 0))
+
+ def test_insert_mult_bits(self):
+ """
+ Input: num = 101 (5)
+ insert_mult_bits(num, 7, 3, 1): 101111 (47)
+ insert_mult_bits(num, 7, 3, 0): 101111 (47)
+ insert_mult_bits(num, 7, 3, 3): 111101 (61)
+ """
+ self.assertEqual(47, insert_mult_bits(5, 7, 3, 1))
+ self.assertEqual(47, insert_mult_bits(5, 7, 3, 0))
+ self.assertEqual(61, insert_mult_bits(5, 7, 3, 3))
+
+ def test_remove_bit(self):
+ """
+ Input: num = 10101 (21)
+ remove_bit(num, 2): output = 1001 (9)
+ remove_bit(num, 4): output = 101 (5)
+ remove_bit(num, 0): output = 1010 (10)
+ """
+ self.assertEqual(9, remove_bit(21, 2))
+ self.assertEqual(5, remove_bit(21, 4))
+ self.assertEqual(10, remove_bit(21, 0))
+
+ def test_binary_gap(self):
+ # 22 = 10110
+ self.assertEqual(2, binary_gap(22))
+ # 6 = 110
+ self.assertEqual(1, binary_gap(6))
+ # 8 = 1000
+ self.assertEqual(0, binary_gap(8))
+ # 145 = 10010001
+ self.assertEqual(4, binary_gap(145))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_compression.py b/tests/test_compression.py
new file mode 100644
index 000000000..503369c4a
--- /dev/null
+++ b/tests/test_compression.py
@@ -0,0 +1,74 @@
+from algorithms.compression.huffman_coding import HuffmanCoding
+from algorithms.compression.rle_compression import (decode_rle, encode_rle)
+from algorithms.compression.elias import (elias_gamma, elias_delta)
+
+import unittest
+
+
+class TestHuffmanCoding(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.file_in_name = "huffman_coding_in.txt"
+ cls.file_out_bin_name = "huffman_coding_out.bin"
+ cls.file_out_name = "huffman_coding_out.txt"
+
+ def setUp(self):
+ import random
+ random.seed(1951)
+ with open(self.file_in_name, "wb") as file_in:
+ for i in range(10000):
+ file_in.write(bytes([random.randrange(0, 256)]))
+
+ def test_huffman_coding(self):
+ HuffmanCoding.encode_file(self.file_in_name, self.file_out_bin_name)
+ HuffmanCoding.decode_file(self.file_out_bin_name, self.file_out_name)
+
+ with open(self.file_in_name, "rb") as file_1, open(self.file_out_name, "rb") as file_2:
+ content_1 = file_1.read()
+ content_2 = file_2.read()
+
+ self.assertEqual(content_1, content_2)
+
+ def tearDown(self):
+ import os
+ os.remove(self.file_in_name)
+ os.remove(self.file_out_bin_name)
+ os.remove(self.file_out_name)
+
+
+class TestRLECompression(unittest.TestCase):
+
+ def test_encode_rle(self):
+ self.assertEqual('12W1B12W3B24W1B14W',
+ encode_rle('WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'))
+
+ def test_decode_rle(self):
+ self.assertEqual('WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW',
+ decode_rle('12W1B12W3B24W1B14W'))
+
+
+class TestEliasCoding(unittest.TestCase):
+
+ def test_elias_gamma(self):
+ correct_result = ['0', '00', '100', '101', '11000', '11001', '11010',
+ '11011', '1110000', '1110001', '1110010']
+
+ result = []
+ for i in range(11):
+ result.append(elias_gamma(i))
+
+ self.assertEqual(correct_result, result)
+
+ def test_elias_delta(self):
+ correct_result = ['0', '000', '1000', '1001', '10100', '10101',
+ '10110', '10111', '11000000', '11000001', '11000010']
+
+ result = []
+ for i in range(11):
+ result.append(elias_delta(i))
+
+ self.assertEqual(correct_result, result)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_dfs.py b/tests/test_dfs.py
new file mode 100644
index 000000000..3164ab873
--- /dev/null
+++ b/tests/test_dfs.py
@@ -0,0 +1,80 @@
+from algorithms.dfs import (
+ get_factors, get_factors_iterative1, get_factors_iterative2,
+ num_islands,
+ pacific_atlantic,
+ Sudoku,
+ walls_and_gates,
+ find_path
+)
+
+import unittest
+
+
+class TestAllFactors(unittest.TestCase):
+ def test_get_factors(self):
+ self.assertEqual([[2, 16], [2, 2, 8], [2, 2, 2, 4], [2, 2, 2, 2, 2],
+ [2, 4, 4], [4, 8]], get_factors(32))
+
+ def test_get_factors_iterative1(self):
+ self.assertEqual([[2, 16], [4, 8], [2, 2, 8], [2, 4, 4], [2, 2, 2, 4],
+ [2, 2, 2, 2, 2]], get_factors_iterative1(32))
+
+ def test_get_factors_iterative2(self):
+ self.assertEqual([[2, 2, 2, 2, 2], [2, 2, 2, 4], [2, 2, 8], [2, 4, 4],
+ [2, 16], [4, 8]], get_factors_iterative2(32))
+
+
+class TestCountIslands(unittest.TestCase):
+ def test_num_islands(self):
+ self.assertEqual(1, num_islands([[1, 1, 1, 1, 0], [1, 1, 0, 1, 0],
+ [1, 1, 0, 0, 0], [0, 0, 0, 0, 0]]))
+ self.assertEqual(3, num_islands([[1, 1, 0, 0, 0], [1, 1, 0, 0, 0],
+ [0, 0, 1, 0, 0], [0, 0, 0, 1, 1]]))
+
+
+class TestPacificAtlantic(unittest.TestCase):
+ def test_pacific_atlantic(self):
+ self.assertEqual([[0, 4], [1, 3], [1, 4], [2, 2], [3, 0],
+ [3, 1], [4, 0]], pacific_atlantic([[1, 2, 2, 3, 5],
+ [3, 2, 3, 4, 4],
+ [2, 4, 5, 3, 1],
+ [6, 7, 1, 4, 5],
+ [5, 1, 1, 2, 4]]))
+
+
+class TestSudoku(unittest.TestCase):
+ def test_sudoku_solver(self):
+ board = [["5", "3", "."], ["6", ".", "."], [".", "9", "8"]]
+ test_obj = Sudoku(board, 3, 3)
+ test_obj.solve()
+ self.assertEqual([['5', '3', '1'], ['6', '1', '2'],
+ ['1', '9', '8']], test_obj.board)
+
+
+class TestWallsAndGates(unittest.TestCase):
+ def test_walls_and_gates(self):
+ rooms = [[float("inf"), -1, 0, float("inf")],
+ [float("inf"), float("inf"), float("inf"), -1],
+ [float("inf"), -1, float("inf"), -1],
+ [0, -1, float("inf"), float("inf")]]
+ walls_and_gates(rooms)
+ self.assertEqual([[3, -1, 0, 1], [2, 2, 1, -1], [1, -1, 2, -1],
+ [0, -1, 3, 4]], rooms)
+
+
+class TestMazeSearch(unittest.TestCase):
+ def test_maze_search(self):
+ maze_1 = [[1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1,
+ 1, 0, 1, 1, 1],
+ [1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,
+ 0, 1, 1, 1, 0, 1]]
+ self.assertEqual(37, find_path(maze_1))
+ maze_2 = [[1, 0, 1, 1, 1, 1], [1, 0, 1, 0, 1, 0],
+ [1, 0, 1, 0, 1, 1], [1, 1, 1, 0, 1, 1]]
+ self.assertEqual(14, find_path(maze_2))
+ maze_3 = [[1, 0, 0], [0, 1, 1], [0, 1, 1]]
+ self.assertEqual(-1, find_path(maze_3))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_dp.py b/tests/test_dp.py
new file mode 100644
index 000000000..e92800a11
--- /dev/null
+++ b/tests/test_dp.py
@@ -0,0 +1,263 @@
+from algorithms.dp import (
+ max_profit_naive, max_profit_optimized,
+ climb_stairs, climb_stairs_optimized,
+ count,
+ combination_sum_topdown, combination_sum_bottom_up,
+ edit_distance,
+ egg_drop,
+ fib_recursive, fib_list, fib_iter,
+ hosoya_testing,
+ house_robber,
+ Job, schedule,
+ Item, get_maximum_value,
+ longest_increasing_subsequence,
+ longest_increasing_subsequence_optimized,
+ longest_increasing_subsequence_optimized2,
+ int_divide,find_k_factor,
+ planting_trees, regex_matching
+)
+
+
+import unittest
+
+
+class TestBuySellStock(unittest.TestCase):
+ def test_max_profit_naive(self):
+ self.assertEqual(max_profit_naive([7, 1, 5, 3, 6, 4]), 5)
+ self.assertEqual(max_profit_naive([7, 6, 4, 3, 1]), 0)
+
+ def test_max_profit_optimized(self):
+ self.assertEqual(max_profit_optimized([7, 1, 5, 3, 6, 4]), 5)
+ self.assertEqual(max_profit_optimized([7, 6, 4, 3, 1]), 0)
+
+
+class TestClimbingStairs(unittest.TestCase):
+ def test_climb_stairs(self):
+ self.assertEqual(climb_stairs(2), 2)
+ self.assertEqual(climb_stairs(10), 89)
+
+ def test_climb_stairs_optimized(self):
+ self.assertEqual(climb_stairs_optimized(2), 2)
+ self.assertEqual(climb_stairs_optimized(10), 89)
+
+
+class TestCoinChange(unittest.TestCase):
+ def test_count(self):
+ self.assertEqual(count([1, 2, 3], 4), 4)
+ self.assertEqual(count([2, 5, 3, 6], 10), 5)
+
+
+class TestCombinationSum(unittest.TestCase):
+ def test_combination_sum_topdown(self):
+ self.assertEqual(combination_sum_topdown([1, 2, 3], 4), 7)
+
+ def test_combination_sum_bottom_up(self):
+ self.assertEqual(combination_sum_bottom_up([1, 2, 3], 4), 7)
+
+
+class TestEditDistance(unittest.TestCase):
+ def test_edit_distance(self):
+ self.assertEqual(edit_distance('food', 'money'), 4)
+ self.assertEqual(edit_distance('horse', 'ros'), 3)
+
+
+class TestEggDrop(unittest.TestCase):
+ def test_egg_drop(self):
+ self.assertEqual(egg_drop(1, 2), 2)
+ self.assertEqual(egg_drop(2, 6), 3)
+ self.assertEqual(egg_drop(3, 14), 4)
+
+
+class TestFib(unittest.TestCase):
+ def test_fib_recursive(self):
+ self.assertEqual(fib_recursive(10), 55)
+ self.assertEqual(fib_recursive(30), 832040)
+
+ def test_fib_list(self):
+ self.assertEqual(fib_list(10), 55)
+ self.assertEqual(fib_list(30), 832040)
+
+ def test_fib_iter(self):
+ self.assertEqual(fib_iter(10), 55)
+ self.assertEqual(fib_iter(30), 832040)
+
+
+class TestHosoyaTriangle(unittest.TestCase):
+ """[summary]
+ Test for the file hosoya_triangle
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_hosoya(self):
+ self.assertEqual([1], hosoya_testing(1))
+ self.assertEqual([1,
+ 1, 1,
+ 2, 1, 2,
+ 3, 2, 2, 3,
+ 5, 3, 4, 3, 5,
+ 8, 5, 6, 6, 5, 8],
+ hosoya_testing(6))
+ self.assertEqual([1,
+ 1, 1,
+ 2, 1, 2,
+ 3, 2, 2, 3,
+ 5, 3, 4, 3, 5,
+ 8, 5, 6, 6, 5, 8,
+ 13, 8, 10, 9, 10, 8, 13,
+ 21, 13, 16, 15, 15, 16, 13, 21,
+ 34, 21, 26, 24, 25, 24, 26, 21, 34,
+ 55, 34, 42, 39, 40, 40, 39, 42, 34, 55],
+ hosoya_testing(10))
+
+
+class TestHouseRobber(unittest.TestCase):
+ def test_house_robber(self):
+ self.assertEqual(44, house_robber([1, 2, 16, 3, 15, 3, 12, 1]))
+
+
+class TestJobScheduling(unittest.TestCase):
+ def test_job_scheduling(self):
+ job1, job2 = Job(1, 3, 2), Job(2, 3, 4)
+ self.assertEqual(4, schedule([job1, job2]))
+
+
+class TestKnapsack(unittest.TestCase):
+ def test_get_maximum_value(self):
+ item1, item2, item3 = Item(60, 10), Item(100, 20), Item(120, 30)
+ self.assertEqual(220, get_maximum_value([item1, item2, item3], 50))
+
+ item1, item2, item3, item4 = Item(60, 5), Item(50, 3), Item(70, 4), Item(30, 2)
+ self.assertEqual(80, get_maximum_value([item1, item2, item3, item4],
+ 5))
+
+
+class TestLongestIncreasingSubsequence(unittest.TestCase):
+ def test_longest_increasing_subsequence(self):
+ sequence = [1, 101, 10, 2, 3, 100, 4, 6, 2]
+ self.assertEqual(5, longest_increasing_subsequence(sequence))
+
+
+class TestLongestIncreasingSubsequenceOptimized(unittest.TestCase):
+ def test_longest_increasing_subsequence_optimized(self):
+ sequence = [1, 101, 10, 2, 3, 100, 4, 6, 2]
+ self.assertEqual(5, longest_increasing_subsequence(sequence))
+
+
+class TestLongestIncreasingSubsequenceOptimized2(unittest.TestCase):
+ def test_longest_increasing_subsequence_optimized2(self):
+ sequence = [1, 101, 10, 2, 3, 100, 4, 6, 2]
+ self.assertEqual(5, longest_increasing_subsequence(sequence))
+
+
+class TestIntDivide(unittest.TestCase):
+ def test_int_divide(self):
+ self.assertEqual(5, int_divide(4))
+ self.assertEqual(42, int_divide(10))
+ self.assertEqual(204226, int_divide(50))
+
+
+class Test_dp_K_Factor(unittest.TestCase):
+ def test_kfactor(self):
+ # Test 1
+ n1 = 4
+ k1 = 1
+ self.assertEqual(find_k_factor(n1, k1), 1)
+
+ # Test 2
+ n2 = 7
+ k2 = 1
+ self.assertEqual(find_k_factor(n2, k2), 70302)
+
+ # Test 3
+ n3 = 10
+ k3 = 2
+ self.assertEqual(find_k_factor(n3, k3), 74357)
+
+ # Test 4
+ n4 = 8
+ k4 = 2
+ self.assertEqual(find_k_factor(n4, k4), 53)
+
+ # Test 5
+ n5 = 9
+ k5 = 1
+ self.assertEqual(find_k_factor(n5, k5), 71284044)
+
+
+class TestPlantingTrees(unittest.TestCase):
+ def test_simple(self):
+ # arrange
+ trees = [0, 1, 10, 10]
+ L = 10
+ W = 1
+
+ # act
+ res = planting_trees(trees, L, W)
+
+ # assert
+ self.assertEqual(res, 2.414213562373095)
+
+ def test_simple2(self):
+ # arrange
+ trees = [0, 3, 5, 5, 6, 9]
+ L = 10
+ W = 1
+
+ # act
+ res = planting_trees(trees, L, W)
+
+ # assert
+ self.assertEqual(res, 9.28538328578604)
+
+class TestRegexMatching(unittest.TestCase):
+ def test_none_0(self):
+ s = ""
+ p = ""
+ self.assertTrue(regex_matching.is_match(s, p))
+
+ def test_none_1(self):
+ s = ""
+ p = "a"
+ self.assertFalse(regex_matching.is_match(s, p))
+
+ def test_no_symbol_equal(self):
+ s = "abcd"
+ p = "abcd"
+ self.assertTrue(regex_matching.is_match(s, p))
+
+ def test_no_symbol_not_equal_0(self):
+ s = "abcd"
+ p = "efgh"
+ self.assertFalse(regex_matching.is_match(s, p))
+
+ def test_no_symbol_not_equal_1(self):
+ s = "ab"
+ p = "abb"
+ self.assertFalse(regex_matching.is_match(s, p))
+
+ def test_symbol_0(self):
+ s = ""
+ p = "a*"
+ self.assertTrue(regex_matching.is_match(s, p))
+
+ def test_symbol_1(self):
+ s = "a"
+ p = "ab*"
+ self.assertTrue(regex_matching.is_match(s, p))
+
+ def test_symbol_2(self):
+ # E.g.
+ # s a b b
+ # p 1 0 0 0
+ # a 0 1 0 0
+ # b 0 0 1 0
+ # * 0 1 1 1
+ s = "abb"
+ p = "ab*"
+ self.assertTrue(regex_matching.is_match(s, p))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_graph.py b/tests/test_graph.py
new file mode 100644
index 000000000..540d29983
--- /dev/null
+++ b/tests/test_graph.py
@@ -0,0 +1,368 @@
+from algorithms.graph import Tarjan
+from algorithms.graph import check_bipartite
+from algorithms.graph.dijkstra import Dijkstra
+from algorithms.graph import ford_fulkerson
+from algorithms.graph import edmonds_karp
+from algorithms.graph import dinic
+from algorithms.graph import maximum_flow_bfs
+from algorithms.graph import maximum_flow_dfs
+from algorithms.graph import all_pairs_shortest_path
+from algorithms.graph import bellman_ford
+from algorithms.graph import count_connected_number_of_component
+from algorithms.graph import prims_minimum_spanning
+from algorithms.graph import check_digraph_strongly_connected
+from algorithms.graph import cycle_detection
+from algorithms.graph import find_path
+from algorithms.graph import path_between_two_vertices_in_digraph
+from algorithms.graph import strongly_connected_components_kosaraju
+
+import unittest
+
+
+class TestTarjan(unittest.TestCase):
+ """
+ Test for the file tarjan.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_tarjan_example_1(self):
+ # Graph from https://en.wikipedia.org/wiki/File:Scc.png
+ example = {
+ 'A': ['B'],
+ 'B': ['C', 'E', 'F'],
+ 'C': ['D', 'G'],
+ 'D': ['C', 'H'],
+ 'E': ['A', 'F'],
+ 'F': ['G'],
+ 'G': ['F'],
+ 'H': ['D', 'G']
+ }
+
+ g = Tarjan(example)
+ self.assertEqual(g.sccs, [['F', 'G'], ['C', 'D', 'H'],
+ ['A', 'B', 'E']])
+
+ def test_tarjan_example_2(self):
+ # Graph from https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm#/media/File:Tarjan%27s_Algorithm_Animation.gif
+ example = {
+ 'A': ['E'],
+ 'B': ['A'],
+ 'C': ['B', 'D'],
+ 'D': ['C'],
+ 'E': ['B'],
+ 'F': ['B', 'E', 'G'],
+ 'G': ['F', 'C'],
+ 'H': ['G', 'H', 'D']
+ }
+
+ g = Tarjan(example)
+ self.assertEqual(g.sccs, [['A', 'B', 'E'], ['C', 'D'], ['F', 'G'],
+ ['H']])
+
+
+class TestCheckBipartite(unittest.TestCase):
+ def test_check_bipartite(self):
+ adj_list_1 = [[0, 0, 1], [0, 0, 1], [1, 1, 0]]
+ self.assertEqual(True, check_bipartite(adj_list_1))
+ adj_list_2 = [[0, 1, 0, 1], [1, 0, 1, 0], [0, 1, 0, 1], [1, 0, 1, 0]]
+ self.assertEqual(True, check_bipartite(adj_list_2))
+ adj_list_3 = [[0, 1, 0, 0], [1, 0, 1, 1], [0, 1, 0, 1], [0, 1, 1, 0]]
+ self.assertEqual(False, check_bipartite(adj_list_3))
+
+
+class TestDijkstra(unittest.TestCase):
+ def test_dijkstra(self):
+ g = Dijkstra(9)
+ g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0],
+ [4, 0, 8, 0, 0, 0, 0, 11, 0],
+ [0, 8, 0, 7, 0, 4, 0, 0, 2],
+ [0, 0, 7, 0, 9, 14, 0, 0, 0],
+ [0, 0, 0, 9, 0, 10, 0, 0, 0],
+ [0, 0, 4, 14, 10, 0, 2, 0, 0],
+ [0, 0, 0, 0, 0, 2, 0, 1, 6],
+ [8, 11, 0, 0, 0, 0, 1, 0, 7],
+ [0, 0, 2, 0, 0, 0, 6, 7, 0]]
+
+ self.assertEqual(g.dijkstra(0), [0, 4, 12, 19, 21, 11, 9, 8, 14])
+
+
+class TestMaximumFlow(unittest.TestCase):
+ """
+ Test for the file maximum_flow.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+ def test_ford_fulkerson(self):
+ capacity = [
+ [0, 10, 10, 0, 0, 0, 0],
+ [0, 0, 2, 0, 4, 8, 0],
+ [0, 0, 0, 0, 0, 9, 0],
+ [0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 10],
+ [0, 0, 0, 0, 6, 0, 10],
+ [0, 0, 0, 0, 0, 0, 0]
+ ]
+ self.assertEqual(19, ford_fulkerson(capacity, 0, 6))
+
+ def test_edmonds_karp(self):
+ capacity = [
+ [0, 10, 10, 0, 0, 0, 0],
+ [0, 0, 2, 0, 4, 8, 0],
+ [0, 0, 0, 0, 0, 9, 0],
+ [0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 10],
+ [0, 0, 0, 0, 6, 0, 10],
+ [0, 0, 0, 0, 0, 0, 0]
+ ]
+ self.assertEqual(19, edmonds_karp(capacity, 0, 6))
+
+ def dinic(self):
+ capacity = [
+ [0, 10, 10, 0, 0, 0, 0],
+ [0, 0, 2, 0, 4, 8, 0],
+ [0, 0, 0, 0, 0, 9, 0],
+ [0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 10],
+ [0, 0, 0, 0, 6, 0, 10],
+ [0, 0, 0, 0, 0, 0, 0]
+ ]
+ self.assertEqual(19, dinic(capacity, 0, 6))
+
+
+class TestMaximum_Flow_Bfs(unittest.TestCase):
+
+ """
+ Test for the file def maximum_flow_bfs.py
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+ def test_maximum_flow_bfs(self):
+ graph = [
+ [0, 16, 13, 0, 0, 0],
+ [0, 0, 10, 12, 0, 0],
+ [0, 4, 0, 0, 14, 0],
+ [0, 0, 9, 0, 0, 20],
+ [0, 0, 0, 7, 0, 4],
+ [0, 0, 0, 0, 0, 0]
+ ]
+ maximum_flow = maximum_flow_bfs(graph)
+
+ self.assertEqual(maximum_flow, 23)
+
+
+class TestMaximum_Flow_Dfs(unittest.TestCase):
+
+ """
+ Test for the file def maximum_flow_dfs.py
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+ def test_maximum_flow_dfs(self):
+ graph = [
+ [0, 16, 13, 0, 0, 0],
+ [0, 0, 10, 12, 0, 0],
+ [0, 4, 0, 0, 14, 0],
+ [0, 0, 9, 0, 0, 20],
+ [0, 0, 0, 7, 0, 4],
+ [0, 0, 0, 0, 0, 0]
+ ]
+ maximum_flow = maximum_flow_dfs(graph)
+
+ self.assertEqual(maximum_flow, 23)
+
+
+class TestAll_Pairs_Shortest_Path(unittest.TestCase):
+ def test_all_pairs_shortest_path(self):
+ graph = [[0, 0.1, 0.101, 0.142, 0.277],
+ [0.465, 0, 0.191, 0.192, 0.587],
+ [0.245, 0.554, 0, 0.333, 0.931],
+ [1.032, 0.668, 0.656, 0, 0.151],
+ [0.867, 0.119, 0.352, 0.398, 0]]
+ result = all_pairs_shortest_path(graph)
+
+ self.assertEqual(result, [
+ [0, 0.1, 0.101, 0.142, 0.277],
+ [0.436, 0, 0.191, 0.192,
+ 0.34299999999999997],
+ [0.245, 0.345, 0, 0.333, 0.484],
+ [0.706, 0.27, 0.46099999999999997, 0,
+ 0.151],
+ [0.5549999999999999, 0.119, 0.31, 0.311,
+ 0],
+ ])
+
+
+class TestBellmanFord(unittest.TestCase):
+ def test_bellman_ford(self):
+ graph1 = {
+ 'a': {'b': 6, 'e': 7},
+ 'b': {'c': 5, 'd': -4, 'e': 8},
+ 'c': {'b': -2},
+ 'd': {'a': 2, 'c': 7},
+ 'e': {'b': -3}
+ }
+ self.assertEqual(True, bellman_ford(graph1, 'a'))
+ graph2 = {
+ 'a': {'d': 3, 'e': 4},
+ 'b': {'a': 7, 'e': 2},
+ 'c': {'a': 12, 'd': 9, 'e': 11},
+ 'd': {'c': 5, 'e': 11},
+ 'e': {'a': 7, 'b': 5, 'd': 1}
+ }
+ self.assertEqual(True, bellman_ford(graph2, 'a'))
+
+
+class TestConnectedComponentInGraph(unittest.TestCase):
+ """
+ Class for testing different cases for connected components in graph
+ """
+ def test_count_connected_components(self):
+ """
+ Test Function that test the different cases of count connected
+ components
+ 2----------0 1--------5 3
+ |
+ |
+ 4
+ output = 3
+ """
+ expected_result = 3
+ # adjacency list representation of graph
+ l = [[2],
+ [5],
+ [0,4],
+ [],
+ [2],
+ [1]]
+
+ size = 5
+ result = count_connected_number_of_component.count_components(l, size)
+ self.assertEqual(result, expected_result)
+
+ def test_connected_components_with_empty_graph(self):
+
+ """
+ input :
+ output : 0
+ """
+ l = [[]]
+ expected_result = 0
+ size = 0
+ result = count_connected_number_of_component.count_components(l, size)
+ self.assertEqual(result, expected_result)
+
+ def test_connected_components_without_edges_graph(self):
+ """
+ input : 0 2 3 4
+ output : 4
+ """
+ l = [[0], [], [2], [3], [4]]
+ size = 4
+ expected_result = 4
+ result = count_connected_number_of_component.count_components(l, size)
+ self.assertEqual(result, expected_result)
+
+
+class PrimsMinimumSpanning(unittest.TestCase):
+ def test_prim_spanning(self):
+ graph1 = {
+ 1: [[3, 2], [8, 3]],
+ 2: [[3, 1], [5, 4]],
+ 3: [[8, 1], [2, 4], [4, 5]],
+ 4: [[5, 2], [2, 3], [6, 5]],
+ 5: [[4, 3], [6, 4]]
+ }
+ self.assertEqual(14, prims_minimum_spanning(graph1))
+ graph2 = {
+ 1: [[7, 2], [6, 4]],
+ 2: [[7, 1], [9, 4], [6, 3]],
+ 3: [[8, 4], [6, 2]],
+ 4: [[6, 1], [9, 2], [8, 3]]
+ }
+ self.assertEqual(19, prims_minimum_spanning(graph2))
+
+class TestDigraphStronglyConnected(unittest.TestCase):
+ def test_digraph_strongly_connected(self):
+ g1 = check_digraph_strongly_connected.Graph(5)
+ g1.add_edge(0, 1)
+ g1.add_edge(1, 2)
+ g1.add_edge(2, 3)
+ g1.add_edge(3, 0)
+ g1.add_edge(2, 4)
+ g1.add_edge(4, 2)
+ self.assertTrue(g1.is_strongly_connected())
+
+ g2 = check_digraph_strongly_connected.Graph(4)
+ g2.add_edge(0, 1)
+ g2.add_edge(1, 2)
+ g2.add_edge(2, 3)
+ self.assertFalse(g2.is_strongly_connected())
+
+class TestCycleDetection(unittest.TestCase):
+ def test_cycle_detection_with_cycle(self):
+ graph = {'A': ['B', 'C'],
+ 'B': ['D'],
+ 'C': ['F'],
+ 'D': ['E', 'F'],
+ 'E': ['B'],
+ 'F': []}
+ self.assertTrue(cycle_detection.contains_cycle(graph))
+
+ def test_cycle_detection_with_no_cycle(self):
+ graph = {'A': ['B', 'C'],
+ 'B': ['D', 'E'],
+ 'C': ['F'],
+ 'D': ['E'],
+ 'E': [],
+ 'F': []}
+ self.assertFalse(cycle_detection.contains_cycle(graph))
+
+class TestFindPath(unittest.TestCase):
+ def test_find_all_paths(self):
+ graph = {'A': ['B', 'C'],
+ 'B': ['C', 'D'],
+ 'C': ['D', 'F'],
+ 'D': ['C'],
+ 'E': ['F'],
+ 'F': ['C']}
+
+ paths = find_path.find_all_path(graph, 'A', 'F')
+ print(paths)
+ self.assertEqual(sorted(paths), sorted([
+ ['A', 'C', 'F'],
+ ['A', 'B', 'C', 'F'],
+ ['A', 'B', 'D', 'C', 'F'],
+ ]))
+
+class TestPathBetweenTwoVertices(unittest.TestCase):
+ def test_node_is_reachable(self):
+ g = path_between_two_vertices_in_digraph.Graph(4)
+ g.add_edge(0, 1)
+ g.add_edge(0, 2)
+ g.add_edge(1, 2)
+ g.add_edge(2, 0)
+ g.add_edge(2, 3)
+ g.add_edge(3, 3)
+
+ self.assertTrue(g.is_reachable(1, 3))
+ self.assertFalse(g.is_reachable(3, 1))
+
+class TestStronglyConnectedComponentsKosaraju(unittest.TestCase):
+ def test_kosaraju_algorithm(self):
+ V = 6
+ adj = [
+ [2],
+ [0],
+ [3],
+ [1, 4],
+ [5],
+ [4]
+ ]
+
+ result = strongly_connected_components_kosaraju.Kosaraju().kosaraju(V, adj)
+
+ # Expected result: 2 strongly connected components
+ self.assertEqual(result, 2)
diff --git a/tests/test_greedy.py b/tests/test_greedy.py
new file mode 100644
index 000000000..095f2a282
--- /dev/null
+++ b/tests/test_greedy.py
@@ -0,0 +1,21 @@
+from algorithms.greedy import (
+ max_contiguous_subsequence_sum,
+)
+
+import unittest
+
+class TestMaxContiguousSubsequenceSum(unittest.TestCase):
+ def test_max_contiguous_subsequence_sum(self):
+ arr1 = [-2, 3, 8, -1, 4]
+ arr2 = [-1, 1, 0]
+ arr3 = [-1, -3, -4]
+ arr4 = [-2, 3, 8, -12, 8, 4]
+
+ self.assertEqual(max_contiguous_subsequence_sum(arr1), 14)
+ self.assertEqual(max_contiguous_subsequence_sum(arr2), 1)
+ self.assertEqual(max_contiguous_subsequence_sum(arr3), -1)
+ self.assertEqual(max_contiguous_subsequence_sum(arr4), 12)
+
+if __name__ == '__main__':
+
+ unittest.main()
\ No newline at end of file
diff --git a/tests/test_heap.py b/tests/test_heap.py
new file mode 100644
index 000000000..afae0d93e
--- /dev/null
+++ b/tests/test_heap.py
@@ -0,0 +1,69 @@
+from algorithms.heap import (
+ BinaryHeap,
+ get_skyline,
+ max_sliding_window,
+ k_closest
+)
+
+import unittest
+
+
+class TestBinaryHeap(unittest.TestCase):
+ """
+ Test suite for the binary_heap data structures
+ """
+
+ def setUp(self):
+ self.min_heap = BinaryHeap()
+ self.min_heap.insert(4)
+ self.min_heap.insert(50)
+ self.min_heap.insert(7)
+ self.min_heap.insert(55)
+ self.min_heap.insert(90)
+ self.min_heap.insert(87)
+
+ def test_insert(self):
+ # Before insert 2: [0, 4, 50, 7, 55, 90, 87]
+ # After insert: [0, 2, 50, 4, 55, 90, 87, 7]
+ self.min_heap.insert(2)
+ self.assertEqual([0, 2, 50, 4, 55, 90, 87, 7],
+ self.min_heap.heap)
+ self.assertEqual(7, self.min_heap.current_size)
+
+ def test_remove_min(self):
+ ret = self.min_heap.remove_min()
+ # Before remove_min : [0, 4, 50, 7, 55, 90, 87]
+ # After remove_min: [7, 50, 87, 55, 90]
+ # Test return value
+ self.assertEqual(4, ret)
+ self.assertEqual([0, 7, 50, 87, 55, 90],
+ self.min_heap.heap)
+ self.assertEqual(5, self.min_heap.current_size)
+
+
+class TestSuite(unittest.TestCase):
+ def test_get_skyline(self):
+ buildings = [[2, 9, 10], [3, 7, 15], [5, 12, 12],
+ [15, 20, 10], [19, 24, 8]]
+ # Expect output
+ output = [[2, 10], [3, 15], [7, 12], [12, 0], [15, 10],
+ [20, 8], [24, 0]]
+ self.assertEqual(output, get_skyline(buildings))
+
+ def test_max_sliding_window(self):
+ nums = [1, 3, -1, -3, 5, 3, 6, 7]
+ self.assertEqual([3, 3, 5, 5, 6, 7], max_sliding_window(nums, 3))
+
+ def test_k_closest_points(self):
+ points = [(1, 0), (2, 3), (5, 2), (1, 1), (2, 8), (10, 2),
+ (-1, 0), (-2, -2)]
+ self.assertEqual([(-1, 0), (1, 0)], k_closest(points, 2))
+ self.assertEqual([(1, 1), (-1, 0), (1, 0)], k_closest(points, 3))
+ self.assertEqual([(-2, -2), (1, 1), (1, 0),
+ (-1, 0)], k_closest(points, 4))
+ self.assertEqual([(10, 2), (2, 8), (5, 2), (-2, -2), (2, 3),
+ (1, 0), (-1, 0), (1, 1)], k_closest(points, 8))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_histogram.py b/tests/test_histogram.py
new file mode 100644
index 000000000..cd35bd216
--- /dev/null
+++ b/tests/test_histogram.py
@@ -0,0 +1,17 @@
+from algorithms.distribution.histogram import get_histogram
+
+import unittest
+
+
+class TestListsInHistogram(unittest.TestCase):
+ def test_histogram(self):
+ list_1 = [3, 3, 2, 1]
+ list_2 = [2, 3, 5, 5, 5, 6, 4, 3, 7]
+
+ self.assertEqual(get_histogram(list_1), {1: 1, 2: 1, 3: 2})
+ self.assertEqual(get_histogram(list_2),
+ {2: 1, 3: 2, 4: 1, 5: 3, 6: 1, 7: 1})
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_iterative_segment_tree.py b/tests/test_iterative_segment_tree.py
new file mode 100644
index 000000000..66d222267
--- /dev/null
+++ b/tests/test_iterative_segment_tree.py
@@ -0,0 +1,99 @@
+from algorithms.tree.segment_tree.iterative_segment_tree import SegmentTree
+from functools import reduce
+
+import unittest
+
+
+def gcd(a, b):
+ if b == 0:
+ return a
+ return gcd(b, a % b)
+
+
+class TestSegmentTree(unittest.TestCase):
+ """
+ Test for the Iterative Segment Tree data structure
+ """
+
+ def test_segment_tree_creation(self):
+ arr = [2, 4, 3, 6, 8, 9, 3]
+ max_segment_tree = SegmentTree(arr, max)
+ min_segment_tree = SegmentTree(arr, min)
+ sum_segment_tree = SegmentTree(arr, lambda a, b: a + b)
+ gcd_segment_tree = SegmentTree(arr, gcd)
+ self.assertEqual(max_segment_tree.tree,
+ [None, 9, 8, 9, 4, 8, 9, 2, 4, 3, 6, 8, 9, 3])
+ self.assertEqual(min_segment_tree.tree,
+ [None, 2, 3, 2, 3, 6, 3, 2, 4, 3, 6, 8, 9, 3])
+ self.assertEqual(sum_segment_tree.tree,
+ [None, 35, 21, 14, 7, 14, 12, 2, 4, 3, 6, 8, 9, 3])
+ self.assertEqual(gcd_segment_tree.tree,
+ [None, 1, 1, 1, 1, 2, 3, 2, 4, 3, 6, 8, 9, 3])
+
+ def test_max_segment_tree(self):
+ arr = [-1, 1, 10, 2, 9, -3, 8, 4, 7, 5, 6, 0]
+ self.__test_all_segments(arr, max)
+
+ def test_min_segment_tree(self):
+ arr = [1, 10, -2, 9, -3, 8, 4, -7, 5, 6, 11, -12]
+ self.__test_all_segments(arr, min)
+
+ def test_sum_segment_tree(self):
+ arr = [1, 10, 2, 9, 3, 8, 4, 7, 5, 6, -11, -12]
+ self.__test_all_segments(arr, lambda a, b: a + b)
+
+ def test_gcd_segment_tree(self):
+ arr = [1, 10, 2, 9, 3, 8, 4, 7, 5, 6, 11, 12, 14]
+ self.__test_all_segments(arr, gcd)
+
+ def test_max_segment_tree_with_updates(self):
+ arr = [-1, 1, 10, 2, 9, -3, 8, 4, 7, 5, 6, 0]
+ updates = {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9,
+ 9: 10, 10: 11, 11: 12}
+ self.__test_all_segments_with_updates(arr, max, updates)
+
+ def test_min_segment_tree_with_updates(self):
+ arr = [1, 10, -2, 9, -3, 8, 4, -7, 5, 6, 11, -12]
+ updates = {0: 7, 1: 2, 2: 6, 3: -14, 4: 5, 5: 4, 6: 7, 7: -10, 8: 9,
+ 9: 10, 10: 12, 11: 1}
+ self.__test_all_segments_with_updates(arr, min, updates)
+
+ def test_sum_segment_tree_with_updates(self):
+ arr = [1, 10, 2, 9, 3, 8, 4, 7, 5, 6, -11, -12]
+ updates = {0: 12, 1: 11, 2: 10, 3: 9, 4: 8, 5: 7, 6: 6, 7: 5, 8: 4,
+ 9: 3, 10: 2, 11: 1}
+ self.__test_all_segments_with_updates(arr, lambda a, b: a + b, updates)
+
+ def test_gcd_segment_tree_with_updates(self):
+ arr = [1, 10, 2, 9, 3, 8, 4, 7, 5, 6, 11, 12, 14]
+ updates = {0: 4, 1: 2, 2: 3, 3: 9, 4: 21, 5: 7, 6: 4, 7: 4, 8: 2,
+ 9: 5, 10: 17, 11: 12, 12: 3}
+ self.__test_all_segments_with_updates(arr, gcd, updates)
+
+ def __test_all_segments(self, arr, fnc):
+ """
+ Test all possible segments in the tree
+ :param arr: array to test
+ :param fnc: function of the segment tpree
+ """
+ segment_tree = SegmentTree(arr, fnc)
+ self.__test_segments_helper(segment_tree, fnc, arr)
+
+ def __test_all_segments_with_updates(self, arr, fnc, upd):
+ """
+ Test all possible segments in the tree with updates
+ :param arr: array to test
+ :param fnc: function of the segment tree
+ :param upd: updates to test
+ """
+ segment_tree = SegmentTree(arr, fnc)
+ for index, value in upd.items():
+ arr[index] = value
+ segment_tree.update(index, value)
+ self.__test_segments_helper(segment_tree, fnc, arr)
+
+ def __test_segments_helper(self, seg_tree, fnc, arr):
+ for i in range(0, len(arr)):
+ for j in range(i, len(arr)):
+ range_value = reduce(fnc, arr[i:j + 1])
+ self.assertEqual(seg_tree.query(i, j), range_value)
diff --git a/tests/test_linkedlist.py b/tests/test_linkedlist.py
new file mode 100644
index 000000000..6b7f1f4fa
--- /dev/null
+++ b/tests/test_linkedlist.py
@@ -0,0 +1,215 @@
+import unittest
+
+from algorithms.linkedlist import (
+ reverse_list, reverse_list_recursive,
+ is_sorted,
+ remove_range,
+ swap_pairs,
+ rotate_right,
+ is_cyclic,
+ merge_two_list, merge_two_list_recur,
+ is_palindrome, is_palindrome_stack, is_palindrome_dict,
+ RandomListNode, copy_random_pointer_v1, copy_random_pointer_v2
+)
+
+
+class Node(object):
+ def __init__(self, x):
+ self.val = x
+ self.next = None
+
+
+# Convert from linked list Node to list for testing
+def convert(head):
+ ret = []
+ if head:
+ current = head
+ while current:
+ ret.append(current.val)
+ current = current.next
+ return ret
+
+
+class TestSuite(unittest.TestCase):
+ def setUp(self):
+ # list test for palindrome
+ self.l = Node('A')
+ self.l.next = Node('B')
+ self.l.next.next = Node('C')
+ self.l.next.next.next = Node('B')
+ self.l.next.next.next.next = Node('A')
+
+ self.l1 = Node('A')
+ self.l1.next = Node('B')
+ self.l1.next.next = Node('C')
+ self.l1.next.next.next = Node('B')
+
+ def test_reverse_list(self):
+ head = Node(1)
+ head.next = Node(2)
+ head.next.next = Node(3)
+ head.next.next.next = Node(4)
+ self.assertEqual([4, 3, 2, 1], convert(reverse_list(head)))
+ head = Node(1)
+ head.next = Node(2)
+ head.next.next = Node(3)
+ head.next.next.next = Node(4)
+ self.assertEqual([4, 3, 2, 1], convert(reverse_list_recursive(head)))
+
+ def test_is_sorted(self):
+ head = Node(-2)
+ head.next = Node(2)
+ head.next.next = Node(2)
+ head.next.next.next = Node(4)
+ head.next.next.next.next = Node(9)
+ # head -> -2 -> 2 -> 2 -> 4 -> 9
+ self.assertTrue(is_sorted(head))
+ head = Node(1)
+ head.next = Node(2)
+ head.next.next = Node(8)
+ head.next.next.next = Node(4)
+ head.next.next.next.next = Node(6)
+ # head -> 1 -> 2 -> 8 -> 4 -> 6
+ self.assertFalse(is_sorted(head))
+
+ def test_remove_range(self):
+ # Test case: middle case.
+ head = Node(0)
+ head.next = Node(1)
+ head.next.next = Node(2)
+ head.next.next.next = Node(3)
+ head.next.next.next.next = Node(4)
+ # Expect output: 0 4
+ self.assertEqual([0, 4], convert(remove_range(head, 1, 3)))
+
+ # Test case: taking out the front node
+ head = Node(0)
+ head.next = Node(1)
+ head.next.next = Node(2)
+ head.next.next.next = Node(3)
+ head.next.next.next.next = Node(4)
+ # Expect output: 2 3 4
+ self.assertEqual([2, 3, 4], convert(remove_range(head, 0, 1)))
+
+ # Test case: removing all the nodes
+ head = Node(0)
+ head.next = Node(1)
+ head.next.next = Node(2)
+ head.next.next.next = Node(3)
+ head.next.next.next.next = Node(4)
+ self.assertEqual([], convert(remove_range(head, 0, 7)))
+
+ def test_swap_in_pairs(self):
+ head = Node(1)
+ head.next = Node(2)
+ head.next.next = Node(3)
+ head.next.next.next = Node(4)
+ # Expect output : 2 --> 1 --> 4 --> 3
+ self.assertEqual([2, 1, 4, 3], convert(swap_pairs(head)))
+
+ def test_rotate_right(self):
+ # Given 1->2->3->4->5->NULL
+ head = Node(1)
+ head.next = Node(2)
+ head.next.next = Node(3)
+ head.next.next.next = Node(4)
+ head.next.next.next.next = Node(5)
+ # K = 2. Expect output: 4->5->1->2->3->NULL.
+ self.assertEqual([4, 5, 1, 2, 3], convert(rotate_right(head, 2)))
+
+ def test_is_cyclic(self):
+ # create linked list => A -> B -> C -> D -> E -> C
+ head = Node('A')
+ head.next = Node('B')
+ curr = head.next
+ cyclic_node = Node('C')
+ curr.next = cyclic_node
+ curr = curr.next
+ curr.next = Node('D')
+ curr = curr.next
+ curr.next = Node('E')
+ curr = curr.next
+ curr.next = cyclic_node
+ self.assertTrue(is_cyclic(head))
+
+ # create linked list 1 -> 2 -> 3 -> 4
+ head = Node(1)
+ curr = head
+ for i in range(2, 6):
+ curr.next = Node(i)
+ curr = curr.next
+ self.assertFalse(is_cyclic(head))
+
+ def test_merge_two_list(self):
+ """
+ Input: head1:1->2->4, head2: 1->3->4
+ Output: 1->1->2->3->4->4
+ """
+ head1 = Node(1)
+ head1.next = Node(2)
+ head1.next.next = Node(4)
+ head2 = Node(1)
+ head2.next = Node(3)
+ head2.next.next = Node(4)
+ self.assertEqual([1, 1, 2, 3, 4, 4],
+ convert(merge_two_list(head1, head2)))
+ # Test recursive
+ head1 = Node(1)
+ head1.next = Node(2)
+ head1.next.next = Node(4)
+ head2 = Node(1)
+ head2.next = Node(3)
+ head2.next.next = Node(4)
+ self.assertEqual([1, 1, 2, 3, 4, 4],
+ convert(merge_two_list_recur(head1, head2)))
+
+ def test_is_palindrome(self):
+ self.assertTrue(is_palindrome(self.l))
+ self.assertFalse(is_palindrome(self.l1))
+
+ def test_is_palindrome_stack(self):
+ self.assertTrue(is_palindrome_stack(self.l))
+ self.assertFalse(is_palindrome_stack(self.l1))
+
+ def test_is_palindrome_dict(self):
+ self.assertTrue(is_palindrome_dict(self.l))
+ self.assertFalse(is_palindrome_dict(self.l1))
+
+ def test_solution_0(self):
+ self._init_random_list_nodes()
+ result = copy_random_pointer_v1(self.random_list_node1)
+ self._assert_is_a_copy(result)
+
+ def test_solution_1(self):
+ self._init_random_list_nodes()
+ result = copy_random_pointer_v2(self.random_list_node1)
+ self._assert_is_a_copy(result)
+
+ def _assert_is_a_copy(self, result):
+ self.assertEqual(5, result.next.next.next.next.label)
+ self.assertEqual(4, result.next.next.next.label)
+ self.assertEqual(3, result.next.next.label)
+ self.assertEqual(2, result.next.label)
+ self.assertEqual(1, result.label)
+ self.assertEqual(3, result.next.next.next.next.random.label)
+ self.assertIsNone(result.next.next.next.random)
+ self.assertEqual(2, result.next.next.random.label)
+ self.assertEqual(5, result.next.random.label)
+ self.assertEqual(4, result.random.label)
+
+ def _init_random_list_nodes(self):
+ self.random_list_node1 = RandomListNode(1)
+ random_list_node2 = RandomListNode(2)
+ random_list_node3 = RandomListNode(3)
+ random_list_node4 = RandomListNode(4)
+ random_list_node5 = RandomListNode(5)
+
+ self.random_list_node1.next, self.random_list_node1.random = random_list_node2, random_list_node4
+ random_list_node2.next, random_list_node2.random = random_list_node3, random_list_node5
+ random_list_node3.next, random_list_node3.random = random_list_node4, random_list_node2
+ random_list_node4.next = random_list_node5
+ random_list_node5.random = random_list_node3
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_map.py b/tests/test_map.py
new file mode 100644
index 000000000..a62656d15
--- /dev/null
+++ b/tests/test_map.py
@@ -0,0 +1,191 @@
+from algorithms.map import (
+ HashTable, ResizableHashTable,
+ SeparateChainingHashTable,
+ word_pattern,
+ is_isomorphic,
+ is_anagram,
+ longest_palindromic_subsequence,
+)
+
+import unittest
+
+
+class TestHashTable(unittest.TestCase):
+ def test_one_entry(self):
+ m = HashTable(10)
+ m.put(1, '1')
+ self.assertEqual('1', m.get(1))
+
+ def test_add_entry_bigger_than_table_size(self):
+ m = HashTable(10)
+ m.put(11, '1')
+ self.assertEqual('1', m.get(11))
+
+ def test_get_none_if_key_missing_and_hash_collision(self):
+ m = HashTable(10)
+ m.put(1, '1')
+ self.assertEqual(None, m.get(11))
+
+ def test_two_entries_with_same_hash(self):
+ m = HashTable(10)
+ m.put(1, '1')
+ m.put(11, '11')
+ self.assertEqual('1', m.get(1))
+ self.assertEqual('11', m.get(11))
+
+ def test_get_on_full_table_does_halts(self):
+ # and does not search forever
+ m = HashTable(10)
+ for i in range(10, 20):
+ m.put(i, i)
+ self.assertEqual(None, m.get(1))
+
+ def test_delete_key(self):
+ m = HashTable(10)
+ for i in range(5):
+ m.put(i, i**2)
+ m.del_(1)
+ self.assertEqual(None, m.get(1))
+ self.assertEqual(4, m.get(2))
+
+ def test_delete_key_and_reassign(self):
+ m = HashTable(10)
+ m.put(1, 1)
+ del m[1]
+ m.put(1, 2)
+ self.assertEqual(2, m.get(1))
+
+ def test_assigning_to_full_table_throws_error(self):
+ m = HashTable(3)
+ m.put(1, 1)
+ m.put(2, 2)
+ m.put(3, 3)
+ with self.assertRaises(ValueError):
+ m.put(4, 4)
+
+ def test_len_trivial(self):
+ m = HashTable(10)
+ self.assertEqual(0, len(m))
+ for i in range(10):
+ m.put(i, i)
+ self.assertEqual(i + 1, len(m))
+
+ def test_len_after_deletions(self):
+ m = HashTable(10)
+ m.put(1, 1)
+ self.assertEqual(1, len(m))
+ m.del_(1)
+ self.assertEqual(0, len(m))
+ m.put(11, 42)
+ self.assertEqual(1, len(m))
+
+ def test_resizable_hash_table(self):
+ m = ResizableHashTable()
+ self.assertEqual(ResizableHashTable.MIN_SIZE, m.size)
+ for i in range(ResizableHashTable.MIN_SIZE):
+ m.put(i, 'foo')
+ self.assertEqual(ResizableHashTable.MIN_SIZE * 2, m.size)
+ self.assertEqual('foo', m.get(1))
+ self.assertEqual('foo', m.get(3))
+ self.assertEqual('foo', m.get(ResizableHashTable.MIN_SIZE - 1))
+
+ def test_fill_up_the_limit(self):
+ m = HashTable(10)
+ for i in range(10):
+ m.put(i, i**2)
+ for i in range(10):
+ self.assertEqual(i**2, m.get(i))
+
+
+class TestSeparateChainingHashTable(unittest.TestCase):
+ def test_one_entry(self):
+ m = SeparateChainingHashTable(10)
+ m.put(1, '1')
+ self.assertEqual('1', m.get(1))
+
+ def test_two_entries_with_same_hash(self):
+ m = SeparateChainingHashTable(10)
+ m.put(1, '1')
+ m.put(11, '11')
+ self.assertEqual('1', m.get(1))
+ self.assertEqual('11', m.get(11))
+
+ def test_len_trivial(self):
+ m = SeparateChainingHashTable(10)
+ self.assertEqual(0, len(m))
+ for i in range(10):
+ m.put(i, i)
+ self.assertEqual(i + 1, len(m))
+
+ def test_len_after_deletions(self):
+ m = SeparateChainingHashTable(10)
+ m.put(1, 1)
+ self.assertEqual(1, len(m))
+ m.del_(1)
+ self.assertEqual(0, len(m))
+ m.put(11, 42)
+ self.assertEqual(1, len(m))
+
+ def test_delete_key(self):
+ m = SeparateChainingHashTable(10)
+ for i in range(5):
+ m.put(i, i**2)
+ m.del_(1)
+ self.assertEqual(None, m.get(1))
+ self.assertEqual(4, m.get(2))
+
+ def test_delete_key_and_reassign(self):
+ m = SeparateChainingHashTable(10)
+ m.put(1, 1)
+ del m[1]
+ m.put(1, 2)
+ self.assertEqual(2, m.get(1))
+
+ def test_add_entry_bigger_than_table_size(self):
+ m = SeparateChainingHashTable(10)
+ m.put(11, '1')
+ self.assertEqual('1', m.get(11))
+
+ def test_get_none_if_key_missing_and_hash_collision(self):
+ m = SeparateChainingHashTable(10)
+ m.put(1, '1')
+ self.assertEqual(None, m.get(11))
+
+
+class TestWordPattern(unittest.TestCase):
+ def test_word_pattern(self):
+ self.assertTrue(word_pattern("abba", "dog cat cat dog"))
+ self.assertFalse(word_pattern("abba", "dog cat cat fish"))
+ self.assertFalse(word_pattern("abba", "dog dog dog dog"))
+ self.assertFalse(word_pattern("aaaa", "dog cat cat dog"))
+
+
+class TestIsSomorphic(unittest.TestCase):
+ def test_is_isomorphic(self):
+ self.assertTrue(is_isomorphic("egg", "add"))
+ self.assertFalse(is_isomorphic("foo", "bar"))
+ self.assertTrue(is_isomorphic("paper", "title"))
+
+
+class TestLongestPalindromicSubsequence(unittest.TestCase):
+ def test_longest_palindromic_subsequence_is_correct(self):
+ self.assertEqual(3, longest_palindromic_subsequence('BBABCBCAB'))
+ self.assertEqual(4, longest_palindromic_subsequence('abbaeae'))
+ self.assertEqual(7, longest_palindromic_subsequence('babbbababaa'))
+ self.assertEqual(4, longest_palindromic_subsequence('daccandeeja'))
+
+ def test_longest_palindromic_subsequence_is_incorrect(self):
+ self.assertNotEqual(4, longest_palindromic_subsequence('BBABCBCAB'))
+ self.assertNotEqual(5, longest_palindromic_subsequence('abbaeae'))
+ self.assertNotEqual(2, longest_palindromic_subsequence('babbbababaa'))
+ self.assertNotEqual(1, longest_palindromic_subsequence('daccandeeja'))
+
+
+class TestIsAnagram(unittest.TestCase):
+ def test_is_anagram(self):
+ self.assertTrue(is_anagram("anagram", "nagaram"))
+ self.assertFalse(is_anagram("rat", "car"))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_maths.py b/tests/test_maths.py
new file mode 100644
index 000000000..c4a54af03
--- /dev/null
+++ b/tests/test_maths.py
@@ -0,0 +1,597 @@
+from algorithms.maths import (
+ power, power_recur,
+ int_to_base, base_to_int,
+ decimal_to_binary_ip,
+ euler_totient,
+ extended_gcd,
+ factorial, factorial_recur,
+ gcd, lcm, trailing_zero, gcd_bit,
+ gen_strobogrammatic, strobogrammatic_in_range,
+ is_strobogrammatic, is_strobogrammatic2,
+ modular_inverse,
+ modular_exponential,
+ find_next_square, find_next_square2,
+ prime_check,
+ get_primes,
+ pythagoras,
+ is_prime,
+ encrypt, decrypt,
+ combination, combination_memo,
+ hailstone,
+ cosine_similarity,
+ magic_number,
+ find_order,
+ find_primitive_root,
+ num_digits,
+ diffie_hellman_key_exchange, krishnamurthy_number,
+ num_perfect_squares,
+ chinese_remainder_theorem,
+ fft
+)
+
+import unittest
+import pytest
+
+
+class TestPower(unittest.TestCase):
+ """
+ Test for the file power.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_power(self):
+ self.assertEqual(8, power(2, 3))
+ self.assertEqual(1, power(5, 0))
+ self.assertEqual(0, power(10, 3, 5))
+ self.assertEqual(280380, power(2265, 1664, 465465))
+
+ def test_power_recur(self):
+ self.assertEqual(8, power_recur(2, 3))
+ self.assertEqual(1, power_recur(5, 0))
+ self.assertEqual(0, power_recur(10, 3, 5))
+ self.assertEqual(280380, power_recur(2265, 1664, 465465))
+
+
+class TestBaseConversion(unittest.TestCase):
+ """
+ Test for the file base_conversion.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_int_to_base(self):
+ self.assertEqual("101", int_to_base(5, 2))
+ self.assertEqual("0", int_to_base(0, 2))
+ self.assertEqual("FF", int_to_base(255, 16))
+
+ def test_base_to_int(self):
+ self.assertEqual(5, base_to_int("101", 2))
+ self.assertEqual(0, base_to_int("0", 2))
+ self.assertEqual(255, base_to_int("FF", 16))
+
+
+class TestDecimalToBinaryIP(unittest.TestCase):
+ """
+ Test for the file decimal_to_binary_ip.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_decimal_to_binary_ip(self):
+ self.assertEqual("00000000.00000000.00000000.00000000",
+ decimal_to_binary_ip("0.0.0.0"))
+ self.assertEqual("11111111.11111111.11111111.11111111",
+ decimal_to_binary_ip("255.255.255.255"))
+ self.assertEqual("11000000.10101000.00000000.00000001",
+ decimal_to_binary_ip("192.168.0.1"))
+
+
+class TestEulerTotient(unittest.TestCase):
+ """[summary]
+ Test for the file euler_totient.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_euler_totient(self):
+ self.assertEqual(4, euler_totient(8))
+ self.assertEqual(12, euler_totient(21))
+ self.assertEqual(311040, euler_totient(674614))
+ self.assertEqual(2354352, euler_totient(3435145))
+
+
+class TestExtendedGcd(unittest.TestCase):
+ """[summary]
+ Test for the file extended_gcd.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_extended_gcd(self):
+ self.assertEqual((0, 1, 2), extended_gcd(8, 2))
+ self.assertEqual((0, 1, 17), extended_gcd(13, 17))
+
+
+class TestGcd(unittest.TestCase):
+ """[summary]
+ Test for the file gcd.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_gcd(self):
+ self.assertEqual(4, gcd(8, 12))
+ self.assertEqual(1, gcd(13, 17))
+
+ def test_gcd_non_integer_input(self):
+ with pytest.raises(ValueError,
+ match=r"Input arguments are not integers"):
+ gcd(1.0, 5)
+ gcd(5, 6.7)
+ gcd(33.8649, 6.12312312)
+
+ def test_gcd_zero_input(self):
+ with pytest.raises(ValueError,
+ match=r"One or more input arguments equals zero"):
+ gcd(0, 12)
+ gcd(12, 0)
+ gcd(0, 0)
+
+ def test_gcd_negative_input(self):
+ self.assertEqual(1, gcd(-13, -17))
+ self.assertEqual(4, gcd(-8, 12))
+ self.assertEqual(8, gcd(24, -16))
+
+ def test_lcm(self):
+ self.assertEqual(24, lcm(8, 12))
+ self.assertEqual(5767, lcm(73, 79))
+
+ def test_lcm_negative_numbers(self):
+ self.assertEqual(24, lcm(-8, -12))
+ self.assertEqual(5767, lcm(73, -79))
+ self.assertEqual(1, lcm(-1, 1))
+
+ def test_lcm_zero_input(self):
+ with pytest.raises(ValueError,
+ match=r"One or more input arguments equals zero"):
+ lcm(0, 12)
+ lcm(12, 0)
+ lcm(0, 0)
+
+ def test_trailing_zero(self):
+ self.assertEqual(1, trailing_zero(34))
+ self.assertEqual(3, trailing_zero(40))
+
+ def test_gcd_bit(self):
+ self.assertEqual(4, gcd_bit(8, 12))
+ self.assertEqual(1, gcd(13, 17))
+
+
+class TestGenerateStroboGrammatic(unittest.TestCase):
+ """[summary]
+ Test for the file generate_strobogrammatic.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_gen_strobomatic(self):
+ self.assertEqual(['88', '11', '96', '69'], gen_strobogrammatic(2))
+
+ def test_strobogrammatic_in_range(self):
+ self.assertEqual(4, strobogrammatic_in_range("10", "100"))
+
+
+class TestIsStrobogrammatic(unittest.TestCase):
+ """[summary]
+ Test for the file is_strobogrammatic.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_is_strobogrammatic(self):
+ self.assertTrue(is_strobogrammatic("69"))
+ self.assertFalse(is_strobogrammatic("14"))
+
+ def test_is_strobogrammatic2(self):
+ self.assertTrue(is_strobogrammatic2("69"))
+ self.assertFalse(is_strobogrammatic2("14"))
+
+
+class TestModularInverse(unittest.TestCase):
+ """[summary]
+ Test for the file modular_Exponential.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_modular_inverse(self):
+ # checks if x * x_inv == 1 (mod m)
+ self.assertEqual(1, 2 * modular_inverse.modular_inverse(2, 19) % 19)
+ self.assertEqual(1, 53 * modular_inverse.modular_inverse(53, 91) % 91)
+ self.assertEqual(1, 2 * modular_inverse.modular_inverse(2, 1000000007)
+ % 1000000007)
+ self.assertRaises(ValueError, modular_inverse.modular_inverse, 2, 20)
+
+
+class TestModularExponential(unittest.TestCase):
+ """[summary]
+ Test for the file modular_Exponential.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_modular_exponential(self):
+ self.assertEqual(1, modular_exponential(5, 117, 19))
+ self.assertEqual(pow(1243, 65321, 10 ** 9 + 7),
+ modular_exponential(1243, 65321, 10 ** 9 + 7))
+ self.assertEqual(1, modular_exponential(12, 0, 78))
+ self.assertRaises(ValueError, modular_exponential, 12, -2, 455)
+
+
+class TestNextPerfectSquare(unittest.TestCase):
+ """[summary]
+ Test for the file next_perfect_square.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_find_next_square(self):
+ self.assertEqual(36, find_next_square(25))
+ self.assertEqual(1, find_next_square(0))
+
+ def test_find_next_square2(self):
+ self.assertEqual(36, find_next_square2(25))
+ self.assertEqual(1, find_next_square2(0))
+
+
+class TestPrimesSieveOfEratosthenes(unittest.TestCase):
+ """[summary]
+ Test for the file primes_sieve_of_eratosthenes.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_primes(self):
+ self.assertListEqual([2, 3, 5, 7], get_primes(7))
+ self.assertRaises(ValueError, get_primes, -42)
+
+
+class TestPrimeTest(unittest.TestCase):
+ """[summary]
+ Test for the file prime_test.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_prime_test(self):
+ """
+ checks all prime numbers between 2 up to 100.
+ Between 2 up to 100 exists 25 prime numbers!
+ """
+ counter = 0
+ for i in range(2, 101):
+ if prime_check(i):
+ counter += 1
+ self.assertEqual(25, counter)
+
+
+class TestPythagoras(unittest.TestCase):
+ """[summary]
+ Test for the file pythagoras.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_pythagoras(self):
+ self.assertEqual("Hypotenuse = 3.605551275463989",
+ pythagoras(3, 2, "?"))
+
+
+class TestRabinMiller(unittest.TestCase):
+ """[summary]
+ Test for the file rabin_miller.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_is_prime(self):
+ self.assertTrue(is_prime(7, 2))
+ self.assertTrue(is_prime(13, 11))
+ self.assertFalse(is_prime(6, 2))
+
+
+class TestRSA(unittest.TestCase):
+ """[summary]
+ Test for the file rsa.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_encrypt_decrypt(self):
+ self.assertEqual(7, decrypt(encrypt(7, 23, 143), 47, 143))
+
+ # def test_key_generator(self): # this test takes a while!
+ # for i in range(100):
+ # print("step {0}".format(i))
+ # n, e, d = generate_key(26)
+ # data = 2
+ # en = encrypt(data, e, n)
+ # dec = decrypt(en, d, n)
+ # self.assertEqual(data,dec)
+
+
+class TestCombination(unittest.TestCase):
+ """[summary]
+ Test for the file combination.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_combination(self):
+ self.assertEqual(10, combination(5, 2))
+ self.assertEqual(252, combination(10, 5))
+
+ def test_combination_memo(self):
+ self.assertEqual(10272278170, combination_memo(50, 10))
+ self.assertEqual(847660528, combination_memo(40, 10))
+
+
+class TestFactorial(unittest.TestCase):
+ """[summary]
+ Test for the file factorial.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_factorial(self):
+ self.assertEqual(1, factorial(0))
+ self.assertEqual(120, factorial(5))
+ self.assertEqual(3628800, factorial(10))
+ self.assertEqual(637816310, factorial(34521, 10 ** 9 + 7))
+ self.assertRaises(ValueError, factorial, -42)
+ self.assertRaises(ValueError, factorial, 42, -1)
+
+ def test_factorial_recur(self):
+ self.assertEqual(1, factorial_recur(0))
+ self.assertEqual(120, factorial_recur(5))
+ self.assertEqual(3628800, factorial_recur(10))
+ self.assertEqual(637816310, factorial_recur(34521, 10 ** 9 + 7))
+ self.assertRaises(ValueError, factorial_recur, -42)
+ self.assertRaises(ValueError, factorial_recur, 42, -1)
+
+
+class TestHailstone(unittest.TestCase):
+ """[summary]
+ Test for the file hailstone.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_hailstone(self):
+ self.assertEqual([8, 4, 2, 1], hailstone.hailstone(8))
+ self.assertEqual([10, 5, 16, 8, 4, 2, 1], hailstone.hailstone(10))
+
+
+class TestCosineSimilarity(unittest.TestCase):
+ """[summary]
+ Test for the file cosine_similarity.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_cosine_similarity(self):
+ vec_a = [1, 1, 1]
+ vec_b = [-1, -1, -1]
+ vec_c = [1, 2, -1]
+ self.assertAlmostEqual(cosine_similarity(vec_a, vec_a), 1)
+ self.assertAlmostEqual(cosine_similarity(vec_a, vec_b), -1)
+ self.assertAlmostEqual(cosine_similarity(vec_a, vec_c), 0.4714045208)
+
+
+class TestFindPrimitiveRoot(unittest.TestCase):
+ """[summary]
+ Test for the file find_primitive_root_simple.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_find_primitive_root_simple(self):
+ self.assertListEqual([0], find_primitive_root(1))
+ self.assertListEqual([2, 3], find_primitive_root(5))
+ self.assertListEqual([], find_primitive_root(24))
+ self.assertListEqual([2, 5, 13, 15, 17, 18, 19, 20, 22, 24, 32, 35],
+ find_primitive_root(37))
+
+
+class TestFindOrder(unittest.TestCase):
+ """[summary]
+ Test for the file find_order_simple.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_find_order_simple(self):
+ self.assertEqual(1, find_order(1, 1))
+ self.assertEqual(6, find_order(3, 7))
+ self.assertEqual(-1, find_order(128, 256))
+ self.assertEqual(352, find_order(3, 353))
+
+
+class TestKrishnamurthyNumber(unittest.TestCase):
+ """[summary]
+ Test for the file krishnamurthy_number.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_krishnamurthy_number(self):
+ self.assertFalse(krishnamurthy_number(0))
+ self.assertTrue(krishnamurthy_number(2))
+ self.assertTrue(krishnamurthy_number(1))
+ self.assertTrue(krishnamurthy_number(145))
+ self.assertTrue(krishnamurthy_number(40585))
+
+
+class TestMagicNumber(unittest.TestCase):
+ """[summary]
+ Test for the file find_order_simple.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_magic_number(self):
+ self.assertTrue(magic_number(50113))
+ self.assertTrue(magic_number(1234))
+ self.assertTrue(magic_number(100))
+ self.assertTrue(magic_number(199))
+ self.assertFalse(magic_number(2000))
+ self.assertFalse(magic_number(500000))
+
+
+class TestDiffieHellmanKeyExchange(unittest.TestCase):
+ """[summary]
+ Test for the file diffie_hellman_key_exchange.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_find_order_simple(self):
+ self.assertFalse(diffie_hellman_key_exchange(3, 6))
+ self.assertTrue(diffie_hellman_key_exchange(3, 353))
+ self.assertFalse(diffie_hellman_key_exchange(5, 211))
+ self.assertTrue(diffie_hellman_key_exchange(11, 971))
+
+
+class TestNumberOfDigits(unittest.TestCase):
+ """[summary]
+ Test for the file num_digits.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+ def test_num_digits(self):
+ self.assertEqual(2, num_digits(12))
+ self.assertEqual(5, num_digits(99999))
+ self.assertEqual(1, num_digits(8))
+ self.assertEqual(1, num_digits(0))
+ self.assertEqual(1, num_digits(-5))
+ self.assertEqual(3, num_digits(-254))
+
+
+
+class TestNumberOfPerfectSquares(unittest.TestCase):
+ """[summary]
+ Test for the file num_perfect_squares.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+ def test_num_perfect_squares(self):
+ self.assertEqual(4,num_perfect_squares(31))
+ self.assertEqual(3,num_perfect_squares(12))
+ self.assertEqual(2,num_perfect_squares(13))
+ self.assertEqual(2,num_perfect_squares(10))
+ self.assertEqual(4,num_perfect_squares(1500))
+ self.assertEqual(2,num_perfect_squares(1548524521))
+ self.assertEqual(3,num_perfect_squares(9999999993))
+ self.assertEqual(1,num_perfect_squares(9))
+
+
+class TestChineseRemainderSolver(unittest.TestCase):
+ def test_k_three(self):
+ # Example which should give the answer 143
+ # which is the smallest possible x that
+ # solves the system of equations
+ num = [3, 7, 10]
+ rem = [2, 3, 3]
+ self.assertEqual(chinese_remainder_theorem.
+ solve_chinese_remainder(num, rem), 143)
+
+ def test_k_five(self):
+ # Example which should give the answer 3383
+ # which is the smallest possible x that
+ # solves the system of equations
+ num = [3, 5, 7, 11, 26]
+ rem = [2, 3, 2, 6, 3]
+ self.assertEqual(chinese_remainder_theorem.
+ solve_chinese_remainder(num, rem), 3383)
+
+ def test_exception_non_coprime(self):
+ # There should be an exception when all
+ # numbers in num are not pairwise coprime
+ num = [3, 7, 10, 14]
+ rem = [2, 3, 3, 1]
+ with self.assertRaises(Exception):
+ chinese_remainder_theorem.solve_chinese_remainder(num, rem)
+
+ def test_empty_lists(self):
+ num = []
+ rem = []
+ with self.assertRaises(Exception):
+ chinese_remainder_theorem.solve_chinese_remainder(num, rem)
+
+
+class TestFFT(unittest.TestCase):
+ """[summary]
+ Test for the file fft.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+ def test_real_numbers(self):
+ x = [1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0]
+ y = [4.000, 2.613, 0.000, 1.082, 0.000, 1.082, 0.000, 2.613]
+ # abs(complex) returns the magnitude
+ result = [float("%.3f" % abs(f)) for f in fft.fft(x)]
+ self.assertEqual(result, y)
+
+ def test_all_zero(self):
+ x = [0.0, 0.0, 0.0, 0.0]
+ y = [0.0, 0.0, 0.0, 0.0]
+ result = [float("%.1f" % abs(f)) for f in fft.fft(x)]
+ self.assertEqual(result, y)
+
+ def test_all_ones(self):
+ x = [1.0, 1.0, 1.0, 1.0]
+ y = [4.0, 0.0, 0.0, 0.0]
+ result = [float("%.1f" % abs(f)) for f in fft.fft(x)]
+ self.assertEqual(result, y)
+
+ def test_complex_numbers(self):
+ x = [2.0+2j, 1.0+3j, 3.0+1j, 2.0+2j]
+ real = [8.0, 0.0, 2.0, -2.0]
+ imag = [8.0, 2.0, -2.0, 0.0]
+ realResult = [float("%.1f" % f.real) for f in fft.fft(x)]
+ imagResult = [float("%.1f" % f.imag) for f in fft.fft(x)]
+ self.assertEqual(real, realResult)
+ self.assertEqual(imag, imagResult)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_matrix.py b/tests/test_matrix.py
new file mode 100644
index 000000000..262fdbe62
--- /dev/null
+++ b/tests/test_matrix.py
@@ -0,0 +1,391 @@
+from algorithms.matrix import (
+ bomb_enemy,
+ copy_transform,
+ crout_matrix_decomposition,
+ cholesky_matrix_decomposition,
+ matrix_exponentiation,
+ matrix_inversion,
+ multiply,
+ rotate_image,
+ sparse_dot_vector,
+ spiral_traversal,
+ sudoku_validator,
+ sum_sub_squares,
+ sort_matrix_diagonally
+)
+import unittest
+
+
+class TestBombEnemy(unittest.TestCase):
+ def test_3x4(self):
+ grid1 = [
+ ["0", "E", "0", "0"],
+ ["E", "0", "W", "E"],
+ ["0", "E", "0", "0"]
+ ]
+ self.assertEqual(3, bomb_enemy.max_killed_enemies(grid1))
+
+ grid1 = [
+ ["0", "E", "0", "E"],
+ ["E", "E", "E", "0"],
+ ["E", "0", "W", "E"],
+ ["0", "E", "0", "0"]
+ ]
+ grid2 = [
+ ["0", "0", "0", "E"],
+ ["E", "0", "0", "0"],
+ ["E", "0", "W", "E"],
+ ["0", "E", "0", "0"]
+ ]
+ self.assertEqual(5, bomb_enemy.max_killed_enemies(grid1))
+ self.assertEqual(3, bomb_enemy.max_killed_enemies(grid2))
+
+
+class TestCopyTransform(unittest.TestCase):
+ """[summary]
+ Test for the file copy_transform.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_copy_transform(self):
+ self.assertEqual(copy_transform.rotate_clockwise(
+ [[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
+ [[7, 4, 1], [8, 5, 2], [9, 6, 3]])
+
+ self.assertEqual(copy_transform.rotate_counterclockwise(
+ [[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
+ [[3, 6, 9], [2, 5, 8], [1, 4, 7]])
+
+ self.assertEqual(copy_transform.top_left_invert(
+ [[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
+ [[1, 4, 7], [2, 5, 8], [3, 6, 9]])
+
+ self.assertEqual(copy_transform.bottom_left_invert(
+ [[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
+ [[9, 6, 3], [8, 5, 2], [7, 4, 1]])
+
+
+class TestCroutMatrixDecomposition(unittest.TestCase):
+ """[summary]
+ Test for the file crout_matrix_decomposition.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_crout_matrix_decomposition(self):
+ self.assertEqual(([[9.0, 0.0], [7.0, 0.0]],
+ [[1.0, 1.0], [0.0, 1.0]]),
+ crout_matrix_decomposition.crout_matrix_decomposition(
+ [[9, 9], [7, 7]]))
+
+ self.assertEqual(([[1.0, 0.0, 0.0],
+ [3.0, -2.0, 0.0],
+ [6.0, -5.0, 0.0]],
+ [[1.0, 2.0, 3.0],
+ [0.0, 1.0, 2.0],
+ [0.0, 0.0, 1.0]]),
+ crout_matrix_decomposition.crout_matrix_decomposition(
+ [[1, 2, 3], [3, 4, 5], [6, 7, 8]]))
+
+ self.assertEqual(([[2.0, 0, 0, 0],
+ [4.0, -1.0, 0, 0],
+ [6.0, -2.0, 2.0, 0],
+ [8.0, -3.0, 3.0, 0.0]],
+ [[1.0, 0.5, 1.5, 0.5],
+ [0, 1.0, 2.0, 1.0],
+ [0, 0, 1.0, 0.0],
+ [0, 0, 0, 1.0]]),
+ crout_matrix_decomposition.crout_matrix_decomposition(
+ [[2, 1, 3, 1], [4, 1, 4, 1], [6, 1, 7, 1],
+ [8, 1, 9, 1]]))
+
+
+class TestCholeskyMatrixDecomposition(unittest.TestCase):
+ """[summary]
+ Test for the file cholesky_matrix_decomposition.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_cholesky_matrix_decomposition(self):
+ self.assertEqual([[2.0, 0.0, 0.0],
+ [6.0, 1.0, 0.0],
+ [-8.0, 5.0, 3.0]],
+ cholesky_matrix_decomposition.cholesky_decomposition(
+ [[4, 12, -16], [12, 37, -43], [-16, -43, 98]]))
+
+ self.assertEqual(None,
+ cholesky_matrix_decomposition.cholesky_decomposition(
+ [[4, 12, -8], [12, 4, -43], [-16, -1, 32]]))
+
+ self.assertEqual(None,
+ cholesky_matrix_decomposition.cholesky_decomposition(
+ [[4, 12, -16], [12, 37, -43], [-16, -43, 98],
+ [1, 2, 3]]))
+
+ # example taken from https://ece.uwaterloo.ca/~dwharder/NumericalAnalysis/04LinearAlgebra/cholesky/
+ self.assertEqual([[2.23606797749979, 0.0, 0.0, 0.0],
+ [0.5366563145999494, 2.389979079406345, 0.0, 0.0],
+ [0.13416407864998736, -0.19749126846635062,
+ 2.818332343581848, 0.0],
+ [-0.2683281572999747, 0.43682390737048743,
+ 0.64657701271919, 3.052723872310221]],
+ cholesky_matrix_decomposition.cholesky_decomposition(
+ [[5, 1.2, 0.3, -0.6], [1.2, 6, -0.4, 0.9],
+ [0.3, -0.4, 8, 1.7], [-0.6, 0.9, 1.7, 10]]))
+
+
+class TestInversion(unittest.TestCase):
+ """[summary]
+ Test for the file matrix_inversion.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_inversion(self):
+ from fractions import Fraction
+
+ m1 = [[1, 1], [1, 2]]
+ self.assertEqual(matrix_inversion.invert_matrix(m1),
+ [[2, -1], [-1, 1]])
+
+ m2 = [[1, 2], [3, 4, 5]]
+ self.assertEqual(matrix_inversion.invert_matrix(m2), [[-1]])
+
+ m3 = [[1, 1, 1, 1], [2, 2, 2, 2]]
+ self.assertEqual(matrix_inversion.invert_matrix(m3), [[-2]])
+
+ m4 = [[1]]
+ self.assertEqual(matrix_inversion.invert_matrix(m4), [[-3]])
+
+ m5 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
+ self.assertEqual(matrix_inversion.invert_matrix(m5), [[-4]])
+
+ m6 = [[3, 5, 1], [2, 5, 0], [1, 9, 8]]
+ self.assertEqual(matrix_inversion.invert_matrix(m6),
+ [[Fraction(40, 53),
+ Fraction(-31, 53),
+ Fraction(-5, 53)],
+ [Fraction(-16, 53),
+ Fraction(23, 53),
+ Fraction(2, 53)],
+ [Fraction(13, 53),
+ Fraction(-22, 53),
+ Fraction(5, 53)]])
+
+
+class TestMatrixExponentiation(unittest.TestCase):
+ """[summary]
+ Test for the file matrix_exponentiation.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_matrix_exponentiation(self):
+ mat = [[1, 0, 2], [2, 1, 0], [0, 2, 1]]
+
+ self.assertEqual(matrix_exponentiation.matrix_exponentiation(mat, 0),
+ [[1, 0, 0], [0, 1, 0], [0, 0, 1]])
+
+ self.assertEqual(matrix_exponentiation.matrix_exponentiation(mat, 1),
+ [[1, 0, 2], [2, 1, 0], [0, 2, 1]])
+
+ self.assertEqual(matrix_exponentiation.matrix_exponentiation(mat, 2),
+ [[1, 4, 4], [4, 1, 4], [4, 4, 1]])
+
+ self.assertEqual(matrix_exponentiation.matrix_exponentiation(mat, 5),
+ [[81, 72, 90], [90, 81, 72], [72, 90, 81]])
+
+
+class TestMultiply(unittest.TestCase):
+ """[summary]
+ Test for the file multiply.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_multiply(self):
+ self.assertEqual(multiply.multiply(
+ [[1, 2, 3], [2, 1, 1]], [[1], [2], [3]]), [[14], [7]])
+
+
+class TestRotateImage(unittest.TestCase):
+ """[summary]
+ Test for the file rotate_image.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_rotate_image(self):
+ self.assertEqual(rotate_image.rotate(
+ [[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
+ [[7, 4, 1], [8, 5, 2], [9, 6, 3]])
+
+
+class TestSparseDotVector(unittest.TestCase):
+ """[summary]
+ Test for the file sparse_dot_vector.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_sparse_dot_vector(self):
+ self.assertEqual(sparse_dot_vector.
+ dot_product(sparse_dot_vector.
+ vector_to_index_value_list([1., 2., 3.]),
+ sparse_dot_vector.
+ vector_to_index_value_list([0., 2., 2.])),
+ 10)
+
+
+class TestSpiralTraversal(unittest.TestCase):
+ """[summary]
+ Test for the file spiral_traversal.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_spiral_traversal(self):
+ self.assertEqual(spiral_traversal.spiral_traversal(
+ [[1, 2, 3], [4, 5, 6], [7, 8, 9]]), [1, 2, 3, 6, 9, 8, 7, 4, 5])
+
+
+class TestSudokuValidator(unittest.TestCase):
+ """[summary]
+ Test for the file sudoku_validator.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_sudoku_validator(self):
+ self.assertTrue(
+ sudoku_validator.valid_solution(
+ [
+ [5, 3, 4, 6, 7, 8, 9, 1, 2],
+ [6, 7, 2, 1, 9, 5, 3, 4, 8],
+ [1, 9, 8, 3, 4, 2, 5, 6, 7],
+ [8, 5, 9, 7, 6, 1, 4, 2, 3],
+ [4, 2, 6, 8, 5, 3, 7, 9, 1],
+ [7, 1, 3, 9, 2, 4, 8, 5, 6],
+ [9, 6, 1, 5, 3, 7, 2, 8, 4],
+ [2, 8, 7, 4, 1, 9, 6, 3, 5],
+ [3, 4, 5, 2, 8, 6, 1, 7, 9]
+ ]))
+
+ self.assertTrue(
+ sudoku_validator.valid_solution_hashtable(
+ [
+ [5, 3, 4, 6, 7, 8, 9, 1, 2],
+ [6, 7, 2, 1, 9, 5, 3, 4, 8],
+ [1, 9, 8, 3, 4, 2, 5, 6, 7],
+ [8, 5, 9, 7, 6, 1, 4, 2, 3],
+ [4, 2, 6, 8, 5, 3, 7, 9, 1],
+ [7, 1, 3, 9, 2, 4, 8, 5, 6],
+ [9, 6, 1, 5, 3, 7, 2, 8, 4],
+ [2, 8, 7, 4, 1, 9, 6, 3, 5],
+ [3, 4, 5, 2, 8, 6, 1, 7, 9]
+ ]))
+
+ self.assertTrue(
+ sudoku_validator.valid_solution_set(
+ [
+ [5, 3, 4, 6, 7, 8, 9, 1, 2],
+ [6, 7, 2, 1, 9, 5, 3, 4, 8],
+ [1, 9, 8, 3, 4, 2, 5, 6, 7],
+ [8, 5, 9, 7, 6, 1, 4, 2, 3],
+ [4, 2, 6, 8, 5, 3, 7, 9, 1],
+ [7, 1, 3, 9, 2, 4, 8, 5, 6],
+ [9, 6, 1, 5, 3, 7, 2, 8, 4],
+ [2, 8, 7, 4, 1, 9, 6, 3, 5],
+ [3, 4, 5, 2, 8, 6, 1, 7, 9]
+ ]))
+
+ self.assertFalse(
+ sudoku_validator.valid_solution(
+ [
+ [5, 3, 4, 6, 7, 8, 9, 1, 2],
+ [6, 7, 2, 1, 9, 0, 3, 4, 9],
+ [1, 0, 0, 3, 4, 2, 5, 6, 0],
+ [8, 5, 9, 7, 6, 1, 0, 2, 0],
+ [4, 2, 6, 8, 5, 3, 7, 9, 1],
+ [7, 1, 3, 9, 2, 4, 8, 5, 6],
+ [9, 0, 1, 5, 3, 7, 2, 1, 4],
+ [2, 8, 7, 4, 1, 9, 6, 3, 5],
+ [3, 0, 0, 4, 8, 1, 1, 7, 9]
+ ]))
+
+ self.assertFalse(
+ sudoku_validator.valid_solution_hashtable(
+ [
+ [5, 3, 4, 6, 7, 8, 9, 1, 2],
+ [6, 7, 2, 1, 9, 0, 3, 4, 9],
+ [1, 0, 0, 3, 4, 2, 5, 6, 0],
+ [8, 5, 9, 7, 6, 1, 0, 2, 0],
+ [4, 2, 6, 8, 5, 3, 7, 9, 1],
+ [7, 1, 3, 9, 2, 4, 8, 5, 6],
+ [9, 0, 1, 5, 3, 7, 2, 1, 4],
+ [2, 8, 7, 4, 1, 9, 6, 3, 5],
+ [3, 0, 0, 4, 8, 1, 1, 7, 9]
+ ]))
+
+ self.assertFalse(
+ sudoku_validator.valid_solution_set(
+ [
+ [5, 3, 4, 6, 7, 8, 9, 1, 2],
+ [6, 7, 2, 1, 9, 0, 3, 4, 9],
+ [1, 0, 0, 3, 4, 2, 5, 6, 0],
+ [8, 5, 9, 7, 6, 1, 0, 2, 0],
+ [4, 2, 6, 8, 5, 3, 7, 9, 1],
+ [7, 1, 3, 9, 2, 4, 8, 5, 6],
+ [9, 0, 1, 5, 3, 7, 2, 1, 4],
+ [2, 8, 7, 4, 1, 9, 6, 3, 5],
+ [3, 0, 0, 4, 8, 1, 1, 7, 9]
+ ]))
+
+
+class TestSumSubSquares(unittest.TestCase):
+ """[summary]
+ Test for the file sum_sub_squares.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_sum_sub_squares(self):
+ mat = [[1, 1, 1, 1, 1],
+ [2, 2, 2, 2, 2],
+ [3, 3, 3, 3, 3],
+ [4, 4, 4, 4, 4],
+ [5, 5, 5, 5, 5]]
+ self.assertEqual(sum_sub_squares.sum_sub_squares(mat, 3),
+ [[18, 18, 18], [27, 27, 27], [36, 36, 36]])
+
+
+class TestSortMatrixDiagonally(unittest.TestCase):
+ def test_sort_diagonally(self):
+ mat = [
+ [3, 3, 1, 1],
+ [2, 2, 1, 2],
+ [1, 1, 1, 2]
+ ]
+
+ self.assertEqual(sort_matrix_diagonally.sort_diagonally(mat), [
+ [1, 1, 1, 1],
+ [1, 2, 2, 2],
+ [1, 2, 3, 3]
+ ])
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_ml.py b/tests/test_ml.py
new file mode 100644
index 000000000..1622ae1a8
--- /dev/null
+++ b/tests/test_ml.py
@@ -0,0 +1,40 @@
+from algorithms.ml.nearest_neighbor import (
+ distance,
+ nearest_neighbor
+)
+
+import unittest
+
+
+class TestML(unittest.TestCase):
+ def setUp(self):
+ # train set for the AND-function
+ self.trainSetAND = {(0, 0): 0, (0, 1): 0, (1, 0): 0, (1, 1): 1}
+
+ # train set for light or dark colors
+ self.trainSetLight = {(11, 98, 237): 'L', (3, 39, 96): 'D',
+ (242, 226, 12): 'L', (99, 93, 4): 'D',
+ (232, 62, 32): 'L', (119, 28, 11): 'D',
+ (25, 214, 47): 'L', (89, 136, 247): 'L',
+ (21, 34, 63): 'D', (237, 99, 120): 'L',
+ (73, 33, 39): 'D'}
+
+ def test_nearest_neighbor(self):
+ # AND-function
+ self.assertEqual(nearest_neighbor((1, 1), self.trainSetAND), 1)
+ self.assertEqual(nearest_neighbor((0, 1), self.trainSetAND), 0)
+
+ # dark/light color test
+ self.assertEqual(nearest_neighbor((31, 242, 164),
+ self.trainSetLight), 'L')
+ self.assertEqual(nearest_neighbor((13, 94, 64),
+ self.trainSetLight), 'D')
+ self.assertEqual(nearest_neighbor((230, 52, 239),
+ self.trainSetLight), 'L')
+
+ def test_distance(self):
+ self.assertAlmostEqual(distance((1, 2, 3), (1, 0, -1)), 4.47, 2)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_monomial.py b/tests/test_monomial.py
new file mode 100644
index 000000000..31e56f79b
--- /dev/null
+++ b/tests/test_monomial.py
@@ -0,0 +1,220 @@
+from algorithms.maths.polynomial import Monomial
+from fractions import Fraction
+import math
+
+
+import unittest
+
+
+class TestSuite(unittest.TestCase):
+
+ def setUp(self):
+ self.m1 = Monomial({})
+ self.m2 = Monomial({1: 1}, 2)
+ self.m3 = Monomial({1: 2, 2: -1}, 1.5)
+ self.m4 = Monomial({1: 1, 2: 2, 3: -2}, 3)
+ self.m5 = Monomial({2: 1, 3: 0}, Fraction(2, 3))
+ self.m6 = Monomial({1: 0, 2: 0, 3: 0}, -2.27)
+ self.m7 = Monomial({1: 2, 7: 2}, -math.pi)
+ self.m8 = Monomial({150: 5, 170: 2, 10000: 3}, 0)
+ self.m9 = 2
+ self.m10 = math.pi
+ self.m11 = Fraction(3, 8)
+ self.m12 = 0
+ self.m13 = Monomial({1: 1}, -2)
+ self.m14 = Monomial({1: 2}, 3)
+ self.m15 = Monomial({1: 1}, 3)
+ self.m16 = Monomial({1: 2, 7: 2}, math.pi)
+ self.m17 = Monomial({1: -1})
+
+ def test_monomial_addition(self):
+
+ # Monomials with different underlying variables or
+ # even different power of those variables must not be added!
+ self.assertRaises(ValueError, lambda x, y: x + y, self.m1, self.m2)
+ self.assertRaises(ValueError, lambda x, y: x + y, self.m2, self.m3)
+ self.assertRaises(ValueError, lambda x, y: x + y, self.m2, self.m14)
+
+ # Additive inverses of each other should produce the zero monomial.
+ self.assertEqual(self.m13 + self.m2, self.m1)
+
+ # Zero monomial + Zero monomial = Zero monomial
+ self.assertEqual(self.m1 + self.m1, self.m1)
+
+ # Coefficient float.
+ self.assertEqual(self.m7 + self.m7, Monomial({1: 2, 7: 2},
+ -2 * math.pi))
+
+ # Coefficient 0 so should equal the zero monomial.
+ self.assertEqual(self.m8, self.m1)
+
+ # The constant term cannot be added to any monomial
+ # that has any variables.
+ self.assertRaises(ValueError, lambda x, y: x + y, self.m2, self.m9)
+
+ # Any literal cannot be added to a Monomial. However, a monomial
+ # can be added to any int, float, Fraction, or Monomial.
+
+ # So 2 + Monomial is raises TypeError but Monomial + 2 may work fine!
+ self.assertRaises(TypeError, lambda x, y: x + y, self.m9, self.m2)
+
+ # Any constant added to a zero monomial produces
+ # a monomial.
+ self.assertEqual(self.m1 + self.m9, Monomial({}, 2))
+ self.assertEqual(self.m1 + self.m12, Monomial({}, 0))
+
+ return
+
+ def test_monomial_subtraction(self):
+
+ # Monomials with different underlying variables or
+ # even different power of those variables must not be subtracted!
+ self.assertRaises(ValueError, lambda x, y: x - y, self.m1, self.m2)
+ self.assertRaises(ValueError, lambda x, y: x - y, self.m2, self.m3)
+ self.assertRaises(ValueError, lambda x, y: x - y, self.m2, self.m14)
+
+ # Additive inverses of each other should produce the zero monomial.
+ self.assertEqual(self.m2 - self.m2, self.m1)
+ self.assertEqual(self.m2 - self.m2, Monomial({}, 0))
+
+ # Zero monomial - Zero monomial = Zero monomial
+ self.assertEqual(self.m1 - self.m1, self.m1)
+
+ # Coefficient int.
+ self.assertEqual(self.m2 - self.m15, Monomial({1: 1}, -1))
+
+ # Coefficient float.
+ self.assertEqual(self.m16 - self.m7, Monomial({1: 2, 7: 2},
+ 2 * math.pi))
+
+ # The constant term cannot be added to any monomial
+ # that has any variables.
+ self.assertRaises(ValueError, lambda x, y: x - y, self.m2, self.m9)
+
+ # Any literal cannot be added to a Monomial. However, a monomial
+ # can be added to any int, float, Fraction, or Monomial.
+
+ # So 2 + Monomial is raises TypeError but Monomial + 2 may work fine!
+ self.assertRaises(TypeError, lambda x, y: x - y, self.m9, self.m2)
+
+ # Any constant added to a zero monomial produces
+ # a monomial.
+ self.assertEqual(self.m1 - self.m9, Monomial({}, -2))
+ self.assertEqual(self.m1 - self.m12, Monomial({}, 0))
+
+ return
+
+ def test_monomial_multiplication(self):
+
+ # Usual multiplication.
+ # The positive and negative powers of the same variable
+ # should cancel out.
+ self.assertEqual(self.m2 * self.m13, Monomial({1: 2}, -4))
+ self.assertEqual(self.m2 * self.m17, Monomial({}, 2))
+
+ # A coefficient of zero should make the product zero.
+ # Zero monomial * any int, float, Fraction, or Monomial = Zero monomial
+ self.assertEqual(self.m8 * self.m5, self.m1)
+ self.assertEqual(self.m1 * self.m2, self.m1)
+
+ # Test usual float multiplication.
+ self.assertEqual(self.m7 * self.m3, Monomial({1: 4, 2: -1, 7: 2},
+ -1.5*math.pi))
+
+ return
+
+ def test_monomial_inverse(self):
+
+ # The Zero monomial is not invertible.
+ self.assertRaises(ValueError, lambda x: x.inverse(), self.m1)
+ self.assertRaises(ValueError, lambda x: x.inverse(), self.m8)
+ self.assertRaises(ValueError, lambda x: x.inverse(),
+ Monomial({}, self.m12))
+
+ # Check some inverses.
+ self.assertEqual(self.m7.inverse(), Monomial({1: -2, 7: -2}, -1 / math.pi))
+
+ # Doesn't matter if the coefficient is Fraction or float.
+ # Both should be treated as same.
+ self.assertEqual(self.m5.inverse(), Monomial({2: -1}, Fraction(3, 2)))
+ self.assertEqual(self.m5.inverse(), Monomial({2: -1}, 1.5))
+
+ # Should work fine without variables too!
+ self.assertTrue(self.m6.inverse(), Monomial({}, Fraction(-100, 227)))
+ self.assertEqual(self.m6.inverse(), Monomial({}, -1/2.27))
+ return
+
+ def test_monomial_division(self):
+ # Any monomial divided by the Zero Monomial should raise a ValueError.
+ self.assertRaises(ValueError, lambda x, y: x.__truediv__(y),
+ self.m2, self.m1)
+ self.assertRaises(ValueError, lambda x, y: x.__truediv__(y),
+ self.m2, self.m8)
+ self.assertRaises(ValueError, lambda x, y: x.__truediv__(y),
+ self.m2, self.m12)
+
+ # Test some usual cases.
+ self.assertEqual(self.m7 / self.m3, Monomial({2: 1, 7: 2},
+ -2 * math.pi / 3))
+ self.assertEqual(self.m14 / self.m13, Monomial({1: 1}) * Fraction(-3, 2))
+
+ return
+
+ def test_monomial_substitution(self):
+ # Test with int.
+ self.assertAlmostEqual(self.m7.substitute(2), -16 * math.pi, delta=1e-9)
+ # Test with float.
+ self.assertAlmostEqual(self.m7.substitute(1.5), (1.5 ** 4) * -math.pi,
+ delta=1e-9)
+ # Test with Fraction.
+ self.assertAlmostEqual(self.m7.substitute(Fraction(-1, 2)),
+ (Fraction(-1, 2) ** 4)*-math.pi, delta=1e-9)
+ # Test with a complete substitution map.
+ self.assertAlmostEqual(self.m7.substitute({1: 3, 7: 0}),
+ (3 ** 2) * (0 ** 2) * -math.pi, delta=1e-9)
+ # Test with a more than complete substitution map.
+ self.assertAlmostEqual(self.m7.substitute({1: 3, 7: 0, 2: 2}),
+ (3 ** 2) * (0 ** 2) * -math.pi, delta=1e-9)
+
+ # Should raise a ValueError if not enough variables are supplied!
+ self.assertRaises(ValueError, lambda x, y: x.substitute(y), self.m7,
+ {1: 3, 2: 2})
+ self.assertRaises(ValueError, lambda x, y: x.substitute(y), self.m7,
+ {2: 2})
+
+ # The zero monomial always gives zero upon substitution.
+ self.assertEqual(self.m8.substitute(2), 0)
+ self.assertEqual(self.m8.substitute({1231: 2, 1: 2}), 0)
+
+ return
+
+ def test_monomial_all_variables(self):
+
+ # Any variable with zero power should not exist in the set
+ # of variables.
+ self.assertEqual(self.m5.all_variables(), {2})
+ self.assertEqual(self.m6.all_variables(), set())
+
+ # The zero monomial should output empty set.
+ self.assertEqual(self.m8.all_variables(), set())
+
+ return
+
+ def test_monomial_clone(self):
+
+ # A monomial should produce its copy
+ # with same underlying variable dictionary
+ # and same coefficient.
+ self.assertEqual(self.m3, self.m3.clone())
+
+ # The zero monomial is identified and
+ # always clones to itself.
+ self.assertEqual(self.m1, self.m8.clone())
+ self.assertEqual(self.m1, self.m1.clone())
+ self.assertEqual(self.m8, self.m1.clone())
+ self.assertEqual(self.m8, self.m8.clone())
+ return
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_polynomial.py b/tests/test_polynomial.py
new file mode 100644
index 000000000..ab5674017
--- /dev/null
+++ b/tests/test_polynomial.py
@@ -0,0 +1,201 @@
+from algorithms.maths.polynomial import (
+ Polynomial,
+ Monomial
+)
+from fractions import Fraction
+import math
+
+
+import unittest
+
+class TestSuite(unittest.TestCase):
+
+ def setUp(self):
+ self.p0 = Polynomial([
+ Monomial({})
+ ])
+ self.p1 = Polynomial([
+ Monomial({}), Monomial({})
+ ])
+ self.p2 = Polynomial([
+ Monomial({1: 1}, 2)
+ ])
+ self.p3 = Polynomial([
+ Monomial({1: 1}, 2),
+ Monomial({1: 2, 2: -1}, 1.5)
+ ])
+ self.p4 = Polynomial([
+ Monomial({2: 1, 3: 0}, Fraction(2, 3)),
+ Monomial({1: -1, 3: 2}, math.pi),
+ Monomial({1: -1, 3: 2}, 1)
+ ])
+ self.p5 = Polynomial([
+ Monomial({150: 5, 170: 2, 10000:3}, 0),
+ Monomial({1: -1, 3: 2}, 1),
+ ])
+ self.p6 = Polynomial([
+ 2,
+ -3,
+ Fraction(1, 7),
+ 2**math.pi,
+ Monomial({2: 3, 3: 1}, 1.25)
+ ])
+ self.p7 = Polynomial([
+ Monomial({1: 1}, -2),
+ Monomial({1: 2, 2: -1}, -1.5)
+ ])
+
+ self.m1 = Monomial({1: 2, 2: 3}, -1)
+
+ return
+
+ def test_polynomial_addition(self):
+
+ # The zero polynomials should add up to
+ # itselves only.
+ self.assertEqual(self.p0 + self.p1, self.p0)
+ self.assertEqual(self.p0 + self.p1, self.p1)
+
+ # Additive inverses should add up to the
+ # zero polynomial.
+ self.assertEqual(self.p3 + self.p7, self.p0)
+ self.assertEqual(self.p3 + self.p7, self.p1)
+
+ # Like terms should combine.
+ # The order of monomials should not matter.
+ self.assertEqual(self.p2 + self.p3, Polynomial([
+ Monomial({1: 1}, 4),
+ Monomial({1: 2, 2: -1}, 1.5)
+ ]))
+ self.assertEqual(self.p2 + self.p3, Polynomial([
+ Monomial({1: 2, 2: -1}, 1.5),
+ Monomial({1: 1}, 4),
+ ]))
+
+ # Another typical computation.
+ self.assertEqual(self.p5 + self.p6, Polynomial([
+ Monomial({}, 7.96783496993343),
+ Monomial({2: 3, 3: 1}, 1.25),
+ Monomial({1: -1, 3: 2})
+ ]))
+
+ return
+
+ def test_polynomial_subtraction(self):
+
+ self.assertEqual(self.p3 - self.p2, Polynomial([
+ Monomial({1: 2, 2: -1}, 1.5)
+ ]))
+
+ self.assertEqual(self.p3 - self.p3, Polynomial([]))
+
+ self.assertEqual(self.p2 - self.p3, Polynomial([
+ Monomial({1: 2, 2: -1}, -1.5)
+ ]))
+
+ pass
+
+ def test_polynomial_multiplication(self):
+ self.assertEqual(self.p0 * self.p2, Polynomial([]))
+ self.assertEqual(self.p1 * self.p2, Polynomial([]))
+
+ self.assertEqual(self.p2 * self.p3, Polynomial([
+ Monomial({1: 2}, 4),
+ Monomial({1: 3, 2: -1}, Fraction(3, 1))
+ ]))
+ return
+
+ def test_polynomial_variables(self):
+ # The zero polynomial has no variables.
+
+ self.assertEqual(self.p0.variables(), set())
+ self.assertEqual(self.p1.variables(), set())
+
+ # The total variables are the union of the variables
+ # from the monomials.
+ self.assertEqual(self.p4.variables(), {1, 2, 3})
+
+ # The monomials with coefficient 0 should be dropped.
+ self.assertEqual(self.p5.variables(), {1, 3})
+ return
+
+ def test_polynomial_subs(self):
+ # Anything substitued in the zero polynomial
+ # should evaluate to 0.
+ self.assertEqual(self.p1.subs(2), 0)
+ self.assertEqual(self.p0.subs(-101231), 0)
+
+ # Should raise a ValueError if not enough variables are supplied.
+ self.assertRaises(ValueError, lambda x, y: x.subs(y), self.p4, {1: 3, 2: 2})
+ self.assertRaises(ValueError, lambda x, y: x.subs(y), self.p4, {})
+
+ # Should work fine if a complete subsitution map is provided.
+ self.assertAlmostEqual(self.p4.subs({1: 1, 2: 1, 3: 1}), (1 + math.pi + Fraction(2, 3)), delta=1e-9)
+ # Should work fine if more than enough substitutions are provided.
+ self.assertAlmostEqual(self.p4.subs({1: 1, 2: 1, 3: 1, 4: 1}), (1 + math.pi + Fraction(2, 3)), delta=1e-9)
+ return
+
+ def test_polynomial_clone(self):
+
+ # The zero polynomial always clones to itself.
+ self.assertEqual(self.p0.clone(), self.p0)
+ self.assertEqual(self.p1.clone(), self.p0)
+ self.assertEqual(self.p0.clone(), self.p1)
+ self.assertEqual(self.p1.clone(), self.p1)
+
+ # The polynomial should clone nicely.
+ self.assertEqual(self.p4.clone(), self.p4)
+
+ # The monomial with a zero coefficient should be dropped
+ # in the clone.
+ self.assertEqual(self.p5.clone(), Polynomial([
+ Monomial({1: -1, 3: 2}, 1)
+ ]))
+ return
+
+ def test_polynomial_long_division(self):
+ """
+ Test polynomial long division
+ """
+
+ # Dividend: 4a_1^3 + 3a_1^2 - 2a_1 + 5
+ dividend = Polynomial([
+ Monomial({1: 3}, 4), # 4(a_1)^3
+ Monomial({1: 2}, 3), # 3(a_1)^2
+ Monomial({1: 1}, -2), # -2(a_1)
+ Monomial({}, 5) # +5
+ ])
+
+ # Divisor: 2a_1 - 1
+ divisor = Polynomial([
+ Monomial({1: 1}, 2), # 2(a_1)
+ Monomial({}, -1) # -1
+ ])
+
+ # Expected Quotient: 2a_1^2 + (5/2)a_1 + 1/4
+ expected_quotient = Polynomial([
+ Monomial({1: 2}, 2), # 2(a_1)^2
+ Monomial({1: 1}, Fraction(5, 2)), # (5/2)(a_1)
+ Monomial({}, Fraction(1, 4)) # +1/4
+ ])
+
+ # Expected Remainder: 21/4
+ expected_remainder = Polynomial([
+ Monomial({}, Fraction(21, 4)) # 21/4
+ ])
+
+ quotient_long_div, remainder_long_div = dividend.poly_long_division(divisor)
+
+ quotient_truediv = dividend / divisor # Calls __truediv__, which returns only the quotient
+
+ # Check if quotient from poly_long_division matches expected
+ self.assertEqual(quotient_long_div, expected_quotient)
+
+ # Check if remainder from poly_long_division matches expected
+ self.assertEqual(remainder_long_div, expected_remainder)
+
+ # Check if quotient from __truediv__ matches quotient from poly_long_division
+ self.assertEqual(quotient_truediv, quotient_long_div)
+
+ return
+
diff --git a/tests/test_queues.py b/tests/test_queues.py
new file mode 100644
index 000000000..5a2f4c89d
--- /dev/null
+++ b/tests/test_queues.py
@@ -0,0 +1,110 @@
+import unittest
+
+from algorithms.queues import (
+ ArrayQueue, LinkedListQueue,
+ max_sliding_window,
+ reconstruct_queue,
+ PriorityQueue
+)
+
+
+class TestQueue(unittest.TestCase):
+ """
+ Test suite for the Queue data structures.
+ """
+
+ def test_ArrayQueue(self):
+ queue = ArrayQueue()
+ queue.enqueue(1)
+ queue.enqueue(2)
+ queue.enqueue(3)
+
+ # test __iter__()
+ it = iter(queue)
+ self.assertEqual(1, next(it))
+ self.assertEqual(2, next(it))
+ self.assertEqual(3, next(it))
+ self.assertRaises(StopIteration, next, it)
+
+ # test __len__()
+ self.assertEqual(3, len(queue))
+
+ # test is_empty()
+ self.assertFalse(queue.is_empty())
+
+ # test peek()
+ self.assertEqual(1, queue.peek())
+
+ # test dequeue()
+ self.assertEqual(1, queue.dequeue())
+ self.assertEqual(2, queue.dequeue())
+ self.assertEqual(3, queue.dequeue())
+
+ self.assertTrue(queue.is_empty())
+
+ def test_LinkedListQueue(self):
+ queue = LinkedListQueue()
+ queue.enqueue(1)
+ queue.enqueue(2)
+ queue.enqueue(3)
+
+ # test __iter__()
+ it = iter(queue)
+ self.assertEqual(1, next(it))
+ self.assertEqual(2, next(it))
+ self.assertEqual(3, next(it))
+ self.assertRaises(StopIteration, next, it)
+
+ # test __len__()
+ self.assertEqual(3, len(queue))
+
+ # test is_empty()
+ self.assertFalse(queue.is_empty())
+
+ # test peek()
+ self.assertEqual(1, queue.peek())
+
+ # test dequeue()
+ self.assertEqual(1, queue.dequeue())
+ self.assertEqual(2, queue.dequeue())
+ self.assertEqual(3, queue.dequeue())
+
+ self.assertTrue(queue.is_empty())
+
+
+class TestSuite(unittest.TestCase):
+ def test_max_sliding_window(self):
+ array = [1, 3, -1, -3, 5, 3, 6, 7]
+ self.assertEqual(max_sliding_window(array, k=5), [5, 5, 6, 7])
+ self.assertEqual(max_sliding_window(array, k=3), [3, 3, 5, 5, 6, 7])
+ self.assertEqual(max_sliding_window(array, k=7), [6, 7])
+
+ array = [8, 5, 10, 7, 9, 4, 15, 12, 90, 13]
+ self.assertEqual(max_sliding_window(array, k=4),
+ [10, 10, 10, 15, 15, 90, 90])
+ self.assertEqual(max_sliding_window(array, k=7), [15, 15, 90, 90])
+ self.assertEqual(max_sliding_window(array, k=2),
+ [8, 10, 10, 9, 9, 15, 15, 90, 90])
+
+ def test_reconstruct_queue(self):
+ self.assertEqual([[5, 0], [7, 0], [5, 2], [6, 1], [4, 4], [7, 1]],
+ reconstruct_queue([[7, 0], [4, 4], [7, 1], [5, 0],
+ [6, 1], [5, 2]]))
+
+
+class TestPriorityQueue(unittest.TestCase):
+ """Test suite for the PriorityQueue data structures.
+ """
+
+ def test_PriorityQueue(self):
+ queue = PriorityQueue([3, 4, 1, 6])
+ self.assertEqual(4, queue.size())
+ self.assertEqual(1, queue.pop())
+ self.assertEqual(3, queue.size())
+ queue.push(2)
+ self.assertEqual(4, queue.size())
+ self.assertEqual(2, queue.pop())
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_search.py b/tests/test_search.py
new file mode 100644
index 000000000..f515cfcb9
--- /dev/null
+++ b/tests/test_search.py
@@ -0,0 +1,153 @@
+from algorithms.search import (
+ binary_search, binary_search_recur,
+ ternary_search,
+ first_occurrence,
+ last_occurrence,
+ linear_search,
+ search_insert,
+ two_sum, two_sum1, two_sum2,
+ search_range,
+ find_min_rotate, find_min_rotate_recur,
+ search_rotate, search_rotate_recur,
+ jump_search,
+ next_greatest_letter, next_greatest_letter_v1, next_greatest_letter_v2,
+ interpolation_search
+)
+
+import unittest
+
+
+class TestSuite(unittest.TestCase):
+
+ def test_first_occurrence(self):
+ def helper(array, query):
+ idx = array.index(query) if query in array else None
+ return idx
+ array = [1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 6, 6, 6]
+ self.assertEqual(first_occurrence(array, 1), helper(array, 1))
+ self.assertEqual(first_occurrence(array, 3), helper(array, 3))
+ self.assertEqual(first_occurrence(array, 5), helper(array, 5))
+ self.assertEqual(first_occurrence(array, 6), helper(array, 6))
+ self.assertEqual(first_occurrence(array, 7), helper(array, 7))
+ self.assertEqual(first_occurrence(array, -1), helper(array, -1))
+
+ def test_binary_search(self):
+ array = [1, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 6]
+ self.assertEqual(10, binary_search(array, 5))
+ self.assertEqual(11, binary_search(array, 6))
+ self.assertEqual(None, binary_search(array, 7))
+ self.assertEqual(None, binary_search(array, -1))
+ # Test binary_search_recur
+ self.assertEqual(10, binary_search_recur(array, 0, 11, 5))
+ self.assertEqual(11, binary_search_recur(array, 0, 11, 6))
+ self.assertEqual(-1, binary_search_recur(array, 0, 11, 7))
+ self.assertEqual(-1, binary_search_recur(array, 0, 11, -1))
+
+ def test_ternary_search(self):
+ array = [1, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 6]
+ self.assertEqual(10, ternary_search(0, 11, 5, array))
+ self.assertEqual(3, ternary_search(0, 10, 3, array))
+ self.assertEqual(-1, ternary_search(0, 10, 5, array))
+ self.assertEqual(-1, ternary_search(0, 11, 7, array))
+ self.assertEqual(-1, ternary_search(0, 11, -1, array))
+
+ def test_last_occurrence(self):
+ array = [1, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 6, 6, 6]
+ self.assertEqual(5, last_occurrence(array, 3))
+ self.assertEqual(10, last_occurrence(array, 5))
+ self.assertEqual(None, last_occurrence(array, 7))
+ self.assertEqual(0, last_occurrence(array, 1))
+ self.assertEqual(13, last_occurrence(array, 6))
+
+ def test_linear_search(self):
+ array = [1, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 6, 6, 6]
+ self.assertEqual(6, linear_search(array, 4))
+ self.assertEqual(10, linear_search(array, 5))
+ self.assertEqual(-1, linear_search(array, 7))
+ self.assertEqual(-1, linear_search(array, -1))
+
+ def test_search_insert(self):
+ array = [1, 3, 5, 6]
+ self.assertEqual(2, search_insert(array, 5))
+ self.assertEqual(1, search_insert(array, 2))
+ self.assertEqual(4, search_insert(array, 7))
+ self.assertEqual(0, search_insert(array, 0))
+
+ def test_two_sum(self):
+ array = [2, 7, 11, 15]
+ # test two_sum
+ self.assertEqual([1, 2], two_sum(array, 9))
+ self.assertEqual([2, 4], two_sum(array, 22))
+ # test two_sum1
+ self.assertEqual([1, 2], two_sum1(array, 9))
+ self.assertEqual([2, 4], two_sum1(array, 22))
+ # test two_sum2
+ self.assertEqual([1, 2], two_sum2(array, 9))
+ self.assertEqual([2, 4], two_sum2(array, 22))
+
+ def test_search_range(self):
+ array = [5, 7, 7, 8, 8, 8, 10]
+ self.assertEqual([3, 5], search_range(array, 8))
+ self.assertEqual([1, 2], search_range(array, 7))
+ self.assertEqual([-1, -1], search_range(array, 11))
+
+ array = [5, 7, 7, 7, 7, 8, 8, 8, 8, 10]
+ self.assertEqual([5, 8], search_range(array, 8))
+ self.assertEqual([1, 4], search_range(array, 7))
+ self.assertEqual([-1, -1], search_range(array, 11))
+
+ def test_find_min_rotate(self):
+ array = [4, 5, 6, 7, 0, 1, 2]
+ self.assertEqual(0, find_min_rotate(array))
+ array = [10, 20, -1, 0, 1, 2, 3, 4, 5]
+ self.assertEqual(-1, find_min_rotate(array))
+ # Test find min using recursion
+ array = [4, 5, 6, 7, 0, 1, 2]
+ self.assertEqual(0, find_min_rotate_recur(array, 0, 6))
+ array = [10, 20, -1, 0, 1, 2, 3, 4, 5]
+ self.assertEqual(-1, find_min_rotate_recur(array, 0, 8))
+
+ def test_search_rotate(self):
+ array = [15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14]
+ self.assertEqual(8, search_rotate(array, 5))
+ self.assertEqual(-1, search_rotate(array, 9))
+ self.assertEqual(8, search_rotate_recur(array, 0, 11, 5))
+ self.assertEqual(-1, search_rotate_recur(array, 0, 11, 9))
+
+ def test_jump_search(self):
+ array = [1, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 6]
+ self.assertEqual(10, jump_search(array, 5))
+ self.assertEqual(2, jump_search(array, 3))
+ self.assertEqual(-1, jump_search(array, 7))
+ self.assertEqual(-1, jump_search(array, -1))
+
+ def test_next_greatest_letter(self):
+ letters = ["c", "f", "j"]
+ target = "a"
+ self.assertEqual("c", next_greatest_letter(letters, target))
+ self.assertEqual("c", next_greatest_letter_v1(letters, target))
+ self.assertEqual("c", next_greatest_letter_v2(letters, target))
+ letters = ["c", "f", "j"]
+ target = "d"
+ self.assertEqual("f", next_greatest_letter(letters, target))
+ self.assertEqual("f", next_greatest_letter_v1(letters, target))
+ self.assertEqual("f", next_greatest_letter_v2(letters, target))
+ letters = ["c", "f", "j"]
+ target = "j"
+ self.assertEqual("c", next_greatest_letter(letters, target))
+ self.assertEqual("c", next_greatest_letter_v1(letters, target))
+ self.assertEqual("c", next_greatest_letter_v2(letters, target))
+
+ def test_interpolation_search(self):
+ array = [0, 3, 5, 5, 9, 12, 12, 15, 16, 19, 20]
+ self.assertEqual(1, interpolation_search(array, 3))
+ self.assertEqual(2, interpolation_search(array, 5))
+ self.assertEqual(6, interpolation_search(array, 12))
+ self.assertEqual(-1, interpolation_search(array, 22))
+ self.assertEqual(-1, interpolation_search(array, -10))
+ self.assertEqual(10, interpolation_search(array, 20))
+
+
+if __name__ == '__main__':
+
+ unittest.main()
diff --git a/tests/test_set.py b/tests/test_set.py
new file mode 100644
index 000000000..e2985c942
--- /dev/null
+++ b/tests/test_set.py
@@ -0,0 +1,12 @@
+from algorithms.set import (
+ find_keyboard_row
+)
+
+import unittest
+
+
+class TestFindKeyboardRow(unittest.TestCase):
+ def test_find_keyboard_row(self):
+ self.assertEqual(["Alaska", "Dad"],
+ find_keyboard_row(["Hello", "Alaska",
+ "Dad", "Peace"]))
diff --git a/tests/test_sort.py b/tests/test_sort.py
new file mode 100644
index 000000000..c80290fdf
--- /dev/null
+++ b/tests/test_sort.py
@@ -0,0 +1,130 @@
+from algorithms.sort import (
+ bitonic_sort,
+ bogo_sort,
+ bubble_sort,
+ comb_sort,
+ counting_sort,
+ cycle_sort,
+ exchange_sort,
+ max_heap_sort, min_heap_sort,
+ merge_sort,
+ pancake_sort,
+ pigeonhole_sort,
+ quick_sort,
+ selection_sort,
+ bucket_sort,
+ shell_sort,
+ radix_sort,
+ gnome_sort,
+ cocktail_shaker_sort,
+ top_sort, top_sort_recursive
+)
+
+import unittest
+
+
+def is_sorted(array):
+ """
+ Helper function to check if the given array is sorted.
+ :param array: Array to check if sorted
+ :return: True if sorted in ascending order, else False
+ """
+ for i in range(len(array) - 1):
+ if array[i] > array[i + 1]:
+ return False
+
+ return True
+
+
+class TestSuite(unittest.TestCase):
+ def test_bogo_sort(self):
+ self.assertTrue(is_sorted(bogo_sort([1, 23, 5])))
+
+ def test_bitonic_sort(self):
+ self.assertTrue(is_sorted(bitonic_sort([1, 3, 2, 5, 65,
+ 23, 57, 1232])))
+
+ def test_bubble_sort(self):
+ self.assertTrue(is_sorted(bubble_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+
+ def test_comb_sort(self):
+ self.assertTrue(is_sorted(comb_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+
+ def test_counting_sort(self):
+ self.assertTrue(is_sorted(counting_sort([1, 3, 2, 5, 65,
+ 23, 57, 1232])))
+
+ def test_cycle_sort(self):
+ self.assertTrue(is_sorted(cycle_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+
+ def test_exchange_sort(self):
+ self.assertTrue(is_sorted(exchange_sort([1, 3, 2, 5, 65,
+ 23, 57, 1232])))
+
+ def test_heap_sort(self):
+ self.assertTrue(is_sorted(max_heap_sort([1, 3, 2, 5, 65,
+ 23, 57, 1232])))
+
+ self.assertTrue(is_sorted(min_heap_sort([1, 3, 2, 5, 65,
+ 23, 57, 1232])))
+
+ def test_insertion_sort(self):
+ self.assertTrue(is_sorted(bitonic_sort([1, 3, 2, 5, 65,
+ 23, 57, 1232])))
+
+ def test_merge_sort(self):
+ self.assertTrue(is_sorted(merge_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+
+ def test_pancake_sort(self):
+ self.assertTrue(is_sorted(pancake_sort([1, 3, 2, 5, 65,
+ 23, 57, 1232])))
+
+ def test_pigeonhole_sort(self):
+ self.assertTrue(is_sorted(pigeonhole_sort([1, 5, 65, 23, 57, 1232])))
+
+ def test_quick_sort(self):
+ self.assertTrue(is_sorted(quick_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+
+ def test_selection_sort(self):
+ self.assertTrue(is_sorted(selection_sort([1, 3, 2, 5, 65,
+ 23, 57, 1232])))
+
+ def test_bucket_sort(self):
+ self.assertTrue(is_sorted(bucket_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+
+ def test_shell_sort(self):
+ self.assertTrue(is_sorted(shell_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+
+ def test_radix_sort(self):
+ self.assertTrue(is_sorted(radix_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+
+ def test_gnome_sort(self):
+ self.assertTrue(is_sorted(gnome_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+
+ def test_cocktail_shaker_sort(self):
+ self.assertTrue(is_sorted(cocktail_shaker_sort([1, 3, 2, 5, 65,
+ 23, 57, 1232])))
+
+
+class TestTopSort(unittest.TestCase):
+ def setUp(self):
+ self.depGraph = {
+ "a": ["b"],
+ "b": ["c"],
+ "c": ['e'],
+ 'e': ['g'],
+ "d": [],
+ "f": ["e", "d"],
+ "g": []
+ }
+
+ def test_topsort(self):
+ res = top_sort_recursive(self.depGraph)
+ # print(res)
+ self.assertTrue(res.index('g') < res.index('e'))
+ res = top_sort(self.depGraph)
+ self.assertTrue(res.index('g') < res.index('e'))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_stack.py b/tests/test_stack.py
new file mode 100644
index 000000000..93b389737
--- /dev/null
+++ b/tests/test_stack.py
@@ -0,0 +1,154 @@
+from algorithms.stack import (
+ first_is_consecutive, second_is_consecutive,
+ is_sorted,
+ remove_min,
+ first_stutter, second_stutter,
+ first_switch_pairs, second_switch_pairs,
+ is_valid,
+ simplify_path,
+ ArrayStack, LinkedListStack,
+ OrderedStack
+)
+
+import unittest
+
+
+class TestSuite(unittest.TestCase):
+ def test_is_consecutive(self):
+ self.assertTrue(first_is_consecutive([3, 4, 5, 6, 7]))
+ self.assertFalse(first_is_consecutive([3, 4, 6, 7]))
+ self.assertFalse(first_is_consecutive([3, 2, 1]))
+
+ self.assertTrue(second_is_consecutive([3, 4, 5, 6, 7]))
+ self.assertFalse(second_is_consecutive([3, 4, 6, 7]))
+ self.assertFalse(second_is_consecutive([3, 2, 1]))
+
+ def test_is_sorted(self):
+ # Test case: bottom [6, 3, 5, 1, 2, 4] top
+ self.assertFalse(is_sorted([6, 3, 5, 1, 2, 4]))
+ self.assertTrue(is_sorted([1, 2, 3, 4, 5, 6]))
+ self.assertFalse(is_sorted([3, 4, 7, 8, 5, 6]))
+
+ def test_remove_min(self):
+ # Test case: bottom [2, 8, 3, -6, 7, 3] top
+ self.assertEqual([2, 8, 3, 7, 3], remove_min([2, 8, 3, -6, 7, 3]))
+ # Test case: 2 smallest value [2, 8, 3, 7, 3]
+ self.assertEqual([4, 8, 7], remove_min([4, 8, 3, 7, 3]))
+
+ def test_stutter(self):
+ # Test case: bottom [3, 7, 1, 14, 9] top
+ self.assertEqual([3, 3, 7, 7, 1, 1, 14, 14, 9, 9],
+ first_stutter([3, 7, 1, 14, 9]))
+ self.assertEqual([3, 3, 7, 7, 1, 1, 14, 14, 9, 9],
+ second_stutter([3, 7, 1, 14, 9]))
+
+ def test_switch_pairs(self):
+ # Test case: even number of values in stack
+ # bottom [3, 8, 17, 9, 1, 10] top
+ self.assertEqual([8, 3, 9, 17, 10, 1],
+ first_switch_pairs([3, 8, 17, 9, 1, 10]))
+ self.assertEqual([8, 3, 9, 17, 10, 1],
+ second_switch_pairs([3, 8, 17, 9, 1, 10]))
+ # Test case: odd number of values in stack
+ # bottom [3, 8, 17, 9, 1] top
+ self.assertEqual([8, 3, 9, 17, 1],
+ first_switch_pairs([3, 8, 17, 9, 1]))
+ self.assertEqual([8, 3, 9, 17, 1],
+ second_switch_pairs([3, 8, 17, 9, 1]))
+
+ def test_is_valid_parenthesis(self):
+
+ self.assertTrue(is_valid("[]"))
+ self.assertTrue(is_valid("[]()[]"))
+ self.assertFalse(is_valid("[[[]]"))
+ self.assertTrue(is_valid("{([])}"))
+ self.assertFalse(is_valid("(}"))
+
+ def test_simplify_path(self):
+ p = '/my/name/is/..//keon'
+ self.assertEqual('/my/name/keon', simplify_path(p))
+
+
+class TestStack(unittest.TestCase):
+ def test_ArrayStack(self):
+ stack = ArrayStack()
+ stack.push(1)
+ stack.push(2)
+ stack.push(3)
+
+ # test __iter__()
+ it = iter(stack)
+ self.assertEqual(3, next(it))
+ self.assertEqual(2, next(it))
+ self.assertEqual(1, next(it))
+ self.assertRaises(StopIteration, next, it)
+
+ # test __len__()
+ self.assertEqual(3, len(stack))
+
+ # test __str__()
+ self.assertEqual(str(stack), "Top-> 3 2 1")
+
+ # test is_empty()
+ self.assertFalse(stack.is_empty())
+
+ # test peek()
+ self.assertEqual(3, stack.peek())
+
+ # test pop()
+ self.assertEqual(3, stack.pop())
+ self.assertEqual(2, stack.pop())
+ self.assertEqual(1, stack.pop())
+
+ self.assertTrue(stack.is_empty())
+
+ def test_LinkedListStack(self):
+ stack = LinkedListStack()
+
+ stack.push(1)
+ stack.push(2)
+ stack.push(3)
+
+ # test __iter__()
+ it = iter(stack)
+ self.assertEqual(3, next(it))
+ self.assertEqual(2, next(it))
+ self.assertEqual(1, next(it))
+ self.assertRaises(StopIteration, next, it)
+
+ # test __len__()
+ self.assertEqual(3, len(stack))
+
+ # test __str__()
+ self.assertEqual(str(stack), "Top-> 3 2 1")
+
+ # test is_empty()
+ self.assertFalse(stack.is_empty())
+
+ # test peek()
+ self.assertEqual(3, stack.peek())
+
+ # test pop()
+ self.assertEqual(3, stack.pop())
+ self.assertEqual(2, stack.pop())
+ self.assertEqual(1, stack.pop())
+
+ self.assertTrue(stack.is_empty())
+
+
+class TestOrderedStack(unittest.TestCase):
+ def test_OrderedStack(self):
+ stack = OrderedStack()
+ self.assertTrue(stack.is_empty())
+ stack.push(1)
+ stack.push(4)
+ stack.push(3)
+ stack.push(6)
+ "bottom - > 1 3 4 6 "
+ self.assertEqual(6, stack.pop())
+ self.assertEqual(4, stack.peek())
+ self.assertEqual(3, stack.size())
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_streaming.py b/tests/test_streaming.py
new file mode 100644
index 000000000..2f59827ef
--- /dev/null
+++ b/tests/test_streaming.py
@@ -0,0 +1,41 @@
+from algorithms.streaming.misra_gries import (
+ misras_gries,
+)
+from algorithms.streaming import (
+ one_sparse
+)
+import unittest
+
+
+class TestMisraGreis(unittest.TestCase):
+ def test_misra_correct(self):
+ self.assertEqual({'4': 5}, misras_gries([1, 4, 4, 4, 5, 4, 4]))
+ self.assertEqual({'1': 4}, misras_gries([0, 0, 0, 1, 1, 1, 1]))
+ self.assertEqual({'0': 4, '1': 3}, misras_gries([0, 0, 0, 0, 1, 1,
+ 1, 2, 2], 3))
+
+ def test_misra_incorrect(self):
+ self.assertEqual(None, misras_gries([1, 2, 5, 4, 5, 4, 4, 5, 4, 4, 5]))
+ self.assertEqual(None, misras_gries([0, 0, 0, 2, 1, 1, 1]))
+ self.assertEqual(None, misras_gries([0, 0, 0, 1, 1, 1]))
+
+
+class TestOneSparse(unittest.TestCase):
+ def test_one_sparse_correct(self):
+ self.assertEqual(4, one_sparse([(4, '+'), (2, '+'), (2, '-'),
+ (4, '+'), (3, '+'), (3, '-')]))
+ self.assertEqual(2, one_sparse([(2, '+'), (2, '+'), (2, '+'),
+ (2, '+'), (2, '+'), (2, '+'),
+ (2, '+')]))
+
+ def test_one_sparse_incorrect(self):
+ self.assertEqual(None, one_sparse([(2, '+'), (2, '+'), (2, '+'),
+ (2, '+'), (2, '+'), (2, '+'),
+ (1, '+')])) # Two values remaining
+ self.assertEqual(None, one_sparse([(2, '+'), (2, '+'),
+ (2, '+'), (2, '+'),
+ (2, '-'), (2, '-'), (2, '-'),
+ (2, '-')])) # No values remaining
+ # Bitsum sum of sign is inccorect
+ self.assertEqual(None, one_sparse([(2, '+'), (2, '+'),
+ (4, '+'), (4, '+')]))
diff --git a/tests/test_strings.py b/tests/test_strings.py
new file mode 100644
index 000000000..e7a68302a
--- /dev/null
+++ b/tests/test_strings.py
@@ -0,0 +1,732 @@
+from algorithms.strings import (
+ add_binary,
+ match_symbol, match_symbol_1, bracket,
+ decode_string,
+ delete_reoccurring_characters,
+ domain_name_1, domain_name_2,
+ encode, decode,
+ group_anagrams,
+ int_to_roman,
+ is_palindrome, is_palindrome_reverse,
+ is_palindrome_two_pointer, is_palindrome_stack, is_palindrome_deque,
+ is_rotated, is_rotated_v1,
+ license_number,
+ make_sentence,
+ is_merge_recursive, is_merge_iterative,
+ multiply,
+ is_one_edit, is_one_edit2,
+ rabin_karp,
+ ultra_pythonic, iterative, recursive, pythonic,
+ reverse_vowel,
+ reverse_words,
+ roman_to_int,
+ is_valid_coordinates_0,
+ word_squares,
+ convert_morse_word, unique_morse,
+ judge_circle,
+ strong_password,
+ caesar_cipher,
+ check_pangram,
+ contain_string,
+ count_binary_substring,
+ repeat_string,
+ text_justification,
+ min_distance,
+ min_distance_dp,
+ longest_common_prefix_v1, longest_common_prefix_v2,
+ longest_common_prefix_v3,
+ rotate, rotate_alt,
+ first_unique_char,
+ repeat_substring,
+ atbash,
+ longest_palindrome,
+ knuth_morris_pratt,
+ panagram,
+ fizzbuzz
+)
+
+import unittest
+
+
+class TestAddBinary(unittest.TestCase):
+ """[summary]
+ Test for the file add_binary.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_add_binary(self):
+ self.assertEqual("100", add_binary("11", "1"))
+ self.assertEqual("101", add_binary("100", "1"))
+ self.assertEqual("10", add_binary("1", "1"))
+
+
+class TestBreakingBad(unittest.TestCase):
+ """[summary]
+ Test for the file breaking_bad.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def setUp(self):
+ self.words = ['Amazon', 'Microsoft', 'Google']
+ self.symbols = ['i', 'Am', 'cro', 'le', 'abc']
+ self.result = ['M[i]crosoft', '[Am]azon', 'Mi[cro]soft', 'Goog[le]']
+
+ def test_match_symbol(self):
+ self.assertEqual(self.result, match_symbol(self.words, self.symbols))
+
+ def test_match_symbol_1(self):
+ self.assertEqual(['[Am]azon', 'Mi[cro]soft', 'Goog[le]'],
+ match_symbol_1(self.words, self.symbols))
+
+ def test_bracket(self):
+ self.assertEqual(('[Am]azon', 'Mi[cro]soft', 'Goog[le]'),
+ bracket(self.words, self.symbols))
+ self.assertEqual(('Amazon', 'Microsoft', 'Google'),
+ bracket(self.words, ['thisshouldnotmatch']))
+ self.assertEqual(('Amazon', 'M[i]crosoft', 'Google'),
+ bracket(self.words, ['i', 'i']))
+
+
+class TestDecodeString(unittest.TestCase):
+ """[summary]
+ Test for the file decode_string.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_decode_string(self):
+ self.assertEqual("aaabcbc", decode_string("3[a]2[bc]"))
+ self.assertEqual("accaccacc", decode_string("3[a2[c]]"))
+
+
+class TestDeleteReoccurring(unittest.TestCase):
+ """[summary]
+ Test for the file delete_reoccurring.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_delete_reoccurring_characters(self):
+ self.assertEqual("abc", delete_reoccurring_characters("aaabcccc"))
+
+
+class TestDomainExtractor(unittest.TestCase):
+ """[summary]
+ Test for the file domain_extractor.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_valid(self):
+ self.assertEqual(domain_name_1("https://github.com/SaadBenn"),
+ "github")
+
+ def test_invalid(self):
+ self.assertEqual(domain_name_2("http://google.com"), "google")
+
+
+class TestEncodeDecode(unittest.TestCase):
+ """[summary]
+ Test for the file encode_decode.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_encode(self):
+ self.assertEqual("4:keon2:is7:awesome", encode("keon is awesome"))
+
+ def test_decode(self):
+ self.assertEqual(['keon', 'is', 'awesome'],
+ decode("4:keon2:is7:awesome"))
+
+
+class TestGroupAnagrams(unittest.TestCase):
+ """[summary]
+ Test for the file group_anagrams.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_group_anagrams(self):
+ self.assertEqual([['eat', 'tea', 'ate'], ['tan', 'nat'], ['bat']], \
+ group_anagrams(["eat", "tea", "tan", "ate", "nat",
+ "bat"]))
+
+
+class TestIntToRoman(unittest.TestCase):
+ """[summary]
+ Test for the file int_to_roman.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_int_to_roman(self):
+ self.assertEqual("DCXLIV", int_to_roman(644))
+ self.assertEqual("I", int_to_roman(1))
+ self.assertEqual("MMMCMXCIX", int_to_roman(3999))
+
+
+class TestIsPalindrome(unittest.TestCase):
+ """[summary]
+ Test for the file is_palindrome.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_is_palindrome(self):
+ # 'Otto' is a old german name.
+ self.assertTrue(is_palindrome("Otto"))
+ self.assertFalse(is_palindrome("house"))
+
+ def test_is_palindrome_reverse(self):
+ # 'Otto' is a old german name.
+ self.assertTrue(is_palindrome_reverse("Otto"))
+ self.assertFalse(is_palindrome_reverse("house"))
+
+ def test_is_palindrome_two_pointer(self):
+ # 'Otto' is a old german name.
+ self.assertTrue(is_palindrome_two_pointer("Otto"))
+ self.assertFalse(is_palindrome_two_pointer("house"))
+
+ def test_is_palindrome_stack(self):
+ # 'Otto' is a old german name.
+ self.assertTrue(is_palindrome_stack("Otto"))
+ self.assertFalse(is_palindrome_stack("house"))
+
+ def test_is_palindrome_deque(self):
+ # 'Otto' is a old german name.
+ self.assertTrue(is_palindrome_deque("Otto"))
+ self.assertFalse(is_palindrome_deque("house"))
+
+
+class TestIsRotated(unittest.TestCase):
+ """[summary]
+ Test for the file is_rotated.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_is_rotated(self):
+ self.assertTrue(is_rotated("hello", "hello"))
+ self.assertTrue(is_rotated("hello", "llohe"))
+ self.assertFalse(is_rotated("hello", "helol"))
+ self.assertFalse(is_rotated("hello", "lloh"))
+ self.assertTrue(is_rotated("", ""))
+
+ def test_is_rotated_v1(self):
+ self.assertTrue(is_rotated_v1("hello", "hello"))
+ self.assertTrue(is_rotated_v1("hello", "llohe"))
+ self.assertFalse(is_rotated_v1("hello", "helol"))
+ self.assertFalse(is_rotated_v1("hello", "lloh"))
+ self.assertTrue(is_rotated_v1("", ""))
+
+
+class TestRotated(unittest.TestCase):
+ def test_rotate(self):
+ self.assertEqual("llohe", rotate("hello", 2))
+ self.assertEqual("hello", rotate("hello", 5))
+ self.assertEqual("elloh", rotate("hello", 6))
+ self.assertEqual("llohe", rotate("hello", 7))
+
+ def test_rotate_alt(self):
+ self.assertEqual("llohe", rotate_alt("hello", 2))
+ self.assertEqual("hello", rotate_alt("hello", 5))
+ self.assertEqual("elloh", rotate_alt("hello", 6))
+ self.assertEqual("llohe", rotate_alt("hello", 7))
+
+
+class TestLicenseNumber(unittest.TestCase):
+ """[summary]
+ Test for the file license_number.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_license_number(self):
+ self.assertEqual("a-b-c-d-f-d-d-f", license_number("a-bc-dfd-df", 1))
+ self.assertEqual("ab-cd-fd-df", license_number("a-bc-dfd-df", 2))
+ self.assertEqual("ab-cdf-ddf", license_number("a-bc-dfd-df", 3))
+ self.assertEqual("abcd-fddf", license_number("a-bc-dfd-df", 4))
+ self.assertEqual("abc-dfddf", license_number("a-bc-dfd-df", 5))
+
+
+class TestMakeSentence(unittest.TestCase):
+ """[summary]
+ Test for the file make_sentence.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_make_sentence(self):
+ dictionarys = ["", "app", "let", "t", "apple", "applet"]
+ word = "applet"
+ self.assertTrue(make_sentence(word, dictionarys))
+
+
+class TestMergeStringChecker(unittest.TestCase):
+ """[summary]
+ Test for the file merge_string_checker.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_is_merge_recursive(self):
+ self.assertTrue(is_merge_recursive("codewars", "cdw", "oears"))
+
+ def test_is_merge_iterative(self):
+ self.assertTrue(is_merge_iterative("codewars", "cdw", "oears"))
+
+
+class TestMultiplyStrings(unittest.TestCase):
+ """[summary]
+ Test for the file multiply_strings.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_multiply(self):
+ self.assertEqual("23", multiply("1", "23"))
+ self.assertEqual("529", multiply("23", "23"))
+ self.assertEqual("0", multiply("0", "23"))
+ self.assertEqual("1000000", multiply("100", "10000"))
+
+
+class TestOneEditDistance(unittest.TestCase):
+ """[summary]
+ Test for the file one_edit_distance.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_is_one_edit(self):
+ self.assertTrue(is_one_edit("abc", "abd"))
+ self.assertFalse(is_one_edit("abc", "aed"))
+ self.assertFalse(is_one_edit("abcd", "abcd"))
+
+ def test_is_one_edit2(self):
+ self.assertTrue(is_one_edit2("abc", "abd"))
+ self.assertFalse(is_one_edit2("abc", "aed"))
+ self.assertFalse(is_one_edit2("abcd", "abcd"))
+
+
+class TestRabinKarp(unittest.TestCase):
+ """[summary]
+ Test for the file rabin_karp.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_rabin_karp(self):
+ self.assertEqual(3, rabin_karp("abc", "zsnabckfkd"))
+ self.assertEqual(None, rabin_karp("abc", "zsnajkskfkd"))
+
+
+class TestReverseString(unittest.TestCase):
+ """[summary]
+ Test for the file reverse_string.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_recursive(self):
+ self.assertEqual("ereht olleh", recursive("hello there"))
+
+ def test_iterative(self):
+ self.assertEqual("ereht olleh", iterative("hello there"))
+
+ def test_pythonic(self):
+ self.assertEqual("ereht olleh", pythonic("hello there"))
+
+ def test_ultra_pythonic(self):
+ self.assertEqual("ereht olleh", ultra_pythonic("hello there"))
+
+
+class TestReverseVowel(unittest.TestCase):
+ """[summary]
+ Test for the file reverse_vowel.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_reverse_vowel(self):
+ self.assertEqual("holle", reverse_vowel("hello"))
+
+
+class TestReverseWords(unittest.TestCase):
+ """[summary]
+ Test for the file reverse_words.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_reverse_words(self):
+ self.assertEqual("pizza like I and kim keon am I", \
+ reverse_words("I am keon kim and I like pizza"))
+
+
+class TestRomanToInt(unittest.TestCase):
+ """[summary]
+ Test for the file roman_to_int.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_roman_to_int(self):
+ self.assertEqual(621, roman_to_int("DCXXI"))
+ self.assertEqual(1, roman_to_int("I"))
+ self.assertEqual(3999, roman_to_int("MMMCMXCIX"))
+
+
+# class TestStripUrlParams(unittest.TestCase):
+# """[summary]
+# Test for the file strip_urls_params.py
+
+# Arguments:
+# unittest {[type]} -- [description]
+# """
+
+# def test_strip_url_params1(self):
+# self.assertEqual(strip_url_params1("www.saadbenn.com?a=1&b=2&a=2"),
+# "www.saadbenn.com?a=1&b=2")
+# self.assertEqual(strip_url_params1("www.saadbenn.com?a=1&b=2",
+# ['b']), "www.saadbenn.com?a=1")
+# def test_strip_url_params2(self):
+# self.assertEqual(strip_url_params2("www.saadbenn.com?a=1&b=2&a=2"),
+# "www.saadbenn.com?a=1&b=2")
+# self.assertEqual(strip_url_params2("www.saadbenn.com?a=1&b=2",
+# 'b']), "www.saadbenn.com?a=1")
+# def test_strip_url_params3(self):
+# self.assertEqual(strip_url_params3("www.saadbenn.com?a=1&b=2&a=2"),
+# "www.saadbenn.com?a=1&b=2")
+# self.assertEqual(strip_url_params3("www.saadbenn.com?a=1&b=2",
+# ['b']), "www.saadbenn.com?a=1")
+
+
+class TestValidateCoordinates(unittest.TestCase):
+ """[summary]
+ Test for the file validate_coordinates.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_valid(self):
+ valid_coordinates = ["-23, 25", "4, -3", "90, 180", "-90, -180"]
+ for coordinate in valid_coordinates:
+ self.assertTrue(is_valid_coordinates_0(coordinate))
+
+ def test_invalid(self):
+ invalid_coordinates = ["23.234, - 23.4234", "99.234, 12.324",
+ "6.325624, 43.34345.345", "0, 1,2",
+ "23.245, 1e1"]
+ for coordinate in invalid_coordinates:
+ self.assertFalse(is_valid_coordinates_0(coordinate))
+
+
+class TestWordSquares(unittest.TestCase):
+ """[summary]
+ Test for the file word_squares.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_word_squares(self):
+ self.assertEqual([['wall', 'area', 'lead', 'lady'], ['ball', 'area',
+ 'lead', 'lady']], \
+ word_squares(["area", "lead", "wall",
+ "lady", "ball"]))
+
+
+class TestUniqueMorse(unittest.TestCase):
+ def test_convert_morse_word(self):
+ self.assertEqual("--...-.", convert_morse_word("gin"))
+ self.assertEqual("--...--.", convert_morse_word("msg"))
+
+ def test_unique_morse(self):
+ self.assertEqual(2, unique_morse(["gin", "zen", "gig", "msg"]))
+
+
+class TestJudgeCircle(unittest.TestCase):
+ def test_judge_circle(self):
+ self.assertTrue(judge_circle("UDLRUD"))
+ self.assertFalse(judge_circle("LLRU"))
+
+
+class TestStrongPassword(unittest.TestCase):
+ def test_strong_password(self):
+ self.assertEqual(3, strong_password(3, "Ab1"))
+ self.assertEqual(1, strong_password(11, "#Algorithms"))
+
+
+class TestCaesarCipher(unittest.TestCase):
+ def test_caesar_cipher(self):
+ self.assertEqual("Lipps_Asvph!", caesar_cipher("Hello_World!", 4))
+ self.assertEqual("okffng-Qwvb", caesar_cipher("middle-Outz", 2))
+
+
+class TestCheckPangram(unittest.TestCase):
+ def test_check_pangram(self):
+ self.assertTrue(check_pangram("The quick brown fox jumps over the lazy dog"))
+ self.assertFalse(check_pangram("The quick brown fox"))
+
+
+class TestContainString(unittest.TestCase):
+ def test_contain_string(self):
+ self.assertEqual(-1, contain_string("mississippi", "issipi"))
+ self.assertEqual(0, contain_string("Hello World", ""))
+ self.assertEqual(2, contain_string("hello", "ll"))
+
+
+class TestCountBinarySubstring(unittest.TestCase):
+ def test_count_binary_substring(self):
+ self.assertEqual(6, count_binary_substring("00110011"))
+ self.assertEqual(4, count_binary_substring("10101"))
+ self.assertEqual(3, count_binary_substring("00110"))
+
+
+class TestCountBinarySubstring(unittest.TestCase):
+ def test_repeat_string(self):
+ self.assertEqual(3, repeat_string("abcd", "cdabcdab"))
+ self.assertEqual(4, repeat_string("bb", "bbbbbbb"))
+
+
+class TestTextJustification(unittest.TestCase):
+ def test_text_justification(self):
+ self.assertEqual(["This is an",
+ "example of text",
+ "justification. "],
+ text_justification(["This", "is", "an", "example",
+ "of", "text",
+ "justification."], 16)
+ )
+
+ self.assertEqual(["What must be",
+ "acknowledgment ",
+ "shall be "],
+ text_justification(["What", "must", "be",
+ "acknowledgment", "shall",
+ "be"], 16)
+ )
+
+
+class TestMinDistance(unittest.TestCase):
+ def test_min_distance(self):
+ self.assertEqual(2, min_distance("sea", "eat"))
+ self.assertEqual(6, min_distance("abAlgocrithmf", "Algorithmmd"))
+ self.assertEqual(4, min_distance("acbbd", "aabcd"))
+
+class TestMinDistanceDP(unittest.TestCase):
+ def test_min_distance(self):
+ self.assertEqual(2, min_distance_dp("sea", "eat"))
+ self.assertEqual(6, min_distance_dp("abAlgocrithmf", "Algorithmmd"))
+ self.assertEqual(4, min_distance("acbbd", "aabcd"))
+
+
+class TestLongestCommonPrefix(unittest.TestCase):
+ def test_longest_common_prefix(self):
+ # Test first solution
+ self.assertEqual("fl", longest_common_prefix_v1(["flower", "flow",
+ "flight"]))
+ self.assertEqual("", longest_common_prefix_v1(["dog", "racecar",
+ "car"]))
+ # Test second solution
+ self.assertEqual("fl", longest_common_prefix_v2(["flower", "flow",
+ "flight"]))
+ self.assertEqual("", longest_common_prefix_v2(["dog", "racecar",
+ "car"]))
+ # Test third solution
+ self.assertEqual("fl", longest_common_prefix_v3(["flower", "flow",
+ "flight"]))
+ self.assertEqual("", longest_common_prefix_v3(["dog", "racecar",
+ "car"]))
+
+
+class TestFirstUniqueChar(unittest.TestCase):
+ def test_first_unique_char(self):
+ self.assertEqual(0, first_unique_char("leetcode"))
+ self.assertEqual(2, first_unique_char("loveleetcode"))
+
+
+class TestRepeatSubstring(unittest.TestCase):
+ def test_repeat_substring(self):
+ self.assertTrue(repeat_substring("abab"))
+ self.assertFalse(repeat_substring("aba"))
+ self.assertTrue(repeat_substring("abcabcabcabc"))
+
+
+class TestAtbashCipher(unittest.TestCase):
+ """[summary]
+ Test for the file atbash_cipher.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_atbash_cipher(self):
+ self.assertEqual("zyxwvutsrqponml", atbash("abcdefghijklmno"))
+ self.assertEqual("KbgslM", atbash("PythoN"))
+ self.assertEqual("AttaCK at DawN", atbash("ZggzXP zg WzdM"))
+ self.assertEqual("ZggzXP zg WzdM", atbash("AttaCK at DawN"))
+
+
+class TestLongestPalindromicSubstring(unittest.TestCase):
+ """[summary]
+ Test for the file longest_palindromic_substring.py
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+ def test_longest_palindromic_substring(self):
+ self.assertEqual("bb", longest_palindrome("cbbd"))
+ self.assertEqual("abba", longest_palindrome("abba"))
+ self.assertEqual("asdadsa", longest_palindrome("dasdasdasdasdasdadsa"))
+ self.assertEqual("abba", longest_palindrome("cabba"))
+
+
+class TestKnuthMorrisPratt(unittest.TestCase):
+ """[summary]
+ Test for the file knuth_morris_pratt.py
+
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_knuth_morris_pratt(self):
+ self.assertEqual([0, 1, 2, 3, 4], knuth_morris_pratt("aaaaaaa", "aaa"))
+ self.assertEqual([0, 4], knuth_morris_pratt("abcdabc", "abc"))
+ self.assertEqual([], knuth_morris_pratt("aabcdaab", "aba"))
+ self.assertEqual([0, 4], knuth_morris_pratt([0,0,1,1,0,0,1,0], [0,0]))
+
+
+class TestPanagram(unittest.TestCase):
+ """[summary]
+ Test for the file panagram.py
+
+ Arguments:
+ unittest {[type]} -- [description]
+ """
+
+ def test_empty_string(self):
+ # Arrange
+ string = ""
+
+ # Act
+ res = panagram(string)
+
+ # Assert
+ self.assertEqual(False, res)
+
+ def test_single_word_non_panagram(self):
+ # Arrange
+ string = "sentence"
+
+ # Act
+ res = panagram(string)
+
+ # Assert
+ self.assertEqual(False, res)
+
+ def test_fox_panagram_no_spaces(self):
+ # Arrange
+ string = "thequickbrownfoxjumpsoverthelazydog"
+
+ # Act
+ res = panagram(string)
+
+ # Assert
+ self.assertEqual(True, res)
+
+ def test_fox_panagram_mixed_case(self):
+ # Arrange
+ string = "theqUiCkbrOwnfOxjUMPSOVErThELAzYDog"
+
+ # Act
+ res = panagram(string)
+
+ # Assert
+ self.assertEqual(True, res)
+
+ def test_whitespace_punctuation(self):
+ # Arrange
+ string = "\n\t\r,.-_!?"
+
+ # Act
+ res = panagram(string)
+
+ # Assert
+ self.assertEqual(False, res)
+
+ def test_fox_panagram(self):
+ # Arrange
+ string = "the quick brown fox jumps over the lazy dog"
+
+ # Act
+ res = panagram(string)
+
+ # Assert
+ self.assertEqual(True, res)
+
+ def test_swedish_panagram(self):
+ # Arrange
+ string = "Yxmördaren Julia Blomqvist på fäktning i Schweiz"
+
+ # Act
+ res = panagram(string)
+
+ # Assert
+ self.assertEqual(True, res)
+
+
+class TestFizzbuzz(unittest.TestCase):
+ """[summary]
+ Tests for the fizzbuzz method in file fizzbuzz.py
+ """
+ def test_fizzbuzz(self):
+ # Testing that n < 0 returns a Value Error
+ self.assertRaises(ValueError, fizzbuzz.fizzbuzz, -2)
+
+ # Testing that a string returns a Type Error.
+ self.assertRaises(TypeError, fizzbuzz.fizzbuzz, "hello")
+
+ # Testing a base case, n = 3
+ result = fizzbuzz.fizzbuzz(3)
+ expected = [1, 2, "Fizz"]
+ self.assertEqual(result, expected)
+
+ # Testing a base case, n = 5
+ result = fizzbuzz.fizzbuzz(5)
+ expected = [1, 2, "Fizz", 4, "Buzz"]
+ self.assertEqual(result, expected)
+
+ # Testing a base case, n = 15 i.e. mod 3 and 5
+ result = fizzbuzz.fizzbuzz(15)
+ expected = [1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11,
+ "Fizz", 13, 14, "FizzBuzz"]
+ self.assertEqual(result, expected)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_tree.py b/tests/test_tree.py
new file mode 100644
index 000000000..c9d0f0fd4
--- /dev/null
+++ b/tests/test_tree.py
@@ -0,0 +1,180 @@
+from algorithms.tree.traversal import (
+ preorder,
+ preorder_rec,
+ postorder,
+ postorder_rec,
+ inorder,
+ inorder_rec
+)
+from algorithms.tree.b_tree import BTree
+
+from algorithms.tree import construct_tree_postorder_preorder as ctpp
+
+from algorithms.tree.fenwick_tree.fenwick_tree import Fenwick_Tree
+
+import unittest
+
+
+class Node:
+
+ def __init__(self, val, left=None, right=None):
+ self.val = val
+ self.left = left
+ self.right = right
+
+
+class TestTraversal(unittest.TestCase):
+
+ def test_preorder(self):
+ tree = create_tree()
+ self.assertEqual([100, 50, 25, 75, 150, 125, 175], preorder(tree))
+ self.assertEqual([100, 50, 25, 75, 150, 125, 175], preorder_rec(tree))
+
+ def test_postorder(self):
+ tree = create_tree()
+ self.assertEqual([25, 75, 50, 125, 175, 150, 100], postorder(tree))
+ self.assertEqual([25, 75, 50, 125, 175, 150, 100], postorder_rec(tree))
+
+ def test_inorder(self):
+ tree = create_tree()
+ self.assertEqual([25, 50, 75, 100, 125, 150, 175], inorder(tree))
+ self.assertEqual([25, 50, 75, 100, 125, 150, 175], inorder_rec(tree))
+
+
+def create_tree():
+ n1 = Node(100)
+ n2 = Node(50)
+ n3 = Node(150)
+ n4 = Node(25)
+ n5 = Node(75)
+ n6 = Node(125)
+ n7 = Node(175)
+ n1.left, n1.right = n2, n3
+ n2.left, n2.right = n4, n5
+ n3.left, n3.right = n6, n7
+ return n1
+
+
+class TestBTree(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ import random
+ random.seed(18719)
+ cls.random = random
+ cls.range = 10000
+
+ def setUp(self):
+ self.keys_to_insert = [self.random.randrange(-self.range, self.range)
+ for i in range(self.range)]
+
+ def test_insertion_and_find_even_degree(self):
+ btree = BTree(4)
+ for i in self.keys_to_insert:
+ btree.insert_key(i)
+
+ for i in range(100):
+ key = self.random.choice(self.keys_to_insert)
+ self.assertTrue(btree.find(key))
+
+ def test_insertion_and_find_odd_degree(self):
+ btree = BTree(3)
+ for i in self.keys_to_insert:
+ btree.insert_key(i)
+
+ for i in range(100):
+ key = self.random.choice(self.keys_to_insert)
+ self.assertTrue(btree.find(key))
+
+ def test_deletion_even_degree(self):
+ btree = BTree(4)
+ key_list = set(self.keys_to_insert)
+ for i in key_list:
+ btree.insert_key(i)
+
+ for key in key_list:
+ btree.remove_key(key)
+ self.assertFalse(btree.find(key))
+
+ self.assertEqual(btree.root.keys, [])
+ self.assertEqual(btree.root.children, [])
+
+ def test_deletion_odd_degree(self):
+ btree = BTree(3)
+ key_list = set(self.keys_to_insert)
+ for i in key_list:
+ btree.insert_key(i)
+
+ for key in key_list:
+ btree.remove_key(key)
+ self.assertFalse(btree.find(key))
+
+ self.assertEqual(btree.root.keys, [])
+ self.assertEqual(btree.root.children, [])
+
+
+class TestConstructTreePreorderPostorder(unittest.TestCase):
+ def test_construct_tree(self):
+
+ # Test 1
+ ctpp.pre_index = 0
+ pre1 = [1, 2, 4, 8, 9, 5, 3, 6, 7]
+ post1 = [8, 9, 4, 5, 2, 6, 7, 3, 1]
+ size1 = len(pre1)
+
+ self.assertEqual(ctpp.construct_tree(pre1, post1, size1),
+ [8, 4, 9, 2, 5, 1, 6, 3, 7])
+
+ # Test 2
+ ctpp.pre_index = 0
+ pre2 = [1, 2, 4, 5, 3, 6, 7]
+ post2 = [4, 5, 2, 6, 7, 3, 1]
+ size2 = len(pre2)
+
+ self.assertEqual(ctpp.construct_tree(pre2, post2, size2),
+ [4, 2, 5, 1, 6, 3, 7])
+
+ # Test 3
+ ctpp.pre_index = 0
+ pre3 = [12, 7, 16, 21, 5, 1, 9]
+ post3 = [16, 21, 7, 1, 9, 5, 12]
+ size3 = len(pre3)
+
+ self.assertEqual(ctpp.construct_tree(pre3, post3, size3),
+ [16, 7, 21, 12, 1, 5, 9])
+
+
+class TestFenwickTree(unittest.TestCase):
+ def test_construct_tree_with_update_1(self):
+ freq = [2, 1, 1, 3, 2, 3, 4, 5, 6, 7, 8, 9]
+ ft = Fenwick_Tree(freq)
+ bit_tree = ft.construct()
+ self.assertEqual(12, ft.get_sum(bit_tree, 5))
+
+ freq[3] += 6
+ ft.update_bit(bit_tree, 3, 6)
+ self.assertEqual(18, ft.get_sum(bit_tree, 5))
+
+ def test_construct_tree_with_update_2(self):
+ freq = [1, 2, 3, 4, 5]
+ ft = Fenwick_Tree(freq)
+ bit_tree = ft.construct()
+ self.assertEqual(10, ft.get_sum(bit_tree, 3))
+
+ freq[3] -= 5
+ ft.update_bit(bit_tree, 3, -5)
+ self.assertEqual(5, ft.get_sum(bit_tree, 3))
+
+ def test_construct_tree_with_update_3(self):
+ freq = [2, 1, 4, 6, -1, 5, -32, 0, 1]
+ ft = Fenwick_Tree(freq)
+ bit_tree = ft.construct()
+ self.assertEqual(12, ft.get_sum(bit_tree, 4))
+
+ freq[2] += 11
+ ft.update_bit(bit_tree, 2, 11)
+ self.assertEqual(23, ft.get_sum(bit_tree, 4))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_unix.py b/tests/test_unix.py
new file mode 100644
index 000000000..3cafba98f
--- /dev/null
+++ b/tests/test_unix.py
@@ -0,0 +1,48 @@
+from algorithms.unix import (
+ join_with_slash,
+ full_path,
+ split,
+ simplify_path_v1, simplify_path_v2
+)
+import os
+import unittest
+
+
+class TestUnixPath(unittest.TestCase):
+ def test_join_with_slash(self):
+ self.assertEqual("path/to/dir/file",
+ join_with_slash("path/to/dir/", "file"))
+ self.assertEqual("path/to/dir/file",
+ join_with_slash("path/to/dir", "file"))
+ self.assertEqual("http://algorithms/part",
+ join_with_slash("http://algorithms", "part"))
+ self.assertEqual("http://algorithms/part",
+ join_with_slash("http://algorithms/", "part"))
+
+ def test_full_path(self):
+ file_name = "file_name"
+ # Test full path relative
+ expect_path = "{}/{}".format(os.getcwd(), file_name)
+ self.assertEqual(expect_path, full_path(file_name))
+ # Test full path with expanding user
+ # ~/file_name
+ expect_path = "{}/{}".format(os.path.expanduser('~'), file_name)
+ self.assertEqual(expect_path, full_path("~/{}".format(file_name)))
+
+ def test_split(self):
+ # Test url path
+ path = "https://algorithms/unix/test.py"
+ expect_result = split(path)
+ self.assertEqual("https://algorithms/unix", expect_result[0])
+ self.assertEqual("test.py", expect_result[1])
+ # Test file path
+ path = "algorithms/unix/test.py"
+ expect_result = split(path)
+ self.assertEqual("algorithms/unix", expect_result[0])
+ self.assertEqual("test.py", expect_result[1])
+
+ def test_simplify_path(self):
+ self.assertEqual("/", simplify_path_v1("/../"))
+ self.assertEqual("/home/foo", simplify_path_v1("/home//foo/"))
+ self.assertEqual("/", simplify_path_v2("/../"))
+ self.assertEqual("/home/foo", simplify_path_v2("/home//foo/"))
diff --git a/tmp/temporary.md b/tmp/temporary.md
deleted file mode 100644
index 7f1f3247b..000000000
--- a/tmp/temporary.md
+++ /dev/null
@@ -1,29 +0,0 @@
-Given input which is a vector of (user name, log-in time, log-out time),
-output time series which will have number of users logged in at each given
-time slot in the input, output should only contain time slots which are given
-in input for example if the input is "September", 1.2, 4.5),
-("June", 3.1, 6.7), ("August", 8.9, 10.3) output should contain only
-1.2, 3.1, 4.5, 3.1, 6.7, 8.9, 10.3
-Example: /* [ ("September", 1.2, 4.5), ("June", 3.1, 6.7), ("August", 8.9, 10.3) ] =>
-[(1.2, 1), (3.1, 2), (4.5, 1), (6.7, 0), (8.9, 1), (10.3, 0)] */
-
-
-• Sweeping line method
- § record the time instance and it type: log in, log out
- § Sort the time instances. Keep a variable to record the number of logged in users, number
- § For a time instance,
- □ if it is log-in type, number++, print
-else number--, print
-
-
-1. Constant time random access hash implementation
-
-2. Efficient elevator API
-
-3. Ransom note
-
-4. Median of k unsorted arrays
-
-5. Design of a task scheduler
-
-6. Custom comparator
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 000000000..f9182236e
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,63 @@
+[tox]
+envlist =
+ py35
+ py36
+ py37
+ coverage
+
+[testenv]
+passenv = TRAVIS TRAVIS_*
+basepython =
+ py35: python3.5
+ py36: python3.6
+ py37: python3.7
+deps =
+ coverage
+ coveralls
+commands =
+ coverage run --source=tests,algorithms -m unittest discover tests
+ coverage report -m
+ coveralls
+
+[testenv:py35]
+passenv = CI TRAVIS TRAVIS_*
+basepython =
+ python3.5
+deps =
+ pytest
+commands =
+ python3 -m unittest discover tests
+ python3 -m pytest tests
+
+[testenv:py36]
+passenv = CI TRAVIS TRAVIS_*
+basepython =
+ python3.6
+deps =
+ pytest
+commands =
+ python3 -m unittest discover tests
+ python3 -m pytest tests
+
+[testenv:py37]
+passenv = CI TRAVIS TRAVIS_*
+basepython =
+ python3.7
+deps =
+ pytest
+commands =
+ python3 -m unittest discover tests
+ python3 -m pytest tests
+
+[testenv:coverage]
+passenv = CI TRAVIS TRAVIS_*
+skip_install = True
+basepython =
+ python3.7
+commands =
+ coverage run --source=tests,algorithms -m unittest discover tests
+ coverage report -m
+ coveralls
+deps =
+ coverage
+ coveralls
diff --git a/tree.md b/tree.md
deleted file mode 100644
index a4a593c65..000000000
--- a/tree.md
+++ /dev/null
@@ -1,202 +0,0 @@
-.
-├── array
-│ ├── circular_counter.py
-│ ├── flatten.py
-│ ├── garage.py
-│ ├── longest_non_repeat.py
-│ ├── merge_intervals.py
-│ ├── missing_ranges.py
-│ ├── plus_one.py
-│ ├── rotate_array.py
-│ ├── summary_ranges.py
-│ ├── three_sum.py
-│ └── two_sum.py
-├── backtrack
-│ ├── anagram.py
-│ ├── array_sum_combinations.py
-│ ├── combination_sum.py
-│ ├── expression_add_operators.py
-│ ├── factor_combinations.py
-│ ├── general_solution.md
-│ ├── generate_abbreviations.py
-│ ├── generate_parenthesis.py
-│ ├── letter_combination.py
-│ ├── palindrome_partitioning.py
-│ ├── pattern_match.py
-│ ├── permute.py
-│ ├── permute_unique.py
-│ ├── subsets.py
-│ └── subsets_unique.py
-├── bfs
-│ ├── shortest_distance_from_all_buildings.py
-│ └── word_ladder.py
-├── bit
-│ ├── count_ones.py
-│ ├── power_of_two.py
-│ ├── reverse_bits.py
-│ ├── single_number2.py
-│ ├── single_number.py
-│ └── subsets.py
-├── design
-│ ├── alarm_system.md
-│ ├── all_o_one_ds.md
-│ ├── calculator.md
-│ ├── excel_table.md
-│ ├── LRUcache.md
-│ ├── nearby_drivers.md
-│ ├── ride_sharing.md
-│ ├── task_runner.md
-│ └── twitter_feeds.md
-├── dfs
-│ ├── all_factors.py
-│ ├── count_islands.py
-│ ├── pacific_atlantic.py
-│ ├── sudoku_solver.py
-│ └── walls_and_gates.py
-├── dp
-│ ├── buy_sell_stock.py
-│ ├── climbing_stairs.py
-│ ├── combination_sum.py
-│ ├── house_robber.py
-│ ├── longest_increasing.py
-│ ├── max_product_subarray.py
-│ ├── max_subarray.py
-│ ├── num_decodings.py
-│ ├── regex_matching.py
-│ └── word_break.py
-├── graph
-│ ├── clone_graph.py
-│ ├── find_path.py
-│ ├── graph.py
-│ └── traversal.py
-├── heap
-│ ├── merge_sorted_k_lists.py
-│ ├── skyline.py
-│ └── sliding_window_max.py
-├── linkedlist
-│ ├── add_two_numbers.py
-│ ├── copy_random_pointer.py
-│ ├── delete_node.py
-│ ├── first_cyclic_node.py
-│ ├── is_cyclic.py
-│ ├── is_palindrome.py
-│ ├── kth_to_last.py
-│ ├── linkedlist.py
-│ ├── remove_duplicates.py
-│ ├── reverse.py
-│ ├── rotate_list.py
-│ └── swap_in_pairs.py
-├── map
-│ ├── hashtable.py
-│ ├── longest_common_subsequence.py
-│ ├── randomized_set.py
-│ └── valid_sudoku.py
-├── math
-│ ├── generate_strobogrammtic.py
-│ ├── is_strobogrammatic.py
-│ ├── nth_digit.py
-│ └── sqrt_precision_factor.py
-├── matrix
-│ ├── bomb_enemy.py
-│ ├── matrix_rotation.txt
-│ ├── rotate_image.py
-│ ├── sparse_dot_vector.py
-│ ├── sparse_mul.py
-│ └── spiral_traversal.py
-├── queue
-│ ├── __init__.py
-│ ├── max_sliding_window.py
-│ ├── moving_average.py
-│ ├── queue.py
-│ ├── reconstruct_queue.py
-│ └── zigzagiterator.py
-├── README.md
-├── search
-│ ├── binary_search.py
-│ ├── count_elem.py
-│ ├── first_occurance.py
-│ └── last_occurance.py
-├── set
-│ └── randomized_set.py
-├── sort
-│ ├── insertion_sort.py
-│ ├── meeting_rooms.py
-│ ├── merge_sort.py
-│ ├── quick_sort.py
-│ ├── selection_sort.py
-│ ├── sort_colors.py
-│ ├── topsort.py
-│ └── wiggle_sort.py
-├── stack
-│ ├── __init__.py
-│ ├── __init__.pyc
-│ ├── longest_abs_path.py
-│ ├── __pycache__
-│ │ ├── __init__.cpython-35.pyc
-│ │ └── stack.cpython-35.pyc
-│ ├── simplify_path.py
-│ ├── stack.py
-│ ├── stack.pyc
-│ └── valid_parenthesis.py
-├── string
-│ ├── add_binary.py
-│ ├── breaking_bad.py
-│ ├── decode_string.py
-│ ├── encode_decode.py
-│ ├── group_anagrams.py
-│ ├── int_to_roman.py
-│ ├── is_palindrome.py
-│ ├── license_number.py
-│ ├── make_sentence.py
-│ ├── multiply_strings.py
-│ ├── one_edit_distance.py
-│ ├── rabin_karp.py
-│ ├── reverse_string.py
-│ ├── reverse_vowel.py
-│ ├── reverse_words.py
-│ ├── roman_to_int.py
-│ └── word_squares.py
-├── tmp
-│ └── temporary.md
-├── tree
-│ ├── binary_tree_paths.py
-│ ├── bintree2list.py
-│ ├── bst
-│ │ ├── array2bst.py
-│ │ ├── bst_closest_value.py
-│ │ ├── BSTIterator.py
-│ │ ├── delete_node.py
-│ │ ├── is_bst.py
-│ │ ├── kth_smallest.py
-│ │ ├── lowest_common_ancestor.py
-│ │ ├── predecessor.py
-│ │ ├── serialize_deserialize.py
-│ │ ├── successor.py
-│ │ └── unique_bst.py
-│ ├── deepest_left.py
-│ ├── invert_tree.py
-│ ├── is_balanced.py
-│ ├── is_subtree.py
-│ ├── is_symmetric.py
-│ ├── longest_consecutive.py
-│ ├── lowest_common_ancestor.py
-│ ├── max_height.py
-│ ├── max_path_sum.py
-│ ├── min_height.py
-│ ├── path_sum2.py
-│ ├── path_sum.py
-│ ├── pretty_print.py
-│ ├── same_tree.py
-│ ├── traversal
-│ │ ├── inorder.py
-│ │ ├── level_order.py
-│ │ └── zigzag.py
-│ ├── tree.py
-│ └── trie
-│ ├── add_and_search.py
-│ └── trie.py
-├── tree.md
-└── union-find
- └── count_islands.py
-
-26 directories, 173 files
diff --git a/tree/binary_tree_paths.py b/tree/binary_tree_paths.py
deleted file mode 100644
index aad327696..000000000
--- a/tree/binary_tree_paths.py
+++ /dev/null
@@ -1,14 +0,0 @@
-def binaryTreePaths(root):
- res = []
- if not root:
- return res
- DFS(res, root, str(root.val))
- return res
-
-def DFS(res, root, cur):
- if not root.left and not root.right:
- res.append(cur)
- if root.left:
- DFS(res, root.left, cur+'->'+str(root.left.val))
- if root.right:
- DFS(res, root.right, cur+'->'+str(root.right.val))
diff --git a/tree/bst/array2bst.py b/tree/bst/array2bst.py
deleted file mode 100644
index cc147eac2..000000000
--- a/tree/bst/array2bst.py
+++ /dev/null
@@ -1,19 +0,0 @@
-"""
-Given an array where elements are sorted in ascending order,
-convert it to a height balanced BST.
-"""
-# class TreeNode(object):
-# def __init__(self, x):
-# self.val = x
-# self.left = None
-# self.right = None
-
-
-def array2bst(nums):
- if not nums:
- return None
- mid = len(nums)//2
- node = Node(nums[mid])
- node.left = array2bst(nums[:mid])
- node.right = array2bst(nums[mid+1:])
- return node
diff --git a/tree/is_balanced.py b/tree/is_balanced.py
deleted file mode 100644
index 69a420e83..000000000
--- a/tree/is_balanced.py
+++ /dev/null
@@ -1,33 +0,0 @@
-
-def is_balanced(root):
- """
- O(N) solution
- """
- return -1 != get_depth(root)
-
-def get_depth(root):
- """
- return 0 if unbalanced else depth + 1
- """
- if not root:
- return 0
- left = get_depth(root.left)
- right = get_depth(root.right)
- if abs(left-right) > 1:
- return -1
- return 1 + max(left, right)
-
-################################
-
-def is_balanced(root):
- """
- O(N^2) solution
- """
- left = max_height(root.left)
- right = max_height(root.right)
- return abs(left-right) <= 1 and is_balanced(root.left) and is_balanced(root.right)
-
-def max_height(root):
- if not root:
- return 0
- return max(max_height(root.left), max_height(root.right)) + 1
diff --git a/tree/is_subtree.py b/tree/is_subtree.py
deleted file mode 100644
index 9a6c91f95..000000000
--- a/tree/is_subtree.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# Given two binary trees s and t, check if t is a subtree of s.
-# A subtree of a tree t is a tree consisting of a node in t and
-# all of its descendants in t.
-
-# Example 1:
-
-# Given s:
-
- # 3
- # / \
- # 4 5
- # / \
- # 1 2
-
-# Given t:
-
- # 4
- # / \
- # 1 2
-# Return true, because t is a subtree of s.
-
-# Example 2:
-
-# Given s:
-
- # 3
- # / \
- # 4 5
- # / \
- # 1 2
- # /
- # 0
-
-# Given t:
-
- # 3
- # /
- # 4
- # / \
- # 1 2
-# Return false, because even though t is part of s,
-# it does not contain all descendants of t.
-
-# Follow up:
-# What if one tree is significantly lager than the other?
-
-
-def is_subtree(big, small):
- flag = False
- queue = collections.deque()
- queue.append(big)
- while queue:
- node = queue.popleft()
- if node.val == small.val:
- flag = comp(node, small)
- break
- else:
- queue.append(node.left)
- queue.append(node.right)
- return flag
-
-def comp(p, q):
- if not p and not q:
- return True
- if p and q:
- return p.val == q.val and comp(p.left,q.left) and comp(p.right, q.right)
- return False
-
-
diff --git a/tree/longest_consecutive.py b/tree/longest_consecutive.py
deleted file mode 100644
index 498aaa6ca..000000000
--- a/tree/longest_consecutive.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# Given a binary tree, find the length of the longest consecutive sequence path.
-
-# The path refers to any sequence of nodes from some starting node to any node
-# in the tree along the parent-child connections.
-# The longest consecutive path need to be from parent to child
-# (cannot be the reverse).
-
-# For example,
- # 1
- # \
- # 3
- # / \
- # 2 4
- # \
- # 5
-# Longest consecutive sequence path is 3-4-5, so return 3.
- # 2
- # \
- # 3
- # /
- # 2
- # /
- # 1
-
-
-maxlen = 0
-def longestConsecutive(root):
- """
- :type root: TreeNode
- :rtype: int
- """
- if not root:
- return 0
- DFS(root, 0, root.val)
- return maxlen
-
-def DFS(root, cur, target):
- if not root: return
- if root.val == target:
- cur += 1
- else:
- cur = 1
- maxlen = max(cur, maxlen)
- DFS(root.left, cur, root.val+1)
- DFS(root.right, cur, root.val+1)
diff --git a/tree/max_path_sum.py b/tree/max_path_sum.py
deleted file mode 100644
index 48c3e3fbf..000000000
--- a/tree/max_path_sum.py
+++ /dev/null
@@ -1,14 +0,0 @@
-
-maximum = float("-inf")
-
-def max_path_sum(root):
- helper(root)
- return maximum
-
-def helper(root):
- if not root:
- return 0
- left = helper(root.left)
- right = helper(root.right)
- maximum = max(maximum, left+right+root.val)
- return root.val + max(left, right)
diff --git a/tree/pretty_print.py b/tree/pretty_print.py
deleted file mode 100644
index dc58ab3ec..000000000
--- a/tree/pretty_print.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# a -> Adam -> Book -> 4
-# b -> Bill -> Computer -> 5
- # -> TV -> 6
- # Jill -> Sports -> 1
-# c -> Bill -> Sports -> 3
-# d -> Adam -> Computer -> 3
- # Quin -> Computer -> 3
-# e -> Quin -> Book -> 5
- # -> TV -> 2
-# f -> Adam -> Computer -> 7
-
-def treePrint(tree):
- for key in tree:
- print key, # comma prevents a newline character
- treeElem = tree[key] # multiple lookups is expensive, even amortized O(1)!
- for subElem in treeElem:
- print " -> ", subElem,
- if type(subElem) != str: # OP wants indenting after digits
- print "\n " # newline and a space to match indenting
- print "" # forces a newline
diff --git a/union-find/count_islands.py b/union-find/count_islands.py
deleted file mode 100644
index 15cd676ee..000000000
--- a/union-find/count_islands.py
+++ /dev/null
@@ -1,78 +0,0 @@
-"""
-A 2d grid map of m rows and n columns is initially filled with water.
-We may perform an addLand operation which turns the water at position
-(row, col) into a land. Given a list of positions to operate,
-count the number of islands after each addLand operation.
-An island is surrounded by water and is formed by connecting adjacent
-lands horizontally or vertically.
-You may assume all four edges of the grid are all surrounded by water.
-
-Given m = 3, n = 3, positions = [[0,0], [0,1], [1,2], [2,1]].
-Initially, the 2d grid grid is filled with water.
-(Assume 0 represents water and 1 represents land).
-
-0 0 0
-0 0 0
-0 0 0
-Operation #1: addLand(0, 0) turns the water at grid[0][0] into a land.
-
-1 0 0
-0 0 0 Number of islands = 1
-0 0 0
-Operation #2: addLand(0, 1) turns the water at grid[0][1] into a land.
-
-1 1 0
-0 0 0 Number of islands = 1
-0 0 0
-Operation #3: addLand(1, 2) turns the water at grid[1][2] into a land.
-
-1 1 0
-0 0 1 Number of islands = 2
-0 0 0
-Operation #4: addLand(2, 1) turns the water at grid[2][1] into a land.
-
-1 1 0
-0 0 1 Number of islands = 3
-0 1 0
-"""
-
-
-class Solution(object):
- def numIslands2(self, m, n, positions):
- ans = []
- islands = Union()
- for p in map(tuple, positions):
- islands.add(p)
- for dp in (0, 1), (0, -1), (1, 0), (-1, 0):
- q = (p[0] + dp[0], p[1] + dp[1])
- if q in islands.id:
- islands.unite(p, q)
- ans += [islands.count]
- return ans
-
-class Union(object):
- def __init__(self):
- self.id = {}
- self.sz = {}
- self.count = 0
-
- def add(self, p):
- self.id[p] = p
- self.sz[p] = 1
- self.count += 1
-
- def root(self, i):
- while i != self.id[i]:
- self.id[i] = self.id[self.id[i]]
- i = self.id[i]
- return i
-
- def unite(self, p, q):
- i, j = self.root(p), self.root(q)
- if i == j:
- return
- if self.sz[i] > self.sz[j]:
- i, j = j, i
- self.id[i] = j
- self.sz[j] += self.sz[i]
- self.count -= 1
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy