d4d8397e5f
Adds some of the code I generated while studying for a role transfer at Google using the fantastic resource, InterviewCake.com. This work predates the mono-repo. I should think of ways to DRY up this code and the code in crack_the_coding_interview, but I'm afraid I'm creating unnecessary work for myself that way.
181 lines
4.5 KiB
Python
181 lines
4.5 KiB
Python
from collections import deque
|
|
import unittest
|
|
|
|
################################################################################
|
|
# Solution
|
|
################################################################################
|
|
|
|
|
|
def rev(xs, i, j):
|
|
"""Reverse xs in place from [i, j]"""
|
|
while i < j:
|
|
xs[i], xs[j] = xs[j], xs[i]
|
|
i += 1
|
|
j -= 1
|
|
|
|
|
|
def rotate(xs, n, i=None, j=None):
|
|
"""Mutably rotates list, xs, n times. Positive n values rotate right while
|
|
negative n values rotate left. Rotate within window [i, j]."""
|
|
i = i or 0
|
|
j = j or len(xs) - 1
|
|
ct = j - i
|
|
|
|
if n < 0:
|
|
n = abs(n)
|
|
p = i + n - 1
|
|
rev(xs, i, p)
|
|
rev(xs, p + 1, j)
|
|
rev(xs, i, j)
|
|
else:
|
|
p = j - (n - 1)
|
|
rev(xs, p, j)
|
|
rev(xs, i, p - 1)
|
|
rev(xs, i, j)
|
|
return xs
|
|
|
|
|
|
def rev_words(xs, i, j):
|
|
if j + 1 == len(xs):
|
|
return 0
|
|
|
|
while j + 1 < len(xs):
|
|
while j + 1 < len(xs) and xs[j + 1] != ' ':
|
|
j += 1
|
|
|
|
rev(xs, i, j)
|
|
j += 2
|
|
i = j
|
|
|
|
return 0
|
|
|
|
|
|
def reverse_words(xs):
|
|
# first reverse everything
|
|
rev(xs, 0, len(xs) - 1)
|
|
return rev_words(xs, 0, 0)
|
|
|
|
|
|
def reverse_words_bak(xs, i=None, j=None):
|
|
i = i or 0
|
|
j = j or len(xs) - 1
|
|
w0, w1 = [], []
|
|
|
|
if i >= j:
|
|
return 0
|
|
|
|
pi = i
|
|
while pi < len(xs) and xs[pi] != ' ':
|
|
w0.append(xs[pi])
|
|
pi += 1
|
|
|
|
if pi == len(xs):
|
|
return 0
|
|
|
|
pj = j
|
|
while xs[pj] != ' ':
|
|
w1.append(xs[pj])
|
|
pj -= 1
|
|
|
|
d = len(w0) - len(w1)
|
|
|
|
rotate(xs, -1 * d, i, j)
|
|
|
|
for k in range(len(w1)):
|
|
xs[i + k] = w1[len(w1) - 1 - k]
|
|
|
|
for k in range(len(w0)):
|
|
xs[j - k] = w0[len(w0) - 1 - k]
|
|
|
|
while i != j and xs[i] != ' ' and xs[j] != ' ':
|
|
i += 1
|
|
j -= 1
|
|
|
|
if i == j:
|
|
return 0
|
|
|
|
elif xs[i] == ' ':
|
|
while j > 0 and xs[j] != ' ':
|
|
j -= 1
|
|
if j == 0:
|
|
return 0
|
|
elif xs[j] == ' ':
|
|
while i < len(xs) and xs[i] != ' ':
|
|
i += 1
|
|
if i == len(xs):
|
|
return 0
|
|
return reverse_words(xs, i + 1, j - 1)
|
|
|
|
|
|
################################################################################
|
|
# Tests
|
|
################################################################################
|
|
class Test(unittest.TestCase):
|
|
def test_rev(self):
|
|
xs = [1, 2, 3, 4, 5]
|
|
rev(xs, 0, len(xs) - 1)
|
|
self.assertEqual(xs, [5, 4, 3, 2, 1])
|
|
|
|
def test_rotate(self):
|
|
ys = [1, 2, 3, 4, 5]
|
|
xs = ys[:]
|
|
self.assertEqual(rotate(xs, 1, 1, 3), [1, 4, 2, 3, 5])
|
|
xs = ys[:]
|
|
self.assertEqual(rotate(xs, -1, 1, 3), [1, 3, 4, 2, 5])
|
|
xs = ys[:]
|
|
self.assertEqual(rotate(xs, 1), [5, 1, 2, 3, 4])
|
|
xs = ys[:]
|
|
self.assertEqual(rotate(xs, -1), [2, 3, 4, 5, 1])
|
|
xs = ys[:]
|
|
self.assertEqual(rotate(xs, -2), [3, 4, 5, 1, 2])
|
|
xs = ys[:]
|
|
self.assertEqual(rotate(xs, -5), [1, 2, 3, 4, 5])
|
|
xs = ys[:]
|
|
self.assertEqual(rotate(xs, 5), [1, 2, 3, 4, 5])
|
|
xs = ys[:]
|
|
self.assertEqual(rotate(xs, 3), [3, 4, 5, 1, 2])
|
|
|
|
def test_one_word(self):
|
|
message = list('vault')
|
|
reverse_words(message)
|
|
expected = list('vault')
|
|
self.assertEqual(message, expected)
|
|
|
|
def test_two_words(self):
|
|
message = list('thief cake')
|
|
reverse_words(message)
|
|
expected = list('cake thief')
|
|
self.assertEqual(message, expected)
|
|
|
|
def test_three_words(self):
|
|
message = list('one another get')
|
|
reverse_words(message)
|
|
expected = list('get another one')
|
|
self.assertEqual(message, expected)
|
|
|
|
def test_multiple_words_same_length(self):
|
|
message = list('rat the ate cat the')
|
|
reverse_words(message)
|
|
expected = list('the cat ate the rat')
|
|
self.assertEqual(message, expected)
|
|
|
|
def test_multiple_words_different_lengths(self):
|
|
message = list('at rat house')
|
|
reverse_words(message)
|
|
expected = list('house rat at')
|
|
self.assertEqual(message, expected)
|
|
|
|
def test_multiple_words_different_lengths(self):
|
|
message = list('yummy is cake bundt chocolate')
|
|
reverse_words(message)
|
|
expected = list('chocolate bundt cake is yummy')
|
|
self.assertEqual(message, expected)
|
|
|
|
def test_empty_string(self):
|
|
message = list('')
|
|
reverse_words(message)
|
|
expected = list('')
|
|
self.assertEqual(message, expected)
|
|
|
|
|
|
unittest.main(verbosity=2)
|