from single_linked_list import Node, LinkedList

def is_palindrome(self):
    fast = self.head
    slow = self.head
    stack = []

    while fast and fast.next:
        fast = fast.next.next
        slow = slow.next
        stack.append(slow.val)

    if not fast:
        stack.pop()

    slow = slow.next
    while slow and stack.pop() == slow.val:
        slow = slow.next
    return (True if not slow else False)

setattr(LinkedList, 'is_palindrome', is_palindrome)

val_list_1 = [1, 2, 3, 4, 5]
linked_list_1 = LinkedList.from_val_list(val_list_1)
print linked_list_1.is_palindrome()
val_list_2 = [1, 2, 3, 2, 1]
linked_list_2 = LinkedList.from_val_list(val_list_2)
print linked_list_2.is_palindrome()
from single_linked_list import Node, LinkedList


def is_palindrome(self):
    fast = self.head
    slow = self.head
    stack = []

    while fast and fast.next:
        fast = fast.next.next
        slow = slow.next
        stack.append(slow.val)

    if not fast:
        stack.pop()

    slow = slow.next
    while slow and stack.pop() == slow.val:
        slow = slow.next
    return (True if not slow else False)


setattr(LinkedList, 'is_palindrome', is_palindrome)

val_list_1 = [1, 2, 3, 4, 5]
linked_list_1 = LinkedList.from_val_list(val_list_1)
print linked_list_1.is_palindrome()
val_list_2 = [1, 2, 3, 2, 1]
linked_list_2 = LinkedList.from_val_list(val_list_2)
print linked_list_2.is_palindrome()
from single_linked_list import Node, LinkedList

def kth_to_last(self, k):
    fast = self.head
    slow = self.head
    for i in xrange(k):
        fast = fast.next

    while fast.next:
        fast = fast.next
        slow = slow.next

    return slow

setattr(LinkedList, 'kth_to_last', kth_to_last)

val_list = [1, 2, 3, 4, 5]
linked_list = LinkedList.from_val_list(val_list)
print linked_list
k = 2
print 'the {k}th to last is {node}'.format(k=k, node=linked_list.kth_to_last(k))
from single_linked_list import Node, LinkedList

def loop_head(self):
    fast = self.head
    slow = self.head
    while fast and fast.next:
        fast = fast.next.next
        slow = slow.next
        if fast == slow:
            break
    if not fast or not fast.next:
        return None
    
    p0 = self.head
    p1 = fast
    while p0 != p1:
        p0 = p0.next
        p1 = p1.next
    return p0

setattr(LinkedList, 'loop_head', loop_head)

val_list = [1, 2, 3, 4, 5]
linked_list = LinkedList.from_val_list(val_list)
linked_list.last().next = linked_list.head.next.next.next
print linked_list.loop_head().val