Okay this is very hard to explain, but i want to add padding to a sentence so that the characters in that sentence are a multiple of n.
however this number '4' has to change to 3 and 5 so it has to work then as well..
anyone know what im talking about?? and how to do it?
I hope the self commented code below would help you grasp the concept. You just have to do some maths to get the pad characters at either end
Some concept
Extra Characters required Padding = len(string) % block_length
Total_Pad_Characters = block_length - len(string) % block_length
Pad Character's at front = Total_Pad_Characters/2
Pad Character's at end = Total_Pad_Characters - Total_Pad_Characters/2
So here is the code
>>> def encrypt(st,length):
#Reversed the String and replace all Spaces with 'X'
st = st[::-1].replace(' ','X')
#Find no of characters to be padded.
padlength = (length - len(st)%length) % length
#Pad the Characters at either end
st = 'X'*(padlength/2)+st+'X'*(padlength-padlength/2)
#Split it with size length and then join with a single space
return ' '.join(st[i:i+length] for i in xrange(0,len(st),length))
>>> encrypt('THE PRICE OF FREEDOM IS ETERNAL VIGILENCE', 4) #Your Example
'XECN ELIG IVXL ANRE TEXS IXMO DEER FXFO XECI RPXE HTXX'
>>> encrypt('THE PRICE', 5) # One Extra Character at end for Odd Numbers
'ECIRP XEHTX'
>>> encrypt('THE PRIC', 5) # 1 Pad Characters at either end
'XCIRP XEHTX'
>>> encrypt('THE PRI', 5) # 1 Pad Characters at either end and one Extra for being Odd
'XIRPX EHTXX'
>>> encrypt('THE PR', 5) # 2 Pad Characters at either end
'XXRPX EHTXX'
>>> encrypt('THE P', 5) # No Pad characters required
'PXEHT'
>>> encrypt('THE PRICE OF FREEDOM IS ETERNAL VIGILENCE', 5) #Ashwini's Example
'XXECN ELIGI VXLAN RETEX SIXMO DEERF XFOXE CIRPX EHTXX'
>>>
>>> import math
>>> def encrypt(string, length):
inverse_string = string.replace(' ','X')[::-1]
center_width = int(math.ceil(len(inverse_string)/float(length)) * length) # Calculate nearest multiple of length rounded up
inverse_string = inverse_string.center(center_width,'X')
create_blocks = ' '.join(inverse_string[i:i+length] for i in xrange(0,len(inverse_string),length))
return create_blocks
>>> encrypt('THE PRICE OF FREEDOM IS ETERNAL VIGILENCE', 4)
'XECN ELIG IVXL ANRE TEXS IXMO DEER FXFO XECI RPXE HTXX'
def pad(yourString,blockLength):
return yourString + ("X" * (blockLength - (len(yourString) % blockLength)))
Is your padding function. for end padding.
If you need center padding use:
def centerPad(yourString,blockLength):
return ("X" * ((blockLength - (len(yourString) % blockLength))/2)) + yourString + ("X" * ((blockLength - (len(yourString) % blockLength))/2))
you need to take a harder look at the rest of your code if you want to implement a block cypher.
Related
Your answers have helped me a lot before, but now I'm stuck on a problem that I can't find the answer to. I'm currently at the start of teaching myself Python, and I've come across an exercise I can't figure out. I need to print each of the characters of a string on a new line in reverse order, with the number of spaces before each character being equal to the character's position in the string. Ideally, this would use a for loop.
I can print each character on a new line and in reverse order fine, but my issue is that when I reverse the string, it reverses the position of each of the characters: e.g. in the string 'dog', 'd' is in position 1, but reversed, is in position 3. I'd like to print the number of spaces multiplied by the original position of the string, rather than after it has been reversed.
This is what I have so far (apologies for any dodgy code).
def print_reverse(text):
x = 0
spc = ' '
for i in text[::-1]:
print(spc * x, i)
x += 1
print_reverse('dog')
Expected results:
g
o
d
Actual results:
g
o
d
The issue is initially x is 0. Instead you can try decreasing x from length of text:
def print_reverse(text):
x = len(text)
spc = ' '
for i in text[::-1]:
print(spc * x, i)
x -= 1
print_reverse('dog')
def print_reverse(text):
x = len(text)
spc = ' '
for i in text[::-1]:
print(spc * x, i)
x -= 1
This works
def print_reverse(text):
x = len(text)
spc = ' '
for i in text[::-1]:
print(spc * x, i)
x -= 1
In the iteration, you iterate like 0,1,2,3,.... You want decreasing spaces (...3,2,1,0), therefore try for example:
def print_reverse(text):
x = 0
spc = ' '
for i in text[::-1]:
print((len(text) - x)*spc,
print(i)
x += 1
Here you take the length of the string and substract your loop index. Same idea as the other stated solution by the user student, but slightly different implementation :)
You can accomplish this in a couple lines with a little bit of generator comprehension and enumerate:
def print_reverse(text):
for line in (' ' * (len(word)-i) + c for i, c in enumerate(text[::-1])):
print(line)
enumerate returns each list item, as well as it's position in a list (or in this case a string).
So enumerate('dog') will return:
((0, 'd'), (1, 'o'), (2, 'g'))
If you subtract the position from the total length of the word (len(word)-i), you'll get the number of spaces you need in front of your leter.
This answer also uses a generator expression, which is easy way to apply the same expression for each item in a list.
Finally, text[::-1] gives you a reversed list (you could also do reversed(text).
Doing some exercises to learn Python and facing issues while closing the code properly. The idea is to get something that does this:
d4 = """ /\\
//\\\\
\\\\//
\\/ """
print(d4)
/\
//\\
\\//
\/
Below is the code I have written:
def diamond(height):
"""Return a string resembling a diamond of specified height (measured in lines).
height must be an even integer.
"""
shape = ''
lchar_top, rchar_top = '/', '\\'
lchar_bottom, rchar_bottom = '\\' , '/'
for i in range((height//2)):
shape += (lchar_top * (i + 1)).rjust(height) + (rchar_top * (i + 1)).ljust(height) + '\n'
for j in range((height//2)):
shape += (lchar_bottom * (height//2 - j)).rjust(height) + (rchar_bottom * (height//2 - j)).ljust(height) + '\n'
print(shape)
Which popped the below output
diamond(8)
/\
//\\
///\\\
////\\\\
\\\\////
\\\///
\\//
\/
However, when I attempt to use a return statement as below:
def diamond(height):
"""Return a string resembling a diamond of specified height (measured in lines).
height must be an even integer.
"""
shape = ''
lchar_top, rchar_top = '/', '\\'
lchar_bottom, rchar_bottom = '\\' , '/'
for i in range((height//2)):
shape += (lchar_top * (i + 1)).rjust(height) + (rchar_top * (i + 1)).ljust(height) + '\n'
for j in range((height//2)):
shape += (lchar_bottom * (height//2 - j)).rjust(height) + (rchar_bottom * (height//2 - j)).ljust(height) + '\n'
return shape
I get this output:
diamond(8)
Out[215]: ' /\\ \n //\\\\ \n ///\\\\\\ \n ////\\\\\\\\ \n \\\\\\\\//// \n \\\\\\/// \n \\\\// \n \\/ \n'
Here is the solution offered via Kaggle(sorry about the formatting issue):
def diamond(height):
s = ''
# The characters currently being used to build the left and right half of
# the diamond, respectively. (We need to escape the backslash with another
# backslash so Python knows we mean a literal "\" character.)
l, r = '/', '\\'
# The "radius" of the diamond (used in lots of calculations)
rad = height // 2
for row in range(height):
# The first time we pass the halfway mark, swap the left and right characters
if row == rad:
l, r = r, l
if row < rad:
# For the first row, use one left character and one right. For
# the second row, use two of each, and so on...
nchars = row+1
else:
# Until we go past the midpoint. Then we start counting back down to 1.
nchars = height - row
left = (l * nchars).rjust(rad)
right = (r * nchars).ljust(rad)
s += left + right + '\n'
# Trim the last newline - we want every line to end with a newline character
# *except* the last
return s[:-1]
What do I need to change so that my attempted return statement also gives me the desired shape rather than a literal string of the appended characters and new line statements from iterating?
You're not wrong; your function returns what it should. It's just that the shell doesn't display it properly: if it sees a 'naked' value, it prints its represenation (the same you would get using the repr() function). The print the formatted value, use print(). Compare (I'm using IDLE while you seem to be using IPython, but the principle is the same):
>>> "line 1\nline 2\n"
'line 1\nline 2\n'
>>> print("line 1\nline 2\n")
line 1
line 2
So what you have to do: instead of just calling your function, you need to call print() with the result of the function:
>>> print(diamond(8))
/\
//\\
///\\\
////\\\\
\\\\////
\\\///
\\//
\/
Can anyone explain this code a little. I can't understand what n does here? We already have taken N = int(input()) as input then why n=len(bin(N))-2? I couldn't figure it out.
N = int(input())
n = len(bin(N))-2
for i in range(1,N+1):
print(str(i).rjust(n) + " " + format(i,'o').rjust(n) + " " + format(i,'X').rjust(n) + " " + format(i,'b').rjust(n))
n counts the number of bits in the number N. bin() produces the binary representation (zeros and ones), as as string with the 0b prefix:
>>> bin(42)
'0b101010'
so len(bin(n)) takes the length of that output string, minus 2 to account for the prefix.
See the bin() documentation:
Convert an integer number to a binary string prefixed with “0b”.
The length is used to set the width of the columns (via str.rjust(), which adds spaces to the front of a string to create an output n characters wide). Knowing how many characters the widest binary representation needs is helpful here.
However, the same information can be gotten directly from the number, with the int.bitlength() method:
>>> N = 42
>>> N.bit_length()
6
>>> len(bin(N)) - 2
6
The other columns are also oversized for the numbers. You could instead calculate max widths for each column, and use str.format() or an f-string to do the formatting:
from math import log10
N = int(input())
decwidth = int(log10(N) + 1)
binwidth = N.bit_length()
hexwidth = (binwidth - 1) // 4 + 1
octwidth = (binwidth - 1) // 3 + 1
for i in range(1, N + 1):
print(f'{i:>{decwidth}d} {i:>{octwidth}o} {i:>{hexwidth}X} {i:>{binwidth}b}')
I have a string of length n composed of letters A,G,C and T. The string is steady if it contains equal number of A,G,C and T(each n/4 times). I need to find the minimum length of the substring that when replaced makes it steady. Here's a link to the full description of the problem.
Suppose s1=AAGAAGAA.
Now since n=8 ideally it should have 2 As, 2 Ts, 2 Gs and 2 Cs. It has 4 excessive As. Hence we need a substring which contains at least 4 As.
I start by taking a 4 character substring from left and if not found then I increment a variable mnum(ie look for 5 variable substrings and so on).
We get AAGAA as an answer. But it's too slow.
from collections import Counter
import sys
n=int(input()) #length of string
s1=input()
s=Counter(s1)
le=int(n/4) #ideal length of each element
comp={'A':le,'G':le,'C':le,'T':le} #dictionary containing equal number of all elements
s.subtract(comp) #Finding by how much each element ('A','G'...) is in excess or loss
a=[]
b=[]
for x in s.values(): #storing frequency(s.values--[4,2]) of elements which are in excess
if(x>0):
a.append(x)
for x in s.keys(): #storing corresponding elements(s.keys--['A','G'])
if(s[x]>0):
b.append(x)
mnum=sum(a) #minimum substring length to start with
if(mnum==0):
print(0)
sys.exit
flag=0
while(mnum<=n): #(when length 4 substring with all the A's and G's is not found increasing to 5 and so on)
for i in range(n-mnum+1): #Finding substrings with length mnum in s1
for j in range(len(a)): #Checking if all of excess elements are present
if(s1[i:i+mnum].count(b[j])==a[j]):
flag=1
else:
flag=0
if(flag==1):
print(mnum)
sys.exit()
mnum+=1
The minimal substring can be found in O(N) time and O(N) space.
First count a frequency fr[i] of each character from the input of length n.
Now, the most important thing to realise is that the necessary and sufficient condition for a substring to be considered minimal, it must contain each excessive character with a frequency of at least fr[i] - n/4. Otherwise, it won't be possible to replace the missing characters. So, our task is to go through each such substring and pick the one with the minimal length.
But how to find all of them efficiently?
At start, minLength is n. We introduce 2 pointer indices - left and right (initially 0) that define a substring from left to right in the original string str. Then, we increment right until the frequency of each excessive character in str[left:right] is at least fr[i] - n/4. But it's not all yet since str[left : right] may contain unnecessary chars to the left (for example, they're not excessive and so can be removed). So, we increment left as long as str[left : right] still contains enough excessive elements. When we're finished we update minLength if it's larger than right - left. We repeat the procedure until right >= n.
Let's consider an example. Let GAAAAAAA be the input string. Then, the algorithm steps are as below:
1.Count frequencies of each character:
['G'] = 1, ['A'] = 6, ['T'] = 0, ['C'] = 0 ('A' is excessive here)
2.Now iterate through the original string:
Step#1: |G|AAAAAAA
substr = 'G' - no excessive chars (left = 0, right = 0)
Step#2: |GA|AAAAAA
substr = 'GA' - 1 excessive char, we need 5 (left = 0, right = 1)
Step#3: |GAA|AAAAA
substr = 'GAA' - 2 excessive chars, we need 5 (left = 0, right = 2)
Step#4: |GAAA|AAAA
substr = 'GAAA' - 3 excessive chars, we need 5 (left = 0, right = 3)
Step#5: |GAAAA|AAA
substr = 'GAAAA' - 4 excessive chars, we need 5 (left = 0, right = 4)
Step#6: |GAAAAA|AA
substr = 'GAAAAA' - 5 excessive chars, nice but can we remove something from left? 'G' is not excessive anyways. (left = 0, right = 5)
Step#7: G|AAAAA|AA
substr = 'AAAAA' - 5 excessive chars, wow, it's smaller now. minLength = 5 (left = 1, right = 5)
Step#8: G|AAAAAA|A
substr = 'AAAAAA' - 6 excessive chars, nice, but can we reduce the substr? There's a redundant 'A'(left = 1, right = 6)
Step#9: GA|AAAAA|A
substr = 'AAAAA' - 5 excessive chars, nice, minLen = 5 (left = 2, right = 6)
Step#10: GA|AAAAAA|
substr = 'AAAAAA' - 6 excessive chars, nice, but can we reduce the substr? There's a redundant 'A'(left = 2, right = 7)
Step#11: GAA|AAAAA|
substr = 'AAAAA' - 5 excessive chars, nice, minLen = 5 (left = 3, right = 7)
Step#12: That's it as right >= 8
Or the full code below:
from collections import Counter
n = int(input())
gene = raw_input()
char_counts = Counter()
for i in range(n):
char_counts[gene[i]] += 1
n_by_4 = n / 4
min_length = n
left = 0
right = 0
substring_counts = Counter()
while right < n:
substring_counts[gene[right]] += 1
right += 1
has_enough_excessive_chars = True
for ch in "ACTG":
diff = char_counts[ch] - n_by_4
# the char cannot be used to replace other items
if (diff > 0) and (substring_counts[ch] < diff):
has_enough_excessive_chars = False
break
if has_enough_excessive_chars:
while left < right and substring_counts[gene[left]] > (char_counts[gene[left]] - n_by_4):
substring_counts[gene[left]] -= 1
left += 1
min_length = min(min_length, right - left)
print (min_length)
Here's one solution with limited testing done. This should give you some ideas on how to improve your code.
from collections import Counter
import sys
import math
n = int(input())
s1 = input()
s = Counter(s1)
if all(e <= n/4 for e in s.values()):
print(0)
sys.exit(0)
result = math.inf
out = 0
for mnum in range(n):
s[s1[mnum]] -= 1
while all(e <= n/4 for e in s.values()) and out <= mnum:
result = min(result, mnum - out + 1)
s[s1[out]] += 1
out += 1
print(result)
How do you format a number as a string so that it takes a number of spaces in front of it? I want the shorter number 5 to have enough spaces in front of it so that the spaces plus the 5 have the same length as 52500. The procedure below works, but is there a built in way to do this?
a = str(52500)
b = str(5)
lengthDiff = len(a) - len(b)
formatted = '%s/%s' % (' '*lengthDiff + b, a)
# formatted looks like:' 5/52500'
Format operator:
>>> "%10d" % 5
' 5'
>>>
Using * spec, the field length can be an argument:
>>> "%*d" % (10,5)
' 5'
>>>
'%*s/%s' % (len(str(a)), b, a)
You can just use the %*d formatter to give a width. int(math.ceil(math.log(x, 10))) will give you the number of digits. The * modifier consumes a number, that number is an integer that means how many spaces to space by. So by doing '%*d' % (width, num)` you can specify the width AND render the number without any further python string manipulation.
Here is a solution using math.log to ascertain the length of the 'outof' number.
import math
num = 5
outof = 52500
formatted = '%*d/%d' % (int(math.ceil(math.log(outof, 10))), num, outof)
Another solution involves casting the outof number as a string and using len(), you can do that if you prefer:
num = 5
outof = 52500
formatted = '%*d/%d' % (len(str(outof)), num, outof)
See String Formatting Operations:
s = '%5i' % (5,)
You still have to dynamically build your formatting string by including the maximum length:
fmt = '%%%ii' % (len('52500'),)
s = fmt % (5,)
Not sure exactly what you're after, but this looks close:
>>> n = 50
>>> print "%5d" % n
50
If you want to be more dynamic, use something like rjust:
>>> big_number = 52500
>>> n = 50
>>> print ("%d" % n).rjust(len(str(52500)))
50
Or even:
>>> n = 50
>>> width = str(len(str(52500)))
>>> ('%' + width + 'd') % n
' 50'