Skip to content

Commit 564dc72

Browse files
authored
Merge pull request #3 from techqueria/master
merge base repo changes
2 parents c05ab3d + 21e7165 commit 564dc72

File tree

3 files changed

+250
-4
lines changed

3 files changed

+250
-4
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
"""
2+
Python version 3.7.0
3+
1.3 - URLify
4+
Write a method to replace all spaces in a string with "%20".
5+
The following only applies to C/C++: "You may assume that the string has sufficient
6+
space at the end to hold the additional characters, and that you are given the "true" length of the string"
7+
(Note: If implementing in Java, please use a character array so that you can perform this operation in place)
8+
Since we are using python, no need to use true length. I will have two functions, one with
9+
true_length and the other without.
10+
"""
11+
import unittest
12+
from typing import List
13+
14+
15+
def urlify(s: str) -> str:
16+
"""
17+
Given a string, this function will return a new string
18+
that replaces all of the spaces of the input string with '%20'.
19+
:param s: the original string to 'urlify'
20+
:return: string with each space from s replaced with '%20'
21+
"""
22+
buf = ['\x00'] * (len(s) * 3)
23+
for i, c in enumerate(s):
24+
buf[i] = c
25+
26+
def _challenge(buf: List[str], original_length: int) -> None:
27+
"""
28+
Your code here. Challenge rules:
29+
* You can only reference |buf| and |original_length|, not |s|.
30+
* You can only allocate O(1) additional memory
31+
* You need to modify |buf| in-place so that the right answer is returned.
32+
* You cannot modify any part of the wrapper function.
33+
:param buf: buffer containing characters
34+
:param original_length: original length of string
35+
:return: None
36+
"""
37+
space_count = 0
38+
for j in range(original_length):
39+
if buf[j] == ' ':
40+
space_count += 1
41+
42+
chars_per_space = 2
43+
idx = original_length + space_count * chars_per_space
44+
for i in range(original_length-1, -1, -1):
45+
if buf[i] == ' ':
46+
buf[idx-1] = '0'
47+
buf[idx-2] = '2'
48+
buf[idx-3] = '%'
49+
idx -= 3
50+
continue
51+
buf[idx-1] = buf[i]
52+
idx -= 1
53+
_challenge(buf, len(s))
54+
return ''.join(buf).rstrip('\x00')
55+
56+
57+
def urlify_no_true_length(s: str) -> str:
58+
"""
59+
This is the version of urlify without the true_length argument.
60+
Given a string and it's "true" length, this function will return a new string
61+
that replaces all of the spaces of the input string with '%20'.
62+
Note that this will return a different result than the other urlify
63+
if the other urlify's true length truncates the string with chars left over.
64+
Precondition(s):
65+
- length of s <= true_length
66+
:param s: the original string to 'urlify'
67+
:return: string with each space from s replaced with '%20'
68+
"""
69+
output = []
70+
for c in s:
71+
if c == ' ':
72+
output.append("%20")
73+
continue
74+
output.append(c)
75+
return ''.join(output)
76+
77+
78+
class TestUrlifyFunction(unittest.TestCase):
79+
def test_urlify(self):
80+
cases = [
81+
("Mr John Smith", "Mr%20John%20Smith"),
82+
("Miguel Hernandez", "Miguel%20Hernandez"),
83+
(" Techqueria", "%20Techqueria"),
84+
("a b c d e f g h", "a%20b%20c%20d%20e%20f%20g%20h"),
85+
("ihavenospaces", "ihavenospaces"),
86+
("nospaces", "nospaces"),
87+
(" ", "%20")
88+
]
89+
for s, expected in cases:
90+
self.assertEqual(urlify(s), expected, msg=s)
91+
92+
def test_urlify_no_true_length(self):
93+
cases = [
94+
("Mr John Smith", "Mr%20John%20Smith"),
95+
("Miguel Hernandez", "Miguel%20Hernandez"),
96+
(" Techqueria ", "%20Techqueria%20"),
97+
("a b c d e f g h", "a%20b%20c%20d%20e%20f%20g%20h"),
98+
("a b c d e f g h ignore this", "a%20b%20c%20d%20e%20f%20g%20h%20ignore%20this"),
99+
("ihavenospaces", "ihavenospaces"),
100+
("nospacesIgnoreme", "nospacesIgnoreme"),
101+
(" ", "%20")
102+
]
103+
for s, expected in cases:
104+
self.assertEqual(urlify_no_true_length(s), expected, msg=s)
105+
106+
107+
if __name__ == '__main__':
108+
unittest.main()

Python/chapter01/1.4 - PalinPerm/Nick4.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
'''
77

88
import unittest
9-
9+
import collections
1010

1111
def palperm(string):
1212
'''
@@ -15,17 +15,30 @@ def palperm(string):
1515
string (str): a string to check for all palindrome permutations
1616
'''
1717
table = {}
18-
count = 0
1918
for letter in string.lower().replace(" ", ""):
2019
table[letter] = table.get(letter, 0) + 1
2120

21+
count = 0
2222
for key in table:
23-
if count > 1:
24-
return False
2523
if table[key] % 2 == 1:
2624
count += 1
25+
if count > 1:
26+
return False
2727
return True
2828

29+
def palperm2(string):
30+
letter_frequencies = collections.defaultdict(int)
31+
for letter in string.lower().replace(' ', ''):
32+
letter_frequencies[letter] += 1
33+
34+
odd_frequency_count = 0
35+
for frequency in letter_frequencies.values():
36+
if frequency % 2 == 0:
37+
continue
38+
odd_frequency_count += 1
39+
if odd_frequency_count > 1:
40+
return False
41+
return True
2942

3043
class Test(unittest.TestCase):
3144
def test1(self):
@@ -38,5 +51,15 @@ def test1(self):
3851
self.assertTrue(palperm(input_string3))
3952
self.assertTrue(palperm(input_string4))
4053

54+
def test2(self):
55+
input_string ="Tact Coa"
56+
input_string2 ="nick"
57+
input_string3 ="saippuakivikauppias"
58+
input_string4 = "iasppaukivikauppias"
59+
self.assertTrue(palperm2(input_string))
60+
self.assertFalse(palperm2(input_string2))
61+
self.assertTrue(palperm2(input_string3))
62+
self.assertTrue(palperm2(input_string4))
63+
4164
if __name__ == '__main__':
4265
unittest.main()
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
"""
2+
Python version 3.7.0
3+
1.4 - Palindrome Permutation
4+
Given a string, write a function to check if it is a permutation of a palindrome.
5+
A palindrome is a word or phrase that is the same forwards and backwards. A permutation is a
6+
rearrangement of letters. The palindrome does not need to be limited to just dictionary words.
7+
"""
8+
import unittest
9+
import itertools as it
10+
import collections
11+
from typing import Callable
12+
13+
14+
def is_permutation_of_palindrome(s: str) -> bool:
15+
"""
16+
Checks if a string is a palindrome by analyzing the frequencies of characters.
17+
A palindrome is a word or phrase that is the same forwards and backwards.
18+
When determining character frequencies, word will be put to lowercase
19+
and spaces will not be counted
20+
A palindrome also has the following property:
21+
* at most one character appears an odd number of times
22+
Runtime: O(n)
23+
Space Complexity: O(n)
24+
:param s: the string we check, 's' is a possible permutation of a palindrome
25+
:return: true if s is a permutation of a palindrome, false otherwise
26+
"""
27+
char_frequencies = collections.Counter(s.lower().replace(' ', ''))
28+
num_odd_freq_chars = 0
29+
30+
for key, val in char_frequencies.items():
31+
if val % 2 == 0:
32+
continue
33+
num_odd_freq_chars += 1
34+
if num_odd_freq_chars > 1:
35+
return False
36+
return True
37+
38+
39+
def _is_palindrome(s: str) -> bool:
40+
"""
41+
Checks if s is a palindrome by checking if the forward version is the same as the backward version.
42+
A palindrome is a word or phrase that is the same forwards and backwards.
43+
Whitespace will not be considered when determining palindrome.
44+
This function is case insensitive.
45+
Runtime: O(n)
46+
Space Complexity: O(n)
47+
:param s: the string we check, possible permutation of a palindrome
48+
:return: true if s is a palindrome, false otherwise
49+
"""
50+
s_no_spaces = s.replace(' ', '').lower()
51+
reversed_s = s_no_spaces[::-1]
52+
return s_no_spaces == reversed_s
53+
54+
55+
def is_permutation_of_palindrome_brute_force(s: str) -> bool:
56+
"""
57+
Given a string, this function will return whether the string is a permutation of a palindrome.
58+
A palindrome is a word or phrase that is the same forwards and backwards.
59+
A permutation is a rearrangement of letters.
60+
When evaluating whether a string is the same forwards and backwards, we will
61+
omit whitespace. For ex: "taco cat" would not equal "tac ocat" IF we expect a space at the 4th index for
62+
the reversed version. So, the space will not be taken into account only when determining palindrome.
63+
Assuming ASCII
64+
Runtime is O(n!)
65+
Space complexity is O(n)
66+
Given: Expect:
67+
Tact Coa True (permutations: "taco cat", "atco cta")
68+
:param s: the string that we want to check for perm of a palindrome
69+
:return: True if s is a palindrome, False otherwise.
70+
"""
71+
s_no_spaces = s.replace(' ', '')
72+
for p in it.permutations(s_no_spaces):
73+
if _is_palindrome(''.join(p)):
74+
return True
75+
return False
76+
77+
78+
class TestIsPermutationOfPalindromeFunction(unittest.TestCase):
79+
def _run_tests(self, f: Callable[[str], bool]) -> None:
80+
cases = [
81+
("Tact Coa", True),
82+
("car race", True),
83+
("ppilffli", True),
84+
("gwas", False),
85+
("sldkjflks", False),
86+
(" ", True),
87+
("", True),
88+
("a", True)
89+
]
90+
for s, expected in cases:
91+
self.assertEqual(f(s), expected, msg=s)
92+
93+
def test_is_permutation_of_palindrome(self):
94+
self._run_tests(is_permutation_of_palindrome_brute_force)
95+
self._run_tests(is_permutation_of_palindrome)
96+
97+
def test_is_palindrome(self):
98+
cases = [
99+
("Taco Cat", True),
100+
("race car", True),
101+
("flippilf", True),
102+
("swag", False),
103+
("miguel", False),
104+
(" ", True),
105+
("", True),
106+
("a", True),
107+
("Tacoo Cat", True),
108+
("Tacooo Cat", True)
109+
]
110+
for s, expected in cases:
111+
self.assertEqual(_is_palindrome(s), expected, msg=s)
112+
113+
114+
if __name__ == '__main__':
115+
unittest.main()

0 commit comments

Comments
 (0)