Skip to content

Commit

Permalink
[chore] add markdown files for string notebooks
Browse files Browse the repository at this point in the history
  • Loading branch information
gitgik committed Feb 25, 2021
1 parent 613404e commit 1a75dac
Show file tree
Hide file tree
Showing 8 changed files with 471 additions and 0 deletions.
48 changes: 48 additions & 0 deletions strings/caesar_cipher.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
```python
"""Caecar Cipher implementation.
Given a non-empty string of lowercase alphabetic characters, write a function that
takes in the string, and an integer called a key,
And returns a string obtained by shifting every letter of the input string by k positions
in the alphabet, where k is the key.
Sample input: "xyz", 2
Sample output: "zab"
"""


def caesar_cipher_encryptor(string, key):
"""
Complexity:
O(n) space
O(n) time
"""
new_letters = []
new_key = key % 26
for letter in string:
new_letter_code = ord(letter) + new_key
if new_letter_code > 122: # z character code is 122
character = chr(96 + new_letter_code % 122)
new_letters.append(character)
else:
new_letters.append(chr(new_letter_code))

return "".join(new_letters)
```


```python
caesar_cipher_encryptor("xyz", 2)
```




'zab'




```python

```
72 changes: 72 additions & 0 deletions strings/delimiter_order.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
```python
"""
Reverse the words in a string but maintain the relative order of delimiters.
For example:
input = "hello:world/here"
output = "here:world/hello"
"""
import re


def reverse(string, delimiters):
"""Split the words and delimiters into their respective lists.
Then reverse the list of words and merge the two lists together.
Complexity: O(n) time | O(n) space, where n == length of input string.
"""
words = re.split(f"[{delimiters}]+", string)
not_words = re.split(f"[^({delimiters})]+", string)

# remove last empty string if present
if words[-1] == '':
words = words[:-1]

# NOTE: we can in built reverse but there's always another way
# reversed_strings = list(reversed(words))
start = 0
end = len(words) - 1
while start < end:
words[start], words[end] = words[end], words[start]
start += 1
end -= 1

output = []
for index, delimiter in enumerate(not_words):
print(index)
output.append(delimiter)
try:
print(f"adding {words[index]}")
output.append(words[index])
except IndexError:
pass

return ''.join(output)
```


```python
reverse("hello:world/here", ":/")
```

0
adding here
1
adding world
2
adding hello
3





'here:world/hello'




```python

```
56 changes: 56 additions & 0 deletions strings/number_palindrome.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
### Convert Number to palindrome
Given an integer, write a function that returns True if the number can be converted into a palindrome, otherwise return False.

If the conversion steps result in a number bigger than 1 million, return False.


```python
def convertToPalindrome(num):
if isPalindrome(num):
return True

while num < 1000000:
reverted = revert(num)
num = num + reverted
if isPalindrome(num):
return True, num
return False

def revert(num):
"""O(log10 (n) time -- since we are dividing by 10 every time. | O(1) space"""
reverted = 0
while num > 0:
reverted = (reverted * 10 + num % 10)
num //= 10
return reverted

def isPalindrome(x):
if (x % 10 == 0 and x != 0) or x < 0:
return False
reverted = revert(x)
return x == reverted or x == reverted // 10
```


```python
convertToPalindrome(3335)
```




(True, 8668)




```python
convertToPalindrome(95999)
```




False


54 changes: 54 additions & 0 deletions strings/palindrome.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
```python
""""All the ways to implement a palindrom checker.
Check if the string is a palindrome, return True, otherwise, return False.
A palindrome is defined as a string that is written the same forward and backward.
"""


def is_palindrome1(string):
"""
Complexity:
O(n) space
O(n) time
"""
reversed_char = []
for i in reversed(range(len(string))):
reversed_char.append(string[i])
return string == "".join(reversed_char)


def is_palindrome_best(string):
"""
Complexity:
O(1) space
O(n) time
"""
left_index = 0
right_index = len(string) - 1

while left_index < right_index:
if string[left_index] != string[right_index]:
return False
left_index += 1
right_index -= 1
return True


def is_palindrome2(string, i = 0):
"""
Recursive implementation.
Complexity:
O(n) space
O(n) time
"""
j = len(string) - 1 - i
return True if i >= j else string[i] == string[j] and is_palindrome2(string, i + 1)
```


```python

```
57 changes: 57 additions & 0 deletions strings/parenthesis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
## Count invalid parenthesis

Given a string of parentheses, write a function to find the minimum number of parentheses to be removed to make the string valid (i.e. each open parenthesis is eventually closed).

For example, given the string "()())()", you should return 1. Given the string ")(", you should return 2, since we must remove all of them.

### Approach
For each opening parenthesis to be considered valid, they should eventually be matched with an closing parenthesis. If not, they are counted as invalid.
Whenever we encounter an unmatched closing parenthesis, we count as invalid. Eventually, we'll add the unmatched open count to the invalid one.


```python
def count_invalid_parenthesis(string) -> int:
invalid = 0
opened = 0

for char in string:
if char == "(":
opened += 1
elif char == ")":
if opened > 0:
opened -= 1
else:
invalid += 1
return invalid + opened
```


```python
count_invalid_parenthesis("((()(())")
```




2




```python
count_invalid_parenthesis("()()()")
```




0



This solution runs at O(N) time, where N = number of characters in the string.


```python

```
56 changes: 56 additions & 0 deletions strings/reverse_mutable_string.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
```python
def reverse(array, start, end):
"""Reverse characters in a string from start to end(inclusive)."""
while start < end:
array[start], array[end] = array[end], array[start]
start += 1
end -= 1


def reverse_mutable_string(string_list):
"""
This function performs a reverse operation on a mutable string in-place.
(saving on space)
Since strings are immutable, a mutable string can be represented
as a list of characters in a buffer e.g
['h','e','l','l','o',' ','w','o','r','l','d']) == 'hello world'
Approach: First, we reverse entire string to get 'dlrow olleh',
then we reverse each word within the string to obtain original words.
Worst-case complexity:
Time: O(n)
Space: O(1) - since the input memory location is overwritten by the
output as we reverse the string as the algorithm executes.
"""
# reverse entire string
reverse(string_list, 0, len(string_list) - 1)
# reverse each word in the string
start = 0
for end in range(len(string_list)):
if string_list[end] == " ":
reverse(string_list, start, end - 1)
start = end + 1

# reverse last word since we stopped at the last white space in the list
# remember, there are characters after the white space.
reverse(string_list, start, len(string_list) - 1)
return string_list
```


```python
reverse_mutable_string(['h','e','l','l','o',' ','w','o','r','l','d'])
```




['w', 'o', 'r', 'l', 'd', ' ', 'h', 'e', 'l', 'l', 'o']




```python

```
46 changes: 46 additions & 0 deletions strings/reverse_string_words.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
## Problem

Given a string of words delimited by spaces, reverse the words in string. For example, given "hello world here", return "here world hello"

Follow-up: given a mutable string representation, can you perform this operation in-place?

### Approach

Since strings are immutable, a mutable string can be represented as a list of characters in a buffer e.g `['h','e','l','l','o',' ','w','o','r','l','d']` == 'hello world'

First we reverse entire string to get `'dlrow olleh'`, then we reverse each word within the string to obtain original words.


```python
def reverse(string_list: list, start: int, end: int) -> str:
while start < end:
string_list[start], string_list[end] = string_list[end], string_list[start]
start += 1
end -= 1

def reverse_words(string_list: list) -> str:
reverse(string_list, 0, len(string_list) - 1)
start = 0
for i in range(len(string_list)):
if string_list[i] == " ":
reverse(string_list, start, i - 1)
start = i + 1
# we need to reverse the last sub-string
reverse(string_list, start, len(string_list) - 1)
return "".join(string_list)
```


```python
string_list = list("well hello there")
reverse_words(string_list)
```




'there hello well'




Loading

0 comments on commit 1a75dac

Please sign in to comment.