there is a syntax error that says that i am returning outside the function
I tried all the possible solutions that people used on the same problem with there code and i still get the same error
the error is in line 32 in the line return result
Problem Introduction
In this problem, we ask a simple question: how many times one string occurs as a substring of another? Recall that di erent occurrences of a substring can overlap with each other. For example, ATA occurs three times in CGATATATCCATAG.
Problem Description
Task. Find all occurrences of a pattern in a string.
Input Format. Strings πππ‘π‘πππ and πΊπππππ.
Constraints. 1 β€ |πππ‘π‘πππ| β€ 106; 1 β€ |πΊπππππ| β€ 106; both strings are over A, C, G, T.
Sample 1.
Input:
Output:
1 12
4 1.5 2
4 4 24
TACG GT
Explanation:
The pattern is longer than the text and hence has no occurrences in the text.
Sample 2.
Input:
Output:
02
Explanation:
The pattern appears at positions 1 and 3 (and these two occurrences overlap each other).
Sample 3.
Input:
Output:
139
Explanation:
The pattern appears at positions 1, 3, and 9 in the text.
ATA ATATA
ATAT
GATATATGCATATACTT
# python3
import sys
def compute_prefix_function(pattern):
s = [0] * len(pattern)
border = 0
for i in range(1, len(pattern)):
while (border > 0) and (pattern[i] != pattern[border]):
border = s[border - 1]
if pattern[i] == pattern[border]:
border = border + 1
else:
border = 0
s[i] = border
return s
def find_pattern(pattern, text):
S = pattern + '$' + text
s = compute_prefix_function(S)
result = []
p = len(pattern)
for i in range(p + 1, len(S)):
if s[i] == p:
result.append(i - 2 * p)
return result
if __name__ == '__main__':
pattern = sys.stdin.readline().strip()
text = sys.stdin.readline().strip()
result = find_pattern(pattern, text)
print(" ".join(map(str, result)))
Realize that white space/indentation matters in python, and replaces the { }, used in most other language to define a scope. Something like this is a proper function (although, the return isn't really necessary):
def foo():
print("bar")
return
Doing this instead would result in an error message similar to your, though, because the return now is outside the scope of the function:
def foo():
print("bar")
return
For more info just Google for python indentation tutorial.
Related
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))
I am wondering if there is a "pythonic" way to from the a character position in a string to the terminal offset that character will be printed at (i.e including tabs).
For example take the following three strings:
$> python3
>>> print("+\tabc")
+ abc
>>> print("\tabc")
abc
>>> print(" abc")
abc
They are three difference strings, with three different character counts preceding the "abc", but the position of 'a' is different each time.
The only solution I have that works "well enough" is
def get_offset(s, c):
pos = s.find(c)
if pos == -1:
return -1
tablen = 0
ntabs = 0
for i in range(0, pos):
if line[i] == '\t':
tablen += (TABLEN - (i % TABLEN))
ntabs += 1
offset = tablen + (pos - ntabs)
return offset
I am wondering is there a more pythonic way to do this?
Not really.
Because python doesn't know about how its output will be rendered, it cannot tell you the offset resulting from tab characters. From python's point of view, a tab is a character like any other.
Once again I'm asking for you advice. I'm trying to print a complex string block, it should look like this:
32 1 9999 523
+ 8 - 3801 + 9999 - 49
---- ------ ------ -----
40 -3800 19998 474
I wrote the function arrange_printer() for the characters arrangement in the correct format that could be reutilized for printing the list. This is how my code looks by now:
import operator
import sys
def arithmetic_arranger(problems, boolean: bool):
arranged_problems = []
if len(problems) <= 5:
for num in range(len(problems)):
arranged_problems += arrange_printer(problems[num], boolean)
else:
sys.exit("Error: Too many problems")
return print(*arranged_problems, end=' ')
def arrange_printer(oper: str, boolean: bool):
oper = oper.split()
ops = {"+": operator.add, "-": operator.sub}
a = int(oper[0])
b = int(oper[2])
if len(oper[0]) > len(oper[2]):
size = len(oper[0])
elif len(oper[0]) < len(oper[2]):
size = len(oper[2])
else:
size = len(oper[0])
line = '------'
ope = ' %*i\n%s %*i\n%s' % (size,a,oper[1],size,b,'------'[0:size+2])
try:
res = ops[oper[1]](a,b)
except:
sys.exit("Error: Operator must be '+' or '-'.")
if boolean == True:
ope = '%s\n%*i' % (ope,size+2, res)
return ope
arithmetic_arranger(['20 + 300', '1563 - 465 '], True)
#arrange_printer(' 20 + 334 ', True)
Sadly, I'm getting this format:
2 0
+ 3 0 0
- - - - -
3 2 0 1 5 6 3
- 4 6 5
- - - - - -
1 0 9 8
If you try printing the return of arrange_printer() as in the last commented line the format is the desired.
Any suggestion for improving my code or adopt good coding practices are well received, I'm starting to get a feel for programming in Python.
Thank you by your help!
The first problem I see is that you use += to add an item to the arranged_problems list. Strings are iterable. somelist += someiterable iterates over the someiterable, and appends each element to somelist. To append, use somelist.append()
Now once you fix this, it still won't work like you expect it to, because print() works by printing what you give it at the location of the cursor. Once you're on a new line, you can't go back to a previous line, because your cursor is already on the new line. Anything you print after that will go to the new line at the location of the cursor, so you need to arrange multiple problems such that their first lines all print first, then their second lines, and so on. Just fixing append(), you'd get this output:
20
+ 300
-----
320 1563
- 465
------
1098
You get a string with \n denoting the start of the new line from each call to arrange_printer(). You can split this output into lines, and then process each row separately.
For example:
def arithmetic_arranger(problems, boolean:bool):
arranged_problems = []
if len(problems) > 5:
print("Too many problems")
return
for problem in problems:
# Arrange and split into individual lines
lines = arrange_printer(problem, boolean).split('\n')
# Append the list of lines to our main list
arranged_problems.append(lines)
# Now, arranged_problems contains one list for each problem.
# Each list contains individual lines we want to print
# Use zip() to iterate over all the lists inside arranged_problems simultaneously
for problems_lines in zip(*arranged_problems):
# problems_lines is e.g.
# (' 20', ' 1563')
# ('+ 300', '- 465') etc
# Unpack this tuple and print it, separated by spaces.
print(*problems_lines, sep=" ")
Which gives the output:
20 1563
+ 300 - 465
----- ------
320 1098
If you expect each problem to have a different number of lines, then you can use the itertools.zip_longest() function instead of zip()
To collect all my other comments in one place:
return print(...) is pretty useless. print() doesn't return anything. return print(...) will always cause your function to return None.
Instead of iterating over range(len(problems)) and accessing problems[num], just do for problem in problems and then use problem instead of problems[num]
Debugging is an important skill, and the sooner into your programming career you learn it, the better off you will be.
Stepping through your program with a debugger allows you to see how each statement affects your program and is an invaluable debugging tool
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.
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).