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)