git-subtree-dir: users/wpcarro git-subtree-mainline:464bbcb15cgit-subtree-split:24f5a642afChange-Id: I6105b3762b79126b3488359c95978cadb3efa789
		
			
				
	
	
		
			114 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import unittest
 | 
						|
 | 
						|
 | 
						|
################################################################################
 | 
						|
# InterviewCake's solution
 | 
						|
################################################################################
 | 
						|
def cycle_len(xs, i):
 | 
						|
    """
 | 
						|
    Returns the length of a cycle that contains no duplicate items.
 | 
						|
    """
 | 
						|
    result = 1
 | 
						|
    checkpt = i
 | 
						|
    current = xs[checkpt - 1]
 | 
						|
 | 
						|
    while current != checkpt:
 | 
						|
        current = xs[current - 1]
 | 
						|
        result += 1
 | 
						|
 | 
						|
    return result
 | 
						|
 | 
						|
 | 
						|
def theirs(xs):
 | 
						|
    """
 | 
						|
    This is InterviewCake's solution.
 | 
						|
    """
 | 
						|
    i = xs[-1]
 | 
						|
    for _ in range(len(xs) - 1):
 | 
						|
        i = xs[i - 1]
 | 
						|
 | 
						|
    cycle_length = cycle_len(xs, i)
 | 
						|
 | 
						|
    p0 = xs[-1]
 | 
						|
    p1 = xs[-1]
 | 
						|
    for _ in range(cycle_length):
 | 
						|
        p1 = xs[p1 - 1]
 | 
						|
 | 
						|
    while p0 != p1:
 | 
						|
        p0 = xs[p0 - 1]
 | 
						|
        p1 = xs[p1 - 1]
 | 
						|
 | 
						|
    print(p0, p1)
 | 
						|
 | 
						|
    return p0
 | 
						|
 | 
						|
 | 
						|
################################################################################
 | 
						|
# My solution
 | 
						|
################################################################################
 | 
						|
def mine(xs):
 | 
						|
    """
 | 
						|
    This is the solution that I came up with, which differs from InterviewCake's
 | 
						|
    solution.
 | 
						|
    """
 | 
						|
    i = xs[-1]
 | 
						|
    offset = 1 if len(xs) % 2 == 0 else 2
 | 
						|
 | 
						|
    for _ in range(len(xs) - offset):
 | 
						|
        i = xs[i - 1]
 | 
						|
 | 
						|
    return i
 | 
						|
 | 
						|
 | 
						|
use_mine = True
 | 
						|
find_duplicate = mine if use_mine else theirs
 | 
						|
 | 
						|
 | 
						|
# Tests
 | 
						|
class Test(unittest.TestCase):
 | 
						|
    def test_just_the_repeated_number(self):
 | 
						|
        # len(xs) even
 | 
						|
        actual = find_duplicate([1, 1])
 | 
						|
        expected = 1
 | 
						|
        self.assertEqual(actual, expected)
 | 
						|
 | 
						|
    def test_short_list(self):
 | 
						|
        # len(xs) even
 | 
						|
        actual = find_duplicate([1, 2, 3, 2])
 | 
						|
        expected = 2
 | 
						|
        self.assertEqual(actual, expected)
 | 
						|
 | 
						|
    def test_medium_list(self):
 | 
						|
        # len(xs) even
 | 
						|
        actual = find_duplicate([1, 2, 5, 5, 5, 5])
 | 
						|
        expected = 5
 | 
						|
        self.assertEqual(actual, expected)
 | 
						|
 | 
						|
    def test_long_list(self):
 | 
						|
        # len(xs) odd
 | 
						|
        actual = find_duplicate([4, 1, 4, 8, 3, 2, 7, 6, 5])
 | 
						|
        expected = 4
 | 
						|
        self.assertEqual(actual, expected)
 | 
						|
 | 
						|
    ############################################################################
 | 
						|
    # Additional examples from InterviewCake.com
 | 
						|
    ############################################################################
 | 
						|
    def test_example_a(self):
 | 
						|
        # len(xs) even
 | 
						|
        actual = find_duplicate([3, 4, 2, 3, 1, 5])
 | 
						|
        expected = 3
 | 
						|
        self.assertTrue(actual, expected)
 | 
						|
 | 
						|
    def test_example_b(self):
 | 
						|
        # len(xs) even
 | 
						|
        actual = find_duplicate([3, 1, 2, 2])
 | 
						|
        expected = 2
 | 
						|
        self.assertEqual(actual, expected)
 | 
						|
 | 
						|
    def test_example_c(self):
 | 
						|
        # len(xs) odd BUT multiple duplicates
 | 
						|
        actual = find_duplicate([4, 3, 1, 1, 4])
 | 
						|
        self.assertTrue(actual in {1, 4})
 | 
						|
 | 
						|
 | 
						|
unittest.main(verbosity=2)
 |