patterns with nested for - python-3.x

How do i achieve the following pattern, if input is 3?
AA
BBAA
AABBAA
Furthest i can get was:
AA
BBBB
AAAAAA
I have tried the following:
#mod operator used to alternate patterns
pattern_size = int (input ("Input height : "))
for level in range (1, pattern_size +1):
for x in range (level):
# print AA if remainder != 0
if level % 2 != 0:
print ("AA", end = '')
# print BB if remainder = 0
if level % 2 == 0:
print ("BB", end = '')

I guess it is a homework, and you will get more if you will find the solution on your own.
Firstly, if you want to alternate AA and BB when printing on the same level, it must depend on x (because x changes when level does not change). Moreover, each level starts with a different pattern. This way you may want to test (level + x) % 2 == 0 (choose the easy way of testing). If the boolean expression is true, print one pattern, else print the other.
Do not forget to print() without arguments after the x loop.
I prefer simpler usage of range() -- with a single argument. If pattern_size is 3, then the first loop can go through levels 0, 1, 2. However, the second for must loop at least once. Then you must go through range(level + 1).

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))

Cant figure out conditionals

I'm working on a 30 day of code challenge and passed 5/8 tests on my code and can't figure out the reason it keeps failing
The parameters are that
if N is odd print weird,
if N is even and in the range of 2-5 print not weird
if N is even and in the range of 6-20 print weird
if N is even and greater than 20 print not weird
N = int(input())
if N % 2 == 0 and range(2-5):
print("Not Weird")
elif N % 2 == 0 and range(6-20):
print("Weird")
elif N % 2 == 0 and N > 20:
print("Not Weird")
elif N % 2 == 1 :
print("Weird")
if N % 2 == 0 and range(2-5):
does not do what you think, it should instead be something like:
if N % 2 == 0 and N in range(2, 6):
Specifically:
each sub-condition (on either side of your 'and') should be complete.
range, in your example, was range(-3) since that's what 2-5 gives.
the range is half open, meaning it includes the start but excludes the end.
1) The function range with defined begging and end is a function that takes 2 parameters as argument. Therefore I'd recommend you to use it as range(x,y) instead of range(x-y).
If you use it like range(2-5), you're actually asking for range(-3). When used with only 1 arg, the function range will give you a list of int from 0 up to the input arg.
Regarded that there is no integer greater than 0 and less than -3, then you're getting an empty list.
2) Also, notice that the upper limit is not inclusive:
>>> for i in range(2,5):
... print(i)
...
2
3
4
so you might consider to use range(2,6) for the first case, range(6,21) for the second case and so on and so forth..
To expand on #paxdiablo's answer, you can also use the step argument of range to test for even numbers:
if N in range(2, 6, 2):

Convert S to T by performing K operations (HackerRank)

I was solving a problem on HackerRank. It required me to see if it is possible to convert string s to string t by performing k operations.
https://www.hackerrank.com/challenges/append-and-delete/problem
The operations we can perform are: appending a lowercase letter to the end of s or removing a lowercase letter from the end of s. For example Ash Ashley 2 would return No since we need 3 operations, not 2.
I tried solving the problem as follows:
def appendAndDelete(s, t, k):
if len(s) > len(t):
maxs = [s,t]
else:
maxs = [t,s]
maximum = maxs[0]
minimum = maxs[1]
k -= len(maximum) - len(minimum)
substr = maximum[len(minimum): len(maximum)]
maximum = maximum.replace(substr, '')
i = 0
while i < len(maximum):
if maximum[i] != minimum[i]:
k -= (len(maximum)-i)*2
break
i += 1
if k < 0:
return 'No'
else:
return 'Yes'
However, it fails at this weird test case. y yu 2. The expected answer is No but according to my code, it would return Yes since only one operation was required. Is there something I do not understand?
Since you don't explain your idea, it's difficult for us to understand
what you mean in your code and debug it to tell you where you went wrong.
However, I would like to share my idea(I solved this on the website too)-
len1 => Length of first string s.
len2 => Length of second/target string t.
Exactly K makes it a bit tricky. So, if len1 + len2 <= k, you can blindly assume it can be accomplished and return true since we can delete empty string many times to get an empty string(as it says) and we can delete characters of one string entirely and keep appending new letters to get the another.
When we start matching s with t from left to right, this looks more like longest common prefix but this is NOT the case. Let's take an example -
aaaaaaaaa (source)
aaaa (target)
7 (k)
Here, up till aaaa it's common and looks like there are additional 5 a's in the source. So, we can delete those 5 a's and get the target but 5 != 7, hence it appears to be a No. But this ain't the case since we can delete an a from the source just like that and append it again(2 operations) just to satisfy k. So, it need not be longest common prefix all the time, however it gets us closer to the solution.
So, let's match both strings from left to right and stop when there is a mismatch. Let's assume we got this index in a variable called first_unmatched. Initialize first_unmatched = min(len(s),len(t)) at the beginning of your method itself.
Let
rem1 = len1 - first_unmatched
rem2 = len2 - first_unmatched
where rem1 is remaining substring of s and rem2 is the remaining substring of t.
Now, comes the conditions.
if(rem1 + rem2 == k) return true-
This is because rem1 characters to delete and rem2 characters to add. If both sum up to k then it's possible.
if(rem1 + rem2 > k) return false-
This is because rem1 characters to delete and rem2 characters to add. If both sum greater than k then it's not possible.
if(rem1 + rem2 < k) return (k - (rem1 + rem2)) % 2 == 0-
This is because rem1 characters to delete and rem2 characters to add. If both sum less than k, then it depends.
Here, (k - (rem1 + rem2)) will give you the extra in k. This extra can or cannot depends upon whether it's divisible by 2 or not. Here, we do %2 because we have 2 operations in our question - delete and append. If the extra k falls short of any operation, then the answer is No, else it's a Yes.
You can cross check this with above example.

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).

How to Print a string to a specific character?

I have a file like this:
NA|polymerase|KC545393|Bundibugyo_ebolavirus|EboBund_112_2012|NA|2012|Human|Democratic_Republic_of_the_Congo
NA|VP24|KC545393|Bundibugyo_ebolavirus|EboBund_112_2012|NA|2012|Human|Democratic_Republic_of_the_Congo
NA|VP30|KC545393|Bundibugyo_ebolavirus|EboBund_112_2012|NA|2012|Human|Democratic_Republic_of_the_Congo
I am trying to print this characters from each line:
polymerase|KC545393
VP24|KC545393
VP30|KC545393
How can I do this?
I tried this code:
for character in line:
if character=="|":
print line[1:i.index(j)]
Use str.split() to split each line by the '|' character; you can limit the splitting because you only need the first 3 columns:
elems = line.split('|', 3)
print '|'.join(elems[1:3])
The print line then takes the elements at index 1 and 2 and joins them together again using the '|' character to produce your desired output.
Demo:
>>> lines = '''\
... NA|polymerase|KC545393|Bundibugyo_ebolavirus|EboBund_112_2012|NA|2012|Human|Democratic_Republic_of_the_Congo
... NA|VP24|KC545393|Bundibugyo_ebolavirus|EboBund_112_2012|NA|2012|Human|Democratic_Republic_of_the_Congo
... NA|VP30|KC545393|Bundibugyo_ebolavirus|EboBund_112_2012|NA|2012|Human|Democratic_Republic_of_the_Congo
... '''.splitlines(True)
>>> for line in lines:
... elems = line.split('|', 3)
... print '|'.join(elems[1:3])
...
polymerase|KC545393
VP24|KC545393
VP30|KC545393
Assuming you know that each line has at least two separators, you can use:
>>> s = 'this|is|a|string'
>>> s
'this|is|a|string'
>>> s[:s.find('|',s.find('|')+1)]
'this|is'
This finds the first | starting at the character position beyond the first | (i.e., it finds the second |) then gives you the substring up but not including to that point.
If it may not have two separators, you just have to be more careful:
s = 'blah blah'
result = s
if s.find('|') >= 0:
if s.find('|',s.find('|')+1) >= 0:
result = s[:s.find('|',s.find('|')+1)]
If that's the case, you'll probably definitely want it in a more general purpose function, something like:
def substringUpToNthChar(str,n,ch):
if n < 1: return ""
pos = -1
while n > 0:
pos = str.find(ch,pos+1)
if pos < 0: return str
n -= 1
return str[:pos]
This will correctly handle the case where there's fewer separators than desired and will also handle (relatively elegantly) getting more than the first two fields.

Resources