While loop and if statements - python

I have a string and k = number, which is the length of a substring that has the same letter repeated in a row. How can I have the wanted output only?
The expected output: For length 3, found the substring ddd!
my_string = 'aabadddefggg'
k = 3
x = 1
c = 1
while x < len(my_string):
if my_string\[x\] == my_string\[x-1\]:
c += 1
else:
c = 1
if c == k:
print("For length " + str(k) + ", found the substring " + my_string\[x\] \* k + "!")
break
else:
print("Didn't find a substring of length " + str(k))
break
x += 1
The output:
Didn't find a substring of length 3
Didn't find a substring of length 3
Didn't find a substring of length 3
Didn't find a substring of length 3
Didn't find a substring of length 3
For length 3, found the substring ddd!

get rid of the break after didnt find the string. Your code means that once you evaluate c == k you will always break beacuse you have the break in both the if and the else meaning you can never reach x += 1
my_string = 'aabadddefggg'
k = 3
x = 1
c = 1
while x < len(my_string):
if my_string[x] == my_string[x-1]:
c += 1
else:
c = 1
if c == k:
print("For length " + str(k) + ", found the substring " + my_string[x] * k + "!")
break
else:
print("Didn't find a substring of length " + str(k))
x += 1
OUTPUT
Didn't find a substring of length 3
Didn't find a substring of length 3
Didn't find a substring of length 3
Didn't find a substring of length 3
Didn't find a substring of length 3
For length 3, found the substring ddd!

Even better, put your else statement under the while, this way:
my_string = 'aabadddefggg'
k = 3
x = 1
c = 1
while x < len(my_string):
if my_string[x] == my_string[x-1]:
c += 1
else:
c = 1
if c == k:
print("For length " + str(k) + ", found the substring " + my_string[x] * k + "!")
break
x += 1
else:
print("Didn't find a substring of length " + str(k))
# For length 3, found the substring ddd!
With k = 4 (the else statement is executed if the end of the loop is reached, which happens only if it doesn't break out of it):
# Didn't find a substring of length 4

Related

Find all the common substrings between two strings, regardless of case and order

So i started with the code from an answer to this question Function to find all common substrings in two strings not giving correct output and modified it a little bit to accommodate case-independence (i.e. AbCd is the same as ABCD as Abcd and so on) by turning the string to lowercase. However, for strings like 'ABCDXGHIJ' and 'ghijYAbCd', it only returns ['ghij'], not the desired output ['ABCD', 'GHIJ'].
Here are other examples:
'Bonywasawarrior' and 'Bonywasxwarrior' (output: ['Bonywas', 'warrior', 'wa'], desired output: ['Bonywas', 'warrior'])
'01101001' and '101010' (output: ['1010', '0', '1010', '01', '10', '01'], desired output: ['1010'])
here is my code:
t = int(input()) #t cases
while t > 0:
A = str(input()) #1st string
B = str(input()) #2nd string
low_A = A.lower()
low_B = B.lower()
answer = ""
anslist=[]
for i in range(len(A)):
common = ""
for j in range(len(B)):
if (i + j < len(A) and low_A[i + j] == low_B[j]):
common += B[j]
else:
#if (len(common) > len(answer)):
answer = common
if answer != '' and len(answer) > 1:
anslist.append(answer)
common = ""
if common != '':
anslist.append(common)
if len(anslist) == 0:
print('[]') #print if no common substring
else:
print(anslist)
t -= 1
You can increment an offset in a while loop to keep concatenating common characters at the offset from the respective indices until they become different instead. To find the longest, non-overlapping common substrings, you can use a function that recursively traverses different paths of substring partitioning, and returns the one with the longest lengths of substrings:
def common_strings(a, b, i=0, j=0):
candidates = []
len_a = len(a)
len_b = len(b)
if j == len_b:
candidates.append(common_strings(a, b, i + 1, 0))
elif i < len_a:
offset = 0
while i + offset < len_a and j + offset < len_b and a[i + offset].lower() == b[j + offset].lower():
offset += 1
if offset > 1:
candidates.append([a[i: i + offset]] + common_strings(a, b, i + offset, j + offset))
candidates.append(common_strings(a, b, i, j + 1))
return candidates and max(candidates, key=lambda t: sorted(map(len, t), reverse=True))
so that:
print(common_strings('ABCDXGHIJ', 'ghijYAbCd'))
print(common_strings('Bonywasawarrior', 'Bonywasxwarrior'))
print(common_strings('01101001', '101010'))
outputs:
['ABCD', 'GHIJ']
['Bonywas', 'warrior']
['1010']
This is a duplicate of Finding all the common substrings of given two strings, which offers a solution in Java and for which I have done my best to translate to Python with the "enhancement" of making it case-insensitive:
def find_common(s, t):
table = [len(t)*[0] for i in range(len(s))]
longest = 0
result = set()
for i, ch1 in enumerate(s.lower()):
for j, ch2 in enumerate(t.lower()):
if ch1 != ch2:
continue
table[i][j] = 1 if i == 0 or j == 0 else 1 + table[i - 1][j - 1]
if table[i][j] > longest:
longest = table[i][j]
result.clear()
if table[i][j] == longest:
result.add(s[i - longest + 1:i + 1]);
return result
print(find_common('Bonywasawarrior', 'Bonywasxwarrior'))
print(find_common('01101001', '101010'))
print(find_common('ABCDXGHIJ', 'ghijYAbCd'))
Prints:
{'Bonywas', 'warrior'}
{'1010'}
{'GHIJ', 'ABCD'}

Counting occurrences of a sub-string without using a built-in function

My teacher challenged me of finding a way to count the occurences of the word "bob" in any random string variable without str.count(). So I did,
a = "dfjgnsdfgnbobobeob bob"
compteurDeBob = 0
for i in range (len(a) - 1):
if a[i] == "b":
if a[i+1] == "o":
if a[i+2] == "b":
compteurDeBob += 1
print(compteurDeBob)
but I wanted to find a way to do that with a word of any length as shown below, but I have no clue on how to do that...
a = input("random string: ")
word = input("Wanted word: ")
compteurDeBob = 0
for i in range (len(a)-1):
#... i don't know...
print(compteurDeBob)
a = input("random string: ")
word = input("Wanted word: ")
count = 0
for i in range(len(a)-len(word)):
if a[i:i+len(word)] == word:
count += 1
print(count)
If you want your search to be case-insensitive, then you can use lower() function:
a = input("random string: ").lower()
word = input("Wanted word: ").lower()
count = 0
for i in range(len(a)):
if a[i:i+len(word)] == word:
count += 1
print(count)
For the user input
Hi Bob. This is bob
the first approach will output 1 and the second approach will output 2
To count all overlapping occurrences (like in your example) you could just slice the string in a loop:
a = input("random string: ")
word = input("Wanted word: ")
cnt = 0
for i in range(len(a)-len(word)+1):
if a[i:i+len(word)] == word:
cnt += 1
print(cnt)
You can use string slicing. One way to adapt your code:
a = 'dfjgnsdfgnbobobeob bob'
counter = 0
value = 'bob'
chars = len(value)
for i in range(len(a) - chars + 1):
if a[i: i + chars] == value:
counter += 1
A more succinct way of writing this is possible via sum and a generator expression:
counter = sum(a[i: i + chars] == value for i in range(len(a) - chars + 1))
This works because bool is a subclass of int in Python, i.e. True / False values are considered 1 and 0 respectively.
Note str.count won't work here, as it only counts non-overlapping matches. You could utilise str.find if built-ins are allowed.
The fastest way to calculate overlapping matches is the Knuth-Morris-Pratt algorithm [wiki] which runs in O(m+n) with m the string to match, and n the size of the string.
The algorithm first builds a lookup table that acts more or less as the description of a finite state machine (FSM). First we construct such table with:
def build_kmp_table(word):
t = [-1] * (len(word)+1)
cnd = 0
for pos in range(1, len(word)):
if word[pos] == word[cnd]:
t[pos] = t[cnd]
else:
t[pos] = cnd
cnd = t[cnd]
while cnd >= 0 and word[pos] != word[cnd]:
cnd = t[cnd]
cnd += 1
t[len(word)] = cnd
return t
Then we can count with:
def count_kmp(string, word):
n = 0
wn = len(word)
t = build_kmp_table(word)
k = 0
j = 0
while j < len(string):
if string[j] == word[k]:
k += 1
j += 1
if k >= len(word):
n += 1
k = t[k]
else:
k = t[k]
if k < 0:
k += 1
j += 1
return n
The above counts overlapping instances in linear time in the string to be searched, which was an improvements of the "slicing" approach that was earlier used, that works in O(m×n).

Printing a hollow triangle in alphabetical order anti-clock-wise

I'm currently having some difficulty with this python pattern problem, where I am not able to generate the proper output, required to this problem. If I could receive some help or feedback from you guys that'll be great! Thank you!!
def print_triangle(sentence):
if len(sentence) % 4 != 0:
return False
else:
char_list = list(sentence)
x = 0
n = int(len(sentence) / 4) + 1
for row in range(1,n+1):
for col in range(1,2*n):
if row ==n or row+col == n+1 or col-row == n-1:
print(char_list[x] ,end="")
x += 1
else:
print(end=" ")
print()
return True
if function print_triangle('abcdefghijkl') is called, it should be able to generate the following output:
a
b l
c k
defghij
Return value:True
However, this is the output that I'm getting
a
b c
d e
fghijkl
Return value:True
Algorythm:
row 0: print spaces + first letter
row 1: print 1 less spaces + next letter, print row*2-1 spaces, print last letter
row 2: - the same, just print the letter before the last letter
...
last row: print remaining letters up to (not including) those that being printed already:
def print_triangle(sentence):
n = len(sentence)
if n % 4 != 0:
return False
# special case handling ;)
elif n==4:
print(" " + sentence[0], sentence[1:], sep="\n")
return True
else:
numRows = n//4
for row in range(numRows+1): # amount of total triangle rows
# end case, print the rest thats not been printed
if row == numRows:
print(sentence[row:-row+1])
return True
# normal case: print enough spaces, then 1 letter, do not end the line
print(' '*(numRows - row)+sentence[row],end="")
# on all but the first line: print padding spaces and last letter
if row != 0:
print(' '*(2*row-1)+sentence[n-row])
else:
print("") # newline to "close" this line if on line 0
print("")
r = print_triangle(input())
print(r) # or do print("Return value: {}".format(r)) to be exact...
Output: ('abcdefghijkl')
a
b l
c k
defghij
True
Output: ('abcdefghijklmnop')
a
b p
c o
d n
efghijklm
True
Output: ('abc')
False

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

Maximum of Longest Increasing Sequences

I have a code that will find all the cycles of a list, e.g for [1,2,3] the cycles are [1,2,3], [2,3,1], [3,1,2]. I also have a code for finding the longest increasing subsequence.
What I want to do is input a list, find the longest increasing subsequence of every cycle of that list, and then return the maximum length out of all of these. how do I go from these two functions to finding the LIS of every cycle and then return the maximum?
Here is my code so far:
def cycles(X):
n = len(X)
values = []
for i in range(0,n):
values.append(X[i:n] + X[0:i])
return values
def longest_increasing_subsequence(d):
l = []
for i in range(len(d)):
l.append(max([l[j] for j in range(i) if l[j][-1] < d[i]] or [[]], key=len) + [d[i]])
return len(max(l, key=len))
I'd appreciate any help. thanks.
This will do the job:
l=[1,2,3,4]
s=cycles(l)
lis=[longest_increasing_subsequence(d) for d in s]
print(lis)
print(max(lis))
The result is
[4,3,2,3]
and
4
Try this code:
l = [3,4,5,9,8,1,2,7,7,7,7,7,7,7,6,0,1]
empty = []
one = [1]
two = [2,1]
three = [1,0,2,3]
tricky = [1,2,3,0,-2,-1]
ring = [3,4,5,0,1,2]
internal = [9,1,2,3,4,5,0]
# consider your list as a ring, continuous and infinite
def longest_increasing_subsequence(l):
length = len(l)
if length == 0: return 0 # list is empty
i, tmp, longest = [0, 1, 1]
# 1 < tmp means that ring is finished, but the sequence continue to increase
while i < length or 1 < tmp:
# compare elements on the ring
if l[i%length] < l[(i+1)%length]:
tmp += 1
else:
if longest < tmp: longest = tmp
tmp = 1
i += 1
return longest
print("0 == " + str(longest_increasing_subsequence(empty)))
print("1 == " + str(longest_increasing_subsequence(one)))
print("2 == " + str(longest_increasing_subsequence(two)))
print("3 == " + str(longest_increasing_subsequence(three)))
print("5 == " + str(longest_increasing_subsequence(tricky)))
print("5 == " + str(longest_increasing_subsequence(internal)))
print("6 == " + str(longest_increasing_subsequence(ring)))
print("6 == " + str(longest_increasing_subsequence(l)))

Categories

Resources