Strings in python 3.7 - python-3.x

How to count sub-strings in a string?
Example: findSubstrings("foxcatfox","fox") # should return 2

If recursion is really a must, you can try dividing the problem first.
Say if you found a matching substring at position i, then the total number of substring is 1 + findSub(string[i+1:], sub), so you can write something like this:
def findSubstringsRecursive(string, substring):
counter = 0
substringLength = len(substring)
for i in range(len(string)):
if string[i] == substring[0]:
end = i + substringLength
sub1 = string[i:end]
if substring == sub1:
return 1 + findSubstringsRecursive(string[i+1:], substring)
return 0

The following pure recursive approach is simple enough (apart from the bool->int coercion):
def findRec(s, pat):
if len(s) < len(pat): # base case should be obvious
return 0
return (pat == s[:len(pat)]) + findRec(s[1:], pat) # recurse with smaller size
>>> findSubstrings('foxcatfox', 'fox')
2
>>> findSubstrings('foxcatfox', 'foxc')
1
>>> findSubstrings('foxcat', 'dog')
0
I should note that this counts overlapping occurrences which may or may not be desired. One might also add protection against or define behaviour for an empty substring.

Related

How do I write a python function to count consecutive zeros in a binary representation of a number?

Given a number N, the function should convert the number to binary form, count the number of consecutive zero (the binary gap), and return the maximum binary gap. For example, 9 = 1001, the binary gap of length 2. The number 529 = 1000010001, has 2 binary gaps with length 4 and 3. If the number has 2 or more binary gaps, the function should return the maximum binary gap i.e. 4 in the case of N = 529.
I tried this function:
def solution(N):
binaryN = bin(N)[2:]
n = len(binaryN)
binaryGap = []
for i in range(n):
if binaryN[i] == 0 and binaryN[i + 1] == 0:
m = len(binaryN)
else:
return 0
binaryGap = binaryGap.append(m)
return max(binaryGap)
The function returns 0 for all values of N which is incorrect. How do I debug/improve the code to produce the accurate result?
Check out the below code. It would solve your problem.
The code is self-explanatory, yet let me know in-case of any doubts.
The Code:
import sys
num = int(sys.argv[1])
# Function to get the binary gap.
def binaryGapFinder(num):
binnum = bin(num).replace("0b", "") # binnum is binary form of the given number.
i = 0
x = 0
x_list = []
while i <= len(binnum)-1:
if binnum[i] == "0":
x += 1
if i == len(binnum)-1: # This loop will also consider if binary form is ending with 0. for example: 12 -> 1100
x_list.append(x)
else:
x_list.append(x)
x = 0
i += 1
return f"The Number: {num}\nIt's Binary Form: {binnum}\nMaximum Consecutive 0's: {max(x_list)}"
print(binaryGapFinder(num))
The Output:
python3 /the/path/to/your/script/binarygap.py 529
The Number: 529
It's Binary Form: 1000010001
Maximum Consecutive 0's: 4
python3 /the/path/to/your/script/binarygap.py 12
The Number: 12
It's Binary Form: 1100
Maximum Consecutive 0's: 2
python3 /the/path/to/your/script/binarygap.py 512
The Number: 512
It's Binary Form: 1000000000
Maximum Consecutive 0's: 9
There's a few issues here worth mentioning to aid you. (Just a side note to start with is that, in Python, it's recommended/best practice to use all lower case for variable names, so I'll replace them in my examples below.)
The bin() built in function returns a string. So you should be checking for equality with "0" (or '0') instead of an integer. e.g.
if binaryN[i] == "0" and binaryN[i + 1] == "0":
With Python you don't need to bother with checking for lengths of strings (or any other iterables) to use in a for loop in scenarios like this. e.g. You can replace:
n = len(binaryN)
for i in range(n):
with the more "Pythonic" way:
for bit in binary_number:
You can then use the variable bit (call it whatever you want of course, bearing in mind that good variable names make code more readable) instead of binary_number[index]. In this case, with each iteration of the for loop, bit will be replaced with the next character in the binary_number string.
From there on in your code:
m = len(binaryN)
will always be the same value, which is the total length of the string binaryN. e.g. 4 for '1001'.) This is not what you intended.
The first statement in your else block of code return 0 will terminate your function immediately and return 0 and thus your binaryGap = binaryGap.append(m) code will never, ever execute as it's unreachable due to that preceding return stopping any further execution of code in that suite.
You've got the right idea(s) and heading towards the right track for a solution but I don't think your code, even when the issues above are corrected, will match all possible binary numbers you may encounter. So, another possible alternative (and yet roughly sticking with the solution I think that you had in mind yourself) would be something like this which I hope will help you:
def solution(n):
binary_no = bin(n)[2:]
binary_gaps = []
gap_counter = 0
for bit in binary_no:
if bit == "0":
gap_counter += 1
else:
# Encountered a 1 so add current count of 0's -- if any -- to list and reset gap_counter
if gap_counter > 0:
binary_gaps.append(gap_counter)
gap_counter = 0
else:
# A for else suite (block of code) is run when all iterables have been exhausted.
if gap_counter > 0:
binary_gaps.append(gap_counter)
if binary_gaps: # If there is at least one element in the list
if len(binary_gaps) > 1:
return max(binary_gaps)
else:
return binary_gaps[0]
else:
# The list is empty, so no gaps were found at all. i.e. Binary number was all 1's.
return 0
print(solution(529))

How to count the number of substrings in a string?

I want to find the number of occurrences of a particular sub-string in a string.
string="abcbcbcb"
sub_str="cbc"
c=string.count(sub_str)
print(c)
This gives the output as
1
which is the number of non-overlapping occurrences of substring in the string.
But I want to calculate the overlapping strings as well. Thus, the desired output is:
2
You can use a regular expression, use module "re"
print len(re.findall('(?=cbc)','abcbcbcb'))
No standard function available for overlapping count. You could write custom function tho.
def count_occ(string, substr):
cnt = 0
pos = 0
while(True):
pos = string.find(substr , pos)
if pos > -1:
cnt += 1
pos += 1
else:
break
return cnt
string="abcbcbcb"
sub_str="cbc"
print(count_occ(string,sub_str))

Why doesn't this function always return the longest palindromic substring in a string?

I wrote this solution to a codewars problem (https://www.codewars.com/kata/longest-palindrome). It passes all but one of the tests, in which it returns 2 instead of 7.
Why might this solution fail?
def longest_palindrome (s):
if s == '':
return 0
if len(s) == 1:
return 1
palindrome_lengths = []
for i in range(len(s)):
# determine all indices for the character
indices = []
for p, character in enumerate(s):
if character == s[i]:
indices.append(p)
# check if each substring is a palindrome and, if so, add length to palindrome_lengths
index = 1
while index < len(indices):
# grab the substring
substring = s[indices[0]:indices[index]+1]
# reverse the substring
reverse_substring = substring[::-1]
# if forward substring equals reverse, add length to a list of lengths
if substring == reverse_substring:
palindrome_lengths.append(len(substring))
index += 1
if palindrome_lengths == []:
return 1
else:
palindrome_lengths.sort(reverse=True)
return palindrome_lengths[0]
You never check any substring that doesn't start with the first occurrence of its first letter in the original string (for example, for the string "mamadam", you never test the substring starting with the second m).

Palindrome rearrangement in Python

I am given a string and I have to determine whether it can be rearranged into a palindrome.
For example: "aabb" is true.
We can rearrange "aabb" to make "abba", which is a palindrome.
I have come up with the code below but it fails in some cases. Where is the problem and how to fix this?
def palindromeRearranging(inputString):
a = sorted(inputString)[::2]
b = sorted(inputString)[1::2]
return b == a[:len(b)]
def palindromeRearranging(inputString):
return sum(map(lambda x: inputString.count(x) % 2, set(inputString))) <= 1
this code counts occurrence for every character in string. in palindromes there is one character with odd occurrence if length of string is odd, if length of string is even then no character has odd occurance.
see here
def palindromeRearranging(inputString):
elements = {c:inputString.count(c) for c in set(inputString)}
even = [e % 2 == 0 for e in elements.values()]
return all(even) or (len(inputString) % 2 == 1 and even.count(False) == 1)
It counts each character number of appearances, and checks whether all elements appear an even number of times or if the length of the input string is odd, checks whether only one character appears an odd number of times.
Python3
def palindromeArrange (string):
string = list(string)
for i in range (len(string)):
"""if the string has even element count"""
if len(string) % 2 == 0 and len(string)/2 == len (set (string)):
return True
"""if the string has odd element count"""
if len(string) - ((len(string)-1)/2) == len (set (string)):
return True
return False
One liner using list comprehension in Python3
return len([x for x in set(inputString) if inputString.count(x) % 2 != 0]) <= 1
Basically counts those characters that have counts that aren't divisible by 2.
For even strings it would be zero, and for odd strings, it would be one.
The solution I can think of right away has time complexity is O(n). The assumption is, palindrome can not be made if there is more than one character with the odd count.
def solution(inputString):
string = list(inputString)
n = len(string)
s_set= set(string)
from collections import Counter
dic = Counter(string)
k =0 #counter for odd characters
for char in s_set:
if dic.get(char)%2!=0:
k+=1
if k>1:
return False
else:
return True

Count 2 (or more) characters recursively in string; return in (x,y) format in Python

I have written a program that will count how many ' ' single spaces or h characters in a string you enter when you call the function:
def chars(s):
if not s:
return 0
else:
return (s[0] == 'h') + chars(s[1:])
When you call chars('hello how are you here')
You will get 3.
Now, let's say I want to count the e along with the h. The h will return a 3 and the e should return a 4. Output would be (3,4).
I tried def chars(s, j=0)and set a counter but then realized, hold on, this has no connection to anything at this point deeming it pointless. I guess, how would I define what that second variable is? Because I only want 1 string as an input.
I am completely lost on how to include that second variable.
Also, just throwing it out there, would I follow the same rules as for 2 characters for more characters? Or would there be a different way?
This is what you want:
def count(s):
if not s:
return (0, 0)
else:
next_count = count(s[1:])
return ((s[0] == 'h') + next_count[0],
(s[0] == 'e') + next_count[1])
count("hello how are you here") # => (3, 4)
The base case returns the tuple (0, 0) and the recursive step looks at both of the values of the next count and adds one to each if necessary.
If you want more than 2 characters, just make the tuples bigger (probably using loops).

Resources