Exemple #1
0
def test_intersects__yes():
    left = LinkedList([1, 2, 3, 4, 5])
    element = left[3]

    right = LinkedList([1, 2])
    right.append(element)

    assert intersects(left, right) == element
Exemple #2
0
def partition(ll, p):
    """
    Admittedly, much of the implementation magic here is making sure that the
    basic dunder method __add__ to join two linked lists works correctly.  I
    also rewrote the LinkedList initializer slightly to make use of a new
    append method that appends an Element to the end of a LinkedList and
    adjusts the prev/next pointers and the tail pointer correctly.
    """
    left = LinkedList([])
    right = LinkedList([])
    for value in ll.values:
        element = Element(value)
        if value < p:
            left.append(element)
        else:
            right.append(element)

    return left + right
Exemple #3
0
def sum(left, right, reverse=True):
    """
    Summation of digits may "carry over" a value to the next digit place.

    When evaluating the linked list, it's simple to just take the carry along
    the traversal of both left and right in tandem, and apply it to the next
    digit place.  If one list terminates before the other, the carry gets
    applied just the same until the traversal ends for the longer list.  This
    algorithm runs in O(M+N) time where M, N is the length of left, right
    respectively.  The sum of each individual element can be applied into a new
    element and just appended to a new linked list.

    The non-reversed case is a bit trickier, and requires special handling for
    the possibility of non-equal list lengths, as we can't assume the first
    elements are the same digit place.  Once we determine the maximum length,
    we can use a hash to store each digit place keyed by power of 10.  Using
    the hash allows us to keep the runtime to O(M+N) at the cost of
    O(max(M, N)) space.  Other methods involve complicated back-tracking with
    pointers, or using a stack which is essentially the first method.

    The non-reserved solution avoids fun workarounds like reversing the linked
    list and running the first algorithm, or converting the LinkedList into
    numbers, summing those, and then converting the number into a string and
    then passing it directly into LinkedList... :rolling_on_the_floor_laughing:
    """
    result = LinkedList([])
    if reverse:
        current_left = left.head
        current_right = right.head

        carry = 0
        while current_left is not None and current_right is not None:
            left_value = 0
            if current_left is not None:
                left_value = current_left.value
                current_left = current_left.next

            right_value = 0
            if current_right is not None:
                right_value = current_right.value
                current_right = current_right.next

            total = left_value + right_value + carry
            carry = total // 10
            digit = total % 10
            result.append(Element(digit))

        if carry > 0:
            result.append(Element(carry))
    else:
        # this is needed here in case there is carry past the max digit place
        places = defaultdict(lambda: 0)

        for ll in [left, right]:
            for index, element in enumerate(ll):
                place = len(ll) - index - 1
                places[place] += element.value

        for place in sorted(places.keys()):
            carry = places[place] // 10
            places[place] %= 10
            if carry > 0:
                places[place + 1] += carry

        for place in sorted(places.keys(), reverse=True):
            result.append(Element(places[place]))

    return result