Skip to content

Commit 5ae7a52

Browse files
committed
miguel soln to string rotation 1.9
1 parent 8ad3fff commit 5ae7a52

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
"""
2+
Python version 3.7.0
3+
1.9 - String Rotation
4+
Assume you have a method isSubstring which
5+
checks if one word is a substring
6+
of another. Given two strings, s1 and s2,
7+
write code to check if s2 is a
8+
rotation of s1 using only one call to isSubstring
9+
(e.g. 'waterbottle' is a rotation of 'erbottlewat')
10+
"""
11+
import unittest
12+
13+
14+
def is_substring(sub: str, s: str) -> bool:
15+
"""
16+
is_substring checks if 'sub' is a substring of 's'
17+
:param sub: the substring
18+
:param s: the alleged full string
19+
:return: true if sub is a substring of s, false otherwise
20+
"""
21+
return sub in s
22+
23+
24+
def string_rotation(s1: str, s2: str) -> bool:
25+
"""
26+
Given two strings, string_rotation will check if s2 is a rotation of s1
27+
using only one call to isSubstring.
28+
We will loop through the original string and compare chars of
29+
rotated string. At the first character equality, we will
30+
compare the rest of the original string to the rotated
31+
string's substring of the same length.
32+
If they match, then we save the index of the
33+
rotated string + 1, and if whatever is left of
34+
s1 is a substring of s2, then we must have a
35+
rotation since we compared the complementary part already.
36+
Runtime: Worst case: O(n^2)
37+
Space Complexity: O(1)
38+
:param s1: the rotated string
39+
:param s2: the original string
40+
:return: true if s2 is a rotation of s1, false otherwise
41+
"""
42+
# not rotation if lengths don't match
43+
if len(s1) != len(s2):
44+
return False
45+
# if they match, but both empty, return true
46+
if s1 == '' and s2 == '':
47+
return True
48+
size = len(s1)
49+
start_idx = -1
50+
for i, c in enumerate(s2):
51+
if c != s1[0]:
52+
continue
53+
# check if substring in s2 from i to the end
54+
# matches s1 from beginning to remaining length of s2
55+
if s2[i:] == s1[0:size - i]:
56+
# store starting idx of remaining substring in s2
57+
start_idx = size - i
58+
break
59+
if start_idx == -1:
60+
return False
61+
if is_substring(s1[start_idx:], s2):
62+
return True
63+
return False
64+
65+
66+
class TestStringRotation(unittest.TestCase):
67+
68+
def setUp(self):
69+
self.str_rotation_cases = [
70+
('erbottlewat', 'waterbottle', True),
71+
('erbottlewet', 'weterbottle', True),
72+
('same', 'same', True),
73+
('oneoff', 'oneof', False),
74+
('erbottleabc', 'waterbottle', False),
75+
('ion?rotat', 'rotation?', True),
76+
('', '', True),
77+
('a', 'a', True),
78+
('a', 'b', False),
79+
('erbottlewat', 'eeeeeeeeee', False)
80+
]
81+
82+
self.is_substring_cases = [
83+
('swag', 'swagger', True),
84+
('swagger', 'swag', False),
85+
('test', 'testing', True),
86+
('', 'sdfkjslf', True),
87+
('abcd', 'defg', False)
88+
]
89+
90+
def test_is_substring(self):
91+
for sub, s, expected in self.is_substring_cases:
92+
self.assertEqual(is_substring(sub, s), expected, msg=(sub, s, expected))
93+
94+
def test_string_rotation(self):
95+
for s1, s2, expected in self.str_rotation_cases:
96+
self.assertEqual(string_rotation(s1, s2), expected, msg=(s1, s2, expected))
97+
98+
99+
if __name__ == '__main__':
100+
unittest.main()

0 commit comments

Comments
 (0)