Beispiel #1
0
def question_1():
    print('##### Sorted Merge #####\n')

    def version_1(test):
        ((A, size_A, B), expected) = test

        ix_A = size_A - 1
        ix_B = len(B) - 1
        ix_merged = ix_A + ix_B + 1 # or size_A + len(B) - 1

        while ix_B >= 0:
            if (ix_A >= 0) and (A[ix_A] > B[ix_B]):
                A[ix_merged] = A[ix_A]
                ix_A -= 1
            else:
                A[ix_merged] = B[ix_B]
                ix_B -= 1
            ix_merged -= 1

        return A == expected

    tests = [
        (([1, 2, 3, None, None, None], 3, [4, 5, 6]), [1, 2, 3, 4, 5, 6]),
        (([4, 5, 6, None, None, None], 3, [1, 2, 3]), [1, 2, 3, 4, 5, 6]),
        (([1, 4, 5, 19, None, None, None], 4, [2, 13, 30]), [1, 2, 4, 5, 13, 19, 30])
    ]

    for test in tests:
        for version in range(1, 2):
            test_question("version %d => {} merged with {} equals to {}" % version,
                          [test[0][0][0 : test[0][1]], test[0][2], test[1]],
                          locals()['version_%d' % version](test))
        print()
Beispiel #2
0
def question_4():
    print('##### Queue via Stacks #####\n')

    # time: O(N); space: O(N)
    def version_1(test):
        forward_stack = Stack()
        backward_stack = Stack()

        for t in test:
            forward_stack.push(t)

        while not forward_stack.is_empty():
            backward_stack.push(forward_stack.pop())

        result = ''.join(backward_stack.to_array())

        return test == result

    tests = [
        '',
        'abcdefghijklmnopqrstuvwxyz',
        'abcdefghijklmnopqrstuvwxyza',
        'aabbcc',
        'mdifnafanfa',
        'aifasoid',
        'zyxvwutsrqponmlkjihgfedcba'
    ]

    for test in tests:
        for version in range(1, 2):
            test_question("version %d => '{}' inserted in queue" % version,
                          [test],
                          locals()['version_%d' % version](test))
        print()
Beispiel #3
0
def question_1():
    print('##### Is Unique #####\n')

    # time: O(N**2); space: O(1)
    # no additional structures used
    def version_1(test):
        (given, expected) = test

        size = len(given)

        for i in range(size):
            for j in range(i + 1, size):
                if given[i] == given[j]:
                    return expected == False

        return expected == True

    # time: O(N); space: O(N)
    # using a hash set
    def version_2(test):
        (given, expected) = test

        chars = set()

        for t in given:
            if t in chars:
                return expected == False
            chars.add(t)

        return expected == True

    # time: O(N); space: O(1)
    # using a bit mask (hint 117; considers only lowercase letters)
    def version_3(test):
        (given, expected) = test

        mask = 0

        for t in given:
            vector = 1 << (ord(t) - 97)
            if (mask & vector) == vector:
                return expected == False
            mask = mask | vector

        return expected == True

    tests = [('', True), ('abcdefghijklmnopqrstuwvxyz', True),
             ('abcdefghijklmnopqrstuwvxyza', False), ('aabbcc', False),
             ('mdifnafanfa', False), ('aifasoid', False),
             ('zyxvwutsrqponmlkjihgfedcba', True)]

    for test in tests:
        for version in range(1, 4):
            test_question("version %d => '{}' is {}unique" % version,
                          [test[0], '' if test[1] else 'NOT '],
                          locals()['version_%d' % version](test))
        print()
Beispiel #4
0
def question_2():
    print('##### Stack Min #####\n')

    # time: O(N); space: O(N)
    def version_1(test):
        class ItemWithMin(Item):

            def __init__(self, value):
                super(ItemWithMin, self).__init__(value)
                self.my_min = value

            def check_min(self):
                if self.below and self.below.my_min < self.my_min:
                    self.my_min = self.below.my_min

        class StackWithMin(Stack):

            def __init__(self):
                super(StackWithMin, self).__init__()

            def push(self, value):
                super(StackWithMin, self).push(value, constructor=ItemWithMin)
                self.top.check_min()

            def min(self):
                if self.is_empty():
                    return None

                return self.top.my_min

        (given_seq, num_pops, expected) = test

        stack = StackWithMin()

        for s in given_seq:
            stack.push(s)
        for _ in range(num_pops):
            stack.pop()

        return stack.min() == expected

    tests = [
        (list(), 1, None),
        ([-5, -4, -3, -2, -1, 0, 1, 2, 3, 4], 0, -5),
        ([4, 3, 2, 1, 0, -1, -2, -3, -4, -5], 0, -5),
        ([-2, -3, 4, 0, 3, 1, -1, 2, -4, -5], 1, -4),
        ([-2, -3, 4, 0, 3, 1, -1, 2, -4, -5], 2, -3)
    ]

    for test in tests:
        for version in range(1, 2):
            test_question("version %d => {}, after {} pops, min is {}" % version,
                          [test[0], test[1], test[2]],
                          locals()['version_%d' % version](test))
        print()
Beispiel #5
0
def question_5():
    print('##### Sum Lists #####\n')

    # time: O(N) (where N is the longer input); space O(N)
    def version_1(test):
        (given, expected) = test

        (A, _) = create_linked_list(
            given[0])  # not considered in the O(.) function calculation
        (B, _) = create_linked_list(
            given[1])  # not considered in the O(.) function calculation
        carry_on = 0

        head_C = tail_C = None

        while True:
            val_A = A.value if A else 0
            val_B = B.value if B else 0
            result = val_A + val_B + carry_on
            carry_on = 0
            if result > 9:
                result = result - 10
                carry_on = 1

            # has something to insert?
            if result > 0 or carry_on > 0:
                if tail_C:
                    tail_C.next = LinkedListNode(result)
                    tail_C = tail_C.next
                else:
                    head_C = tail_C = LinkedListNode(result)
            else:
                break

            if A:
                A = A.next
            if B:
                B = B.next

        C = reduce_linked_list_to_list(
            head_C)  # not considered in the O(.) function calculation
        return C == expected

    tests = [(([7, 1, 6], [5, 9, 2]), [2, 1, 9]),
             (([7, 8, 9], [5, 9, 2]), [2, 8, 2, 1]),
             (([7, 8, 8, 4], [5, 9, 7]), [2, 8, 6, 5])]

    for test in tests:
        for version in range(1, 2):
            test_question("version %d => {} + {} = {}" % version,
                          [test[0][0], test[0][1], test[1]],
                          locals()['version_%d' % version](test))
        print()
Beispiel #6
0
def question_2():
    print('##### Check Permutation #####\n')

    # time: O(A*logA + B*logB); space: O(A + B)
    # Python uses Timsort, with worst cases: O(N*logN) and O(N) for time and space, respectively
    def version_1(test):
        (A, B, expected) = test

        if len(A) != len(B):
            return expected == False

        return expected == (sorted(A) == sorted(B))

    # time: O(len(A)); space: O(len(A))
    # worst case complexity only happens when A and B have the same length
    def version_2(test):
        (A, B, expected) = test

        if len(A) != len(B):
            return expected == False

        stats_A = dict()
        stats_B = dict()

        for i in range(len(A)):
            A_i = A[i]
            if A_i not in stats_A:
                stats_A[A_i] = 0
            stats_A[A_i] += 1

            B_i = B[i]
            if B_i not in stats_B:
                stats_B[B_i] = 0
            stats_B[B_i] += 1

        return expected == (stats_A == stats_B)

    tests = [('', '', True), ('aabbcc', 'abc', False),
             ('abcaa', 'abcaa', True), ('abc', 'bca', True),
             ('abc', 'bda', False), ('aabccc', 'aabccccccc', False)]

    for test in tests:
        for version in range(1, 3):
            test_question(
                "version %d => '{}' is {}permutation of '{}'" % version,
                [test[0], '' if test[2] else 'NOT ', test[1]],
                locals()['version_%d' % version](test))
        print()
Beispiel #7
0
def question_2():
    print('##### Group Anagrams #####\n')

    # time: # O(N*W*logW) (N = #word and W = avg size of a word)
    def version_1(test):
        (given, expected) = test

        anagrams = dict()
                                        # O(N*W*logW)
        for word in given:              # O(N)
            sorted_word = list(word)
            merge_sort(sorted_word)     # O(W*logW)
            sorted_word = ''.join(sorted_word)

            if sorted_word in anagrams:
                anagrams[sorted_word].append(word)
            else:
                anagrams[sorted_word] = [word]

        keys = list(anagrams.keys())
        merge_sort(keys)

        sorted_words = list()

                                        # O(N*W*logW)
        for key in keys:                # O(1..N/p..N) (#keys <= N and p = #words/key)
            merge_sort(anagrams[key])   # O(W*logW)
            for word in anagrams[key]:  # O(N..p..1) (p = #words/key)
                sorted_words.append(word)

        return sorted_words == expected

    tests = [
        (['anagram', 'arara', 'aaagmnr', 'nagaram', 'arraa', 'ate', 'eta', 'eat'],
            ['aaagmnr', 'anagram', 'nagaram', 'arara', 'arraa', 'ate', 'eat', 'eta']),
        (['listen', 'admirer', 'silent', 'paternal', 'parental', 'married'],
            ['parental', 'paternal', 'admirer', 'married', 'listen', 'silent'])
    ]

    for test in tests:
        for version in range(1, 2):
            test_question("version %d => {} sorted to {}" % version,
                          [test[0], test[1]],
                          locals()['version_%d' % version](test))
        print()
Beispiel #8
0
def question_1():
    print('##### Remove Dups #####\n')

    # time: O(N); space: O(N)
    def version_1(test):
        given = test[0]
        expected = test[1]

        (head, _) = create_linked_list(
            given)  # not considered in the O(.) function calculation

        chars = set()

        if head:
            chars.add(head.value)
            prev = head
            node = head.next
            while node:
                if node.value in chars:  # 1st time
                    prev.next = node.next
                else:
                    chars.add(node.value)
                    prev = node

                node = node.next

        output = reduce_linked_list_to_str(
            head)  # not considered in the O(.) function calculation

        return output == expected

    tests = [('', ''), ('abcdee', 'abcde'), ('abcddefacdlkasdlk', 'abcdeflks'),
             ('abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'),
             ('abcdeyzabcd', 'abcdeyz')]

    for test in tests:
        for version in range(1, 2):
            test_question("version %d => '{}' becomes '{}'" % version,
                          [test[0], test[1]],
                          locals()['version_%d' % version](test))
        print()
Beispiel #9
0
def question_2():
    print('##### Run Kth to Last #####\n')

    # time: O(N); space O(1)
    def version_1(test):
        given = test[0]
        k = test[1]
        expected = test[2]

        (head, _) = create_linked_list(
            given)  # not considered in the O(.) function calculation

        node = head
        num_nodes = 0
        while node:
            num_nodes += 1
            node = node.next

        node = None
        if 0 < k <= num_nodes:
            num_nodes = num_nodes - k
            node = head
            while num_nodes > 0:
                node = node.next
                num_nodes -= 1

            return node.value == expected

        return node == expected

    tests = [(list(), 1, None), ([1, 2, 3], 3, 1), ([1, 2, 3], 0, None),
             ([4, 3, 2, 1], 1, 1), ([4, 3, 2, 1], 4, 4), ([4, 3, 2,
                                                           1], 5, None)]

    for test in tests:
        for version in range(1, 2):
            test_question("version %d => k = {}, in list {} is {}" % version,
                          [test[1], test[0], test[2]],
                          locals()['version_%d' % version](test))
        print()
Beispiel #10
0
def question_3():
    print('##### Delete Middle Node #####\n')

    # time: O(N); space: O(1)
    def version_1(test):
        given = test[0]
        value = test[1]
        expected = test[2]

        (head, _) = create_linked_list(
            given)  # not considered in the O(.) function calculation

        if head:
            prev = head
            node = head.next
            while node:
                if node.value == value and node.next:  # node.next avoids matching the tail
                    prev.next = node.next
                    break

                prev = node
                node = node.next

        output = reduce_linked_list_to_str(
            head)  # not considered in the O(.) function calculation

        return output == expected

    tests = [('', 'a', ''), ('abcdef', 'c', 'abdef'),
             ('abcdef', 'a', 'abcdef'), ('abcdef', 'f', 'abcdef'),
             ('abbbf', 'b', 'abbf')]

    for test in tests:
        for version in range(1, 2):
            test_question(
                "version %d => '{}' after removal of '{}' becomes '{}'" %
                version, [test[0], test[1], test[2]],
                locals()['version_%d' % version](test))
        print()
Beispiel #11
0
def question_0():
    print('##### Merge Sort #####\n')

    def version_1(test):
        (given, expected) = test

        sorted_given = given[:] # doesn't enter in the O(.) calculation
        merge_sort(sorted_given)

        return sorted_given == expected

    tests = [
        ([6, 3, 1, 7, 2, 8, 5, 4], [1, 2, 3, 4, 5, 6, 7, 8]),
        ([1, 2, 3, 4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7, 8]),
        ([8, 7, 6, 5, 4, 3, 2, 1], [1, 2, 3, 4, 5, 6, 7, 8])
    ]

    for test in tests:
        for version in range(1, 2):
            test_question("version %d => {} sorted to {}" % version,
                          [test[0], test[1]],
                          locals()['version_%d' % version](test))
        print()
Beispiel #12
0
def question_6():
    print('##### String Compression #####\n')

    # time: O(N) or O(N*d), where O(d) is the order to turn int into string; space: O(N)
    def version_1(test):
        given = test[0]
        expected = test[1]

        compressed = ''
        cur = prev = given[0]
        i = freq = 0

        while i <= len(given):
            cur = given[i] if i < len(given) else None
            if i < len(given) and cur == prev:
                freq += 1
            else:
                compressed = '{}{}{}'.format(compressed, prev, freq)
                freq = 1

            prev = cur
            i += 1

        final = compressed if len(compressed) < len(given) else given

        return final == expected

    tests = [('abc', 'abc'), ('aabbcc', 'aabbcc'), ('aabbccc', 'a2b2c3'),
             ('aabcccccaaa', 'a2b1c5a3')]

    for test in tests:
        for version in range(1, 2):
            test_question("version %d => '{}' is compressed to '{}'" % version,
                          [test[0], test[1]],
                          locals()['version_%d' % version](test))
        print()
Beispiel #13
0
def question_9():
    print('##### String Rotation #####\n')

    # time: O(N); space: O(N) (considering the indexed strings must be copied)
    def version_1(test):
        given = test[0]
        rotated = test[1]
        expected = test[2]

        if len(given) != len(rotated):
            return False == expected

        for i in range(len(given)):
            i_comp = len(rotated) - i

            if given[i:] == rotated[:i_comp] and rotated[i_comp:] == given[:i]:
                return True == expected

        return False == expected

    def version_2(test):
        given = test[0]
        rotated = test[1]
        expected = test[2]

        if len(given) != len(rotated):
            return False == expected

        i = j = 0
        found_first_equal = False
        while j < len(rotated):
            g = given[i]
            e = rotated[j]

            i = (i + 1) % len(given)

            if g == e:
                found_first_equal = True
                j += 1

                if j > len(given):
                    return False == expected

            if found_first_equal and (g != e):
                return False == expected

        return True == expected

    tests = [('waterbottle', 'erbottlewat', True),
             ('waterbottle', 'erbottlehov', False),
             ('waterbottle', 'bottlewater', True),
             ('waterbottle', 'bottlehover', False),
             ('waterbottle', 'bottlewaters', False),
             ('waterbottle', 'erbottlewaterbottlewat', False),
             ('erbottlewaterbottlewat', 'waterbottle', False),
             ('erbottlewaterbottlewat', 'erbottlewat', False)]

    for test in tests:
        for version in range(1, 3):
            test_question(
                "version %d => '{}' is {}a rotation of '{}'" % version,
                [test[0], '' if test[2] else 'NOT ', test[1]],
                locals()['version_%d' % version](test))
        print()
Beispiel #14
0
def question_3():
    print('##### Stack of Plates #####\n')

    class SetOfStacks(object):

        def __init__(self, threshold):
            self.threshold = threshold
            self.stacks = list()
            self.cur_stack_index = -1;

        def push(self, value):
            if self.cur_stack_index < 0:
                self.stacks.append(Stack())
                self.cur_stack_index = 0

            cur_stack = self.stacks[self.cur_stack_index]

            if cur_stack.size == self.threshold:
                cur_stack = Stack()
                self.stacks.append(cur_stack)
                self.cur_stack_index += 1

            cur_stack.push(value)

        def pop(self):
            if self.cur_stack_index < 0:
                return None

            cur_stack = self.stacks[self.cur_stack_index]

            value = cur_stack.pop()

            if cur_stack.is_empty():
                self.stacks.remove(cur_stack)
                self.cur_stack_index -= 1

            return value

        def to_array_list(self):
            arrays = list()

            for stack in self.stacks:
                arrays.append(stack.to_array())

            return arrays

    # time: O(?); space: O(N)
    def version_1(test):
        (given_seq, threshold, num_pops, expected) = test

        set_of_stacks = SetOfStacks(threshold)
        for s in given_seq:
            set_of_stacks.push(s)

        for _ in range(num_pops):
            set_of_stacks.pop()

        return set_of_stacks.to_array_list() == expected

    tests = [
        (range(1, 11), 3, 0, [[3, 2, 1], [6, 5, 4], [9, 8, 7], [10]]),
        (range(1, 11), 5, 0, [[5, 4, 3, 2, 1], [10, 9, 8, 7, 6]]),
        (range(1, 11), 3, 2, [[3, 2, 1], [6, 5, 4], [8, 7]])
    ]

    for test in tests:
        for version in range(1, 2):
            test_question("version %d => {} stacked into {} stacks of max size {} and equal to {} after {} pops" % version,
                          [list(test[0]), len(test[3]), test[1], test[3], test[2]],
                          locals()['version_%d' % version](test))
        print()
Beispiel #15
0
def question_7():
    print('##### Rotate Matrix #####\n')

    def version_1(test):
        given = test[0]
        expected = test[1]

        size = len(given)
        middled = int(size / 2)

        end = size - 1
        for i in range(middled):
            for j in range(i, end - i):
                upper_left_line = i
                upper_left_column = j % size
                upper_left_value = given[upper_left_line][upper_left_column]

                bottom_left_line = end - j
                bottom_left_column = i % size
                given[upper_left_line][upper_left_column] = given[
                    bottom_left_line][bottom_left_column]

                bottom_right_line = end - i
                bottom_right_column = end - j
                given[bottom_left_line][bottom_left_column] = given[
                    bottom_right_line][bottom_right_column]

                upper_right_line = j
                upper_right_column = end - i
                given[bottom_right_line][bottom_right_column] = given[
                    upper_right_line][upper_right_column]

                given[upper_right_line][upper_right_column] = upper_left_value

        return given == expected

    tests = [([['1-1']], [['1-1']]),
             ([['1-1', '1-2', '1-3', '1-4'], ['2-1', '2-2', '2-3', '2-4'],
               ['3-1', '3-2', '3-3', '3-4'],
               ['4-1', '4-2', '4-3', '4-4']], [['4-1', '3-1', '2-1', '1-1'],
                                               ['4-2', '3-2', '2-2', '1-2'],
                                               ['4-3', '3-3', '2-3', '1-3'],
                                               ['4-4', '3-4', '2-4', '1-4']]),
             ([['1-1', '1-2', '1-3', '1-4', '1-5'],
               ['2-1', '2-2', '2-3', '2-4', '2-5'],
               ['3-1', '3-2', '3-3', '3-4', '3-5'],
               ['4-1', '4-2', '4-3', '4-4', '4-5'],
               ['5-1', '5-2', '5-3', '5-4',
                '5-5']], [['5-1', '4-1', '3-1', '2-1', '1-1'],
                          ['5-2', '4-2', '3-2', '2-2', '1-2'],
                          ['5-3', '4-3', '3-3', '2-3', '1-3'],
                          ['5-4', '4-4', '3-4', '2-4', '1-4'],
                          ['5-5', '4-5', '3-5', '2-5', '1-5']])]

    for test in tests:
        for version in range(1, 2):
            test_question(
                "version %d =>\nmatrix\n\n {}\nrotated to\n\n {}\n" % version,
                [show_matrix(test[0]),
                 show_matrix(test[1])],
                locals()['version_%d' % version](test))
        print()
Beispiel #16
0
def question_5():
    print('##### One Away #####\n')

    # time: O(N), where N is the size of the smaller string; space: O(1)
    def version_1(test):
        original = test[0]
        edited = test[1]
        expected = test[2]

        diff_len = len(original) - len(edited)

        if diff_len == 0:  # possible replace
            num_diffs = 0

            # time: O(N)
            for i in range(len(original)):
                if original[i] != edited[i]:
                    num_diffs += 1
                if num_diffs > 1:
                    return False == expected

            return True == expected

        elif diff_len == 1:  # possible removal
            i = j = 0

            # time: O(N), where N is the length of edited
            while (i < len(original)) and (j < len(edited)):
                if original[i] == edited[j]:
                    j += 1
                i += 1

                if i - j == 2:
                    return False == expected

            return True == expected

        elif diff_len == -1:  # possible insertion
            i = j = 0

            # time: O(N), where N is the length of original
            while (i < len(original)) and (j < len(edited)):
                if original[i] == edited[j]:
                    i += 1
                j += 1

                if i - j == -2:
                    return False == expected

            return True == expected

        return False == expected

    # time: O(N), where N is the size of the smaller string; space: O(1)
    def version_2(test):
        original = test[0]
        edited = test[1]
        expected = test[2]

        diff_len = len(original) - len(edited)

        if diff_len == 0:  # possible replace
            num_diffs = 0

            # time: O(N)
            for i in range(len(original)):
                if original[i] != edited[i]:
                    num_diffs += 1
                if num_diffs > 1:
                    return False == expected

            return True == expected

        elif (diff_len == 1) or (diff_len
                                 == -1):  # possible removal or insertion
            i = j = 0

            while (i < len(original)) and (j < len(edited)):
                if original[i] == edited[j]:
                    i += 1
                    j += 1
                else:
                    if diff_len == 1:
                        i += 1
                    else:
                        j += 1

                if (diff_len == 1 and i - j == 2) or (diff_len == -1
                                                      and i - j == -2):
                    return False == expected

            return True == expected

        return False == expected

    # time: O(N), where N is the size of the smaller string; space: O(1)
    def version_3(test):
        original = test[0]
        edited = test[1]
        expected = test[2]

        diff_len = len(original) - len(edited)

        if diff_len < -1 or diff_len > 1:
            return False == expected

        num_diffs = i = j = 0
        while (i < len(original)) and (j < len(edited)):
            if diff_len == 0:
                if original[i] != edited[i]:
                    num_diffs += 1
                if num_diffs > 1:
                    return False == expected

                i += 1
                j += 1
            else:
                if original[i] == edited[j]:
                    i += 1
                    j += 1
                else:
                    if diff_len == 1:
                        i += 1
                    else:
                        j += 1

                if (diff_len == 1 and i - j == 2) or (diff_len == -1
                                                      and i - j == -2):
                    return False == expected

        return True == expected

    tests = [('pale', 'ple', True), ('pales', 'pale', True),
             ('pales', 'bale', False), ('pale', 'bale', True),
             ('pale', 'bake', False), ('ball', 'balls', True),
             ('ball', 'ballss', False), ('ball', 'calls', False),
             ('ball', 'cball', True), ('ball', 'cballss', False),
             ('ball', 'call', True)]

    for test in tests:
        for version in range(1, 4):
            test_question("version %d => '{}' is {}one way to '{}'" % version,
                          [test[0], '' if test[2] else 'NOT ', test[1]],
                          locals()['version_%d' % version](test))
        print()
Beispiel #17
0
def question_4():
    print('##### Palindrome Permutation #####\n')

    # time: O(N); space: O(N)
    # using hash sets
    def version_1(test):
        (given, expected) = test

        odds = set()
        evens = set()

        given = given.lower()  # O(N)
        for t in given:
            c = ord(t)
            if ord('a') <= c <= ord('z'):
                if c in odds:
                    odds.remove(c)
                    evens.add(c)
                elif c in evens:
                    evens.remove(c)
                    odds.add(c)
                else:  # 1st time
                    odds.add(c)

        return (len(odds) <= 1) == expected

    # time: O(N); space: O(1)
    # using bit masks
    def version_2(test):
        (given, expected) = test

        odds = 0
        evens = 0

        given = given.lower()  # O(N)
        for t in given:
            c = ord(t)
            if ord('a') <= c <= ord('z'):
                vec = 1 << (c - 97)
                if (odds & vec) == vec:
                    odds = odds ^ vec
                    evens = evens | vec
                elif (evens & vec) == vec:
                    evens = evens ^ vec
                    odds = odds | vec
                else:
                    odds = odds | vec

        num_odds_bits = 0
        for i in range(ord('z') - ord('a') + 1):
            vec = 1 << i
            if (odds & vec) == vec:
                num_odds_bits += 1
            if num_odds_bits > 1:
                return False == expected

        return (num_odds_bits <= 1) == expected

    tests = [('Tact Coa', True), ('arara', True), ('casa', False), ('', True),
             ('palindrome', False), ('Madam I\'m Adam', True),
             ('Madam I am Adam', False), ('coco', True)]

    for test in tests:
        for version in range(1, 3):
            test_question(
                "version %d => '{}' does {}have palindrome permutation" %
                version, [test[0], '' if test[1] else 'NOT '],
                locals()['version_%d' % version](test))
        print()
Beispiel #18
0
def question_3():
    print('##### URLify #####\n')

    # time: O(length); space: O(N)
    def version_1(test):
        chars = list(test[0])  # doesn't count in the O(.) calculation
        length = test[1]
        expected = test[2]

        output = [''] * len(chars)

        j = 0
        for i in range(length):
            c = chars[i]
            if c == ' ':
                output[j] = '%'
                output[j + 1] = '2'
                output[j + 2] = '0'
                j += 3
            else:
                output[j] = c
                j += 1

        chars = ''.join(output)  # doesn't count in the O(.) calculation

        return chars == expected

    # time: O(length); space: O(1)
    # replaces ' ' by '%20' in place (assuming it has enough space after the word)
    def version_2(test):
        chars = list(test[0])  # doesn't count in the O(.) calculation
        length = test[1]
        expected = test[2]

        i = length - 1
        j = len(chars) - 1
        while i >= 0:
            c = chars[i]
            if c == ' ':
                chars[j] = '0'
                chars[j - 1] = '2'
                chars[j - 2] = '%'
                j -= 3
            else:
                chars[j] = c
                j -= 1

            i -= 1

        chars = chars[j + 1:]
        chars = ''.join(chars)  # doesn't count in the O(.) calculation

        return chars == expected

    tests = [('Mr John Smith        ', 13, 'Mr%20John%20Smith'),
             (' Mr   John Smith                 ', 18,
              '%20Mr%20%20%20John%20Smith%20%20'), ('        ', 2, '%20%20'),
             ('    ', 0, ''),
             ('Mr   John Smith            ', 15, 'Mr%20%20%20John%20Smith')]

    for test in tests:
        for version in range(1, 3):
            test_question(
                "version %d => '{}' URLfied first {} chars to '{}'" % version,
                [test[0], test[1], test[2]],
                locals()['version_%d' % version](test))
        print()
Beispiel #19
0
def question_5():
    print('##### Sort Stack #####\n')
    # just use insertion sort

    # time: O(N^2); space: O(N)
    def version_1(test):
        (given, expected) = test

        original_stack = Stack()
        sorted_stack = Stack()

        for g in given:
            original_stack.push(g)

        # starts here

        while not original_stack.is_empty():
            pivot = original_stack.pop()

            while (not sorted_stack.is_empty()) and (pivot < sorted_stack.peek()):
                original_stack.push(sorted_stack.pop())
            sorted_stack.push(pivot)

        # sorts in reverse order (smallest on top)
        while not sorted_stack.is_empty():
            original_stack.push(sorted_stack.pop())

        given_str = ''.join(original_stack.to_array()) # doesn't count in the O(.) calculation
        return given_str == expected

    # time: O(N^2); space: O(N)
    def version_2(test):
        (given, expected) = test

        original_stack = Stack()
        sorted_stack = Stack()

        for g in given:
            original_stack.push(g)

        # starts here

        num_eltos = original_stack.size

        for i in range(num_eltos):
            pivot = original_stack.pop()

            num_swaps = 0
            while (not sorted_stack.is_empty()) and (pivot < sorted_stack.peek()):
                original_stack.push(sorted_stack.pop())
                num_swaps += 1
            sorted_stack.push(pivot)

            for _ in range(num_swaps):
                sorted_stack.push(original_stack.pop())

        # sorts in reverse order (smallest on top)
        while not sorted_stack.is_empty():
            original_stack.push(sorted_stack.pop())

        given_str = ''.join(original_stack.to_array()) # doesn't count in the O(.) calculation
        return given_str == expected

    tests = [
        ('', ''),
        ('abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'),
        ('zyxvwutsrqponmlkjihgfedcba', 'abcdefghijklmnopqrstuvwxyz'),
        ('wqhrgacdzbmsnlvukjfpteixoy', 'abcdefghijklmnopqrstuvwxyz')
    ]

    for test in tests:
        for version in range(1, 3):
            test_question("version %d => '{}' sorted as '{}'" % version,
                          [test[0], test[1]],
                          locals()['version_%d' % version](test))
        print()
Beispiel #20
0
def question_8():
    print('##### Loop Detection #####\n')

    # time: O(N); space: O(N)
    def version_1(test):
        (given, point, expected) = test

        (head, tail) = create_linked_list(given)

        if point:
            node = head
            cur = 0
            while cur < point:
                node = node.next
                cur += 1

            tail.next = point = node

        # begins here

        visited = set()
        node = head

        while node:
            if node in visited:
                return True == expected

            visited.add(node)
            node = node.next

        return False == expected

    # time: O(N); space: O(1)
    def version_2(test):
        (given, point, expected) = test

        (head, tail) = create_linked_list(given)

        if point:
            node = head
            cur = 0
            while cur < point:
                node = node.next
                cur += 1

            tail.next = point = node

        # begins here

        node_A = node_B = head

        while node_A and node_B:
            if (node_A == node_B) and (node_A != head):
                return True == expected

            node_A = node_A.next
            node_B = node_B.next
            if node_B:
                node_B = node_B.next

        return False == expected

    tests = [(['A', 'B', 'C', 'D', 'E', 'F'], None, False),
             (['A', 'B', 'C', 'D', 'E'], 2, True)]

    for test in tests:
        for version in range(1, 3):
            test_question("version %d => {} is {}circular" % version,
                          [test[0], '' if test[2] else 'NOT '],
                          locals()['version_%d' % version](test))
        print()