Python is not recognizing null in a list - python

I am new in Python and I have a question. What should I put in line 5? I want to see if the character c doesn't exist in groups, then I want to create one and assign it to 0. And then, increase it as much as this character has appeared
def firstUniqChar(self, s):
groups = {}
for i in range(0, len(s) - 1):
c = s[i]
if groups[c] == null:
groups[c] = 0
else:
groups[c] = groups[c] + 1
for j in range(0, len(s) - 1):
if groups[s[i]] == 1:
return j
return -1

Rather than null you need to write None in python.
You can write it like
if groups[c] is None:

Related

Removing substring from string in Python

I want to write a function that takes 2 inputs: a string and a substring, then the function will remove that part of the substring from the string.
def remove_substring(s, substr):
"""(str, str) -> NoneType
Returns string without string substr
remove_substring_from_string("Im in cs", "cs")
Im in
"""
other_s = ''
for substr in s:
if substr in s:
continue
How do I continue on from here? Assuming my logic is sound.
Avoiding the use of Python functions.
Method 1
def remove_substring_from_string(s, substr):
'''
find start index in s of substring
remove it by skipping over it
'''
i = 0
while i < len(s) - len(substr) + 1:
# Check if substring starts at i
if s[i:i+len(substr)] == substr:
break
i += 1
else:
# break not hit, so substr not found
return s
# break hit
return s[:i] + s[i+len(substr):]
Method 2
If the range function can be used, the above can be written more compactly as follows.
def remove_substring_from_string(s, substr):
'''
find start index in s of substring
remove it by skipping over it
'''
for i in range(len(s) - len(substr) + 1):
if s[i:i+len(substr)] == substr:
break
else:
# break not hit, so substr not found
return s
return s[:i] + s[i+len(substr):]
Test
print(remove_substring_from_string("I have nothing to declare except my genuis", " except my genuis"))
# Output: I have nothing to declare'
This approach is based on the KMP algorithm:
def KMP(s):
n = len(s)
pi = [0 for _ in range(n)]
for i in range(1, n):
j = pi[i - 1]
while j > 0 and s[i] != s[j]:
j = pi[j - 1]
if s[i] == s[j]:
j += 1
pi[i] = j
return pi
# Removes all occurences of t in s
def remove_substring_from_string(s, t):
n = len(s)
m = len(t)
# Calculate the prefix function using KMP
pi = KMP(t + '\x00' + s)[m + 1:]
r = ""
i = 0
while i + m - 1 < n: # Before the remaining string is smaller than the substring
if pi[i + m - 1] == m: # If the substring is here, skip it
i += m
else: # Otherwise, add the current character and move to the next
r += s[i]
i += 1
# Add the remaining string
r += s[i:]
return r
It runs in O(|s| + |t|), but it has a few downsides:
The code is long and unintuitive.
It requires that there is no null (\x00) in the input strings.
Its constant factors are pretty bad for short s and t.
It doesn't handle overlapping strings how you might want it: remove_substring_from_string("aaa", "aa") will return "a". The only guarantee made is that t in remove_substring_from_string(s, t) is False for any two strings s and t.
A C++ example and further explanation for the KMP algorithm can be found here. The remove_substring_from_string function then only checks if the entire substring is matched at each position and if so, skips over the substring.
I would do this using re.
import re
def remove_substring(s, substr):
# type: (str, str) -> str
return re.subn(substr, '', s)[0]
remove_substring('I am in cs', 'cs')
# 'I am in '
remove_substring('This also removes multiple substr that are found. Even if that substr is repeated like substrsubstrsubstr', 'substr')
# 'This also removes multiple that are found. Even if that is repeated like '
def remove_substring(s, substr):
while s != "":
if substr in s:
s = s.replace(substr, "")
else:
return s
if s == "":
return "Empty String"
The idea here is that we replace all occurrences of substr within s, by replacing the first instance of substr and then looping until we are done.

How can i remove the break from find_frequent(s) code since our teacher told us we can't use it on the test and I'm trying to practice not using it?

I wrote this code, and I'm struggling to replace using break since it says in the homework that we are not allowed to use continue/break statements in our loops.
The code's goal is:
finds the character that appears most frequently in the input parameter string and returns it. For Example, if the string is "Canada day" the function returns the string "a"
If there are two characters or more with the same frequency, the function should return the first of many values with the same frequency.
def find_frequent(s):
"""
-------------------------------------------------------
description
Use:
-------------------------------------------------------
Parameters:
name - description (type)
Returns:
name - description (type)
------------------------------------------------------
"""
L = []
count = 0
char = 0
i = 0
words = True
while i < 1 and words:
x = s[i]
for j in range(len(L)):
if x == L[j]:
words = False
L[j + 1] = L[j + 1] + 1
else:
L.append(x)
L.append(1)
for i in range(1, len(L), 2):
if L[i] > count:
count = L[i]
char = L[i - 1]
return char
the output should look like this
`Enter a string: Hello Hi`
output should be
`Most frequent characters: H`
I'm getting this output
Enter a string: canada
Most frequent character: c
You can replace the break statement in a for loop with a while loop.
print("using for loop + break")
for i in range(0, 5):
print(i)
if i == 3:
break
print("using while")
i = 0
keep_searching = True
while i < 5 and keep_searching:
print(i)
if i == 3:
keep_searching = False
i += 1
The output is:
using for loop + break
0
1
2
3
using while
0
1
2
3
I think you can figure it out from here, but if you need help with finding the most frequent character (a different issue from the break), take a look here and here.
No need for a break if you don't use a loop in the first place :-)
def find_frequent(s):
return max(s, key=s.count)
(I'm actually serious... forbidding break sounds to me like your teacher didn't want you to write it with such nested loops.)
Or if you want to teach your teacher a lesson (the lesson being that they shouldn't forbid stuff), you could fake the break:
for i in range(0, len(s), 1):
x = s[i]
it = iter(range(len(L))) # make it an iterator
for j in it:
if x == L[j]:
L[j + 1] = L[j + 1] + 1
*it, # exhaust the iterator
it = None # make it false
if it: # instead of `else`
L.append(x)
L.append(1)

For loop stores old variable value?

I am trying to implement ZigZag from LeetCode. Somehow during the second recursive call my second for loop within "addElements" retains the value from the last call. Why does this happen?
I have shared the output below - my question is in regards to how beg and end stay the same value until 3, then beg moves to 6 as expected but end remains at 3.
https://leetcode.com/problems/zigzag-conversion/
class Solution:
def convert(self, s: str, numRows: int) -> str:
row = [''] * len(s)
self.s = s
self.numRows = numRows
self.final_grid = []
for i in range(numRows):
self.final_grid.append(list(row))
self.addElements(0, 0)
final_arr = []
for i in self.final_grid:
final_arr += i
final_word = ''
for i in final_arr:
if i != "":
final_word += i
return (final_word)
def addElements(self, count, column):
print(column, "beg")
for i in range(self.numRows):
if count > len(self.s) - 1:
break
self.final_grid[i][column] = self.s[count]
count += 1
for i in range(1, self.numRows - 1):
if count > len(self.s) - 1:
break
self.final_grid[self.numRows - i - 1][column + i] = self.s[count]
count += 1
print(column, "end")
self.addElements(count, column + self.numRows - 1)
INPUT: "PAYPALISHIRING" 4
STDOUT:
0 beg
0 end
3 beg
3 end
6 beg
3 end **why does this stay at 3?
6 beg
0 end
3 beg
3 end
6 beg
3 end
6 beg
Output: "PINALSIGYAHRGPIG"
Expected: "PINALSIGYAHRPI"
The problem appears to be this block:
for i in range(1, self.numRows - 1):
if count > len(self.s) - 1:
break
self.final_grid[self.numRows - i - 1][column + i] = self.s[count]
count += 1
print(column, "end")
self.addElements(count, column + self.numRows - 1)
Here, you are recursing for every element in the loop. You probably meant:
def addElements(self, count, column):
for i in range(self.numRows):
if count >= len(self.s):
return # <-- return instead of break
self.final_grid[i][column] = self.s[count]
count += 1
for i in range(1, self.numRows - 1):
if count >= len(self.s):
return # <-- return instead of break
self.final_grid[self.numRows-i-1][column+i] = self.s[count]
count += 1
self.addElements(count, column + self.numRows - 1)
#^^^ move this outside of the loop
With these changes, the output matches expected: "PINALSIGYAHRPI". The code is still a bit awkward and the various conditionals are strangely placed, doing double duty as pre/post conditions, so I'd consider a re-write.
Caveat: I've only taken a look at this problem and I'm not vouching that this code will work on the remainder of the tests. For one, it uses a huge amount of memory, so there is likely a way to build the result without creating a giant n x m array. There are other minor inefficiencies, like building the result array character by character, then building the result string from the array (runs in quadratic time because strings are immutable).
Instead of:
final_arr = []
for i in self.final_grid:
final_arr += i
final_word = ''
for i in final_arr:
if i != "":
final_word += i
return (final_word)
use:
return "".join(map("".join, self.final_grid))
Instead of:
row = [''] * len(s)
consider:
row = [''] * ((len(s) // 2) + 1)
Because the last element of the for loop stores the last variable.
To make so that you don't have that variable type del variable if you try to use that variable without reassigning a new value, it will throw an error

count an occurrence of a string in a bigger string

I am looking to understand what I can do to make my code to work. Learning this concept will probably unlock a lot in my programming understanding. I am trying to count the number of times the string 'bob' occurs in a larger string. Here is my method:
s='azcbobobegghakl'
for i in range(len(s)):
if (gt[0]+gt[1]+gt[2]) == 'bob':
count += 1
gt.replace(gt[0],'')
else:
gt.replace(gt[0],'')
print count
How do I refer to my string instead of having to work with integers because of using for i in range(len(s))?
Try this:
def number_of_occurrences(needle, haystack, overlap=False):
hlen, nlen = len(haystack), len(needle)
if nlen > hlen:
return 0 # definitely no occurrences
N, i = 0, 0
while i < hlen:
consecutive_matching_chars = 0
for j, ch in enumerate(needle):
if (i + j < hlen) and (haystack[i + j] == ch):
consecutive_matching_chars += 1
else:
break
if consecutive_matching_chars == nlen:
N += 1
# if you don't need overlap, skip 'nlen' characters of 'haystack'
i += (not overlap) * nlen # booleans can be treated as numbers
i += 1
return N
Example usage:
haystack = 'bobobobobobobobobob'
needle = 'bob'
r = number_of_occurrences(needle, haystack)
R = haystack.count(needle)
print(r == R)
thanks. your support help to birth the answer in. here what I have :
numBobs = 0
for i in range(1, len(s)-1):
if s[i-1:i+2] == 'bob':
numBobs += 1
print 'Number of times bob occurs is:', numBobs

Recursion Pascal's Triangle (Python)

I'm not sure what I'm doing wrong with my code here in getting a recursive pascal's triangle to work in python. Any help is kindly appreciated :)
n = 5
def printPascal(n):
Pascal_List = []
if n == 0:
Pascal_List.append([1])
return Pascal_List
if n == 1:
Pascal_List.append([1])
Pascal_List.append([1,1])
return Pascal_List
else:
new_row = [1]
final_r = printPascal(n - 1)
last_row = final_r[-1]
for k in range(1, last_row[-1]):
new_row.append(final_r[k] + final_r[k - 1])
new_row += last_row
final_r.append(new_row)
return final_r
print(printPascal(n))
You've made a few confusions in the loop that builds a new line. range(1, last_row[-1]) doesn't really make sense; you want to iterate over the indices of the last row, ie range(len(last_row)). You've also mixed up final_r and last_row on the next line.
Here is a corrected version of your code :
n = 5
def printPascal(n):
Pascal_List = []
if n == 0:
Pascal_List.append([1])
return Pascal_List
if n == 1:
Pascal_List.append([1])
Pascal_List.append([1,1])
return Pascal_List
else:
new_row = [1]
final_r = printPascal(n - 1)
last_row = final_r[-1]
for k in range(len(last_row)-1):
new_row.append(last_row[k] + last_row[k + 1])
new_row.append(1)
final_r.append(new_row)
return final_r
print(printPascal(n))
There is a better method to do this using the general formula for Pascal's triangle (n choose k), but I will not go into that.
Looking at your code, I'm guessing you are trying to add the previous two numbers from the previous row to get the next number.
Change replace with this in your else condition:
#It should be length instead.
for k in range(1, len(last_row)):
new_row.append(last_row[k] + last_row[k - 1])
#You need to add the 1 at the end
new_row.append(1)
#zale already explained the problem with your for loop, no need to repeat that. However, note that you can make your code a good deal simpler:
no need for the special treatment of the n == 1 case
you can make the second part much simpler by padding the last line with zeros
Try this:
def printPascal(n):
if n == 0:
return [[1]]
else:
final_r = printPascal(n - 1)
last = [0] + final_r[-1] + [0] # note: this does not modify final_r
new_row = [last[k] + last[k - 1] for k in range(1, len(last))]
return final_r + [new_row]

Categories

Resources