I want to create the following function
Left_padded(n, width)
That returns, for example:
Left_padded(6, 4):
' 6' #number 6 into a 4 digits space
Left_padded(54, 5)
' 54' #number 54 into a 5 digits space
You can use rjust:
>>> def Left_padded(n, width):
... return str(n).rjust(width)
>>> Left_padded(54, 5)
' 54'
Assuming you want to put the number next to another string, you can also use % formatting to achieve the same result:
>>> w1 = "your number is:"
>>> num = 20
>>> line = '%s%10s' % (w1, num)
>>> print(line)
'your number is: 20'
Related
I can reverse a string using the [::- 1] syntax. Take note of the example below:
text_in = 'I am 25 years old'
rev_text = text_in[::-1]
print rev_text
Output:
dlo sraey 52 ma I
How can I reverse only the letters while keeping the numbers in order?
The desired result for the example is 'dlo sraey 25 ma I'.
Here's an approach with re:
>>> import re
>>> text_in = 'I am 25 years old'
>>> ''.join(s if s.isdigit() else s[::-1] for s in reversed(re.split('(\d+)', text_in)))
'dlo sraey 25 ma I'
>>>
>>> text_in = 'Iam25yearsold'
>>> ''.join(s if s.isdigit() else s[::-1] for s in reversed(re.split('(\d+)', text_in)))
'dlosraey25maI'
Using split() and join() along with str.isdigit() to identify numbers :
>>> s = 'I am 25 years old'
>>> s1 = s.split()
>>> ' '.join([ ele if ele.isdigit() else ele[::-1] for ele in s1[::-1] ])
=> 'dlo sraey 25 ma I'
NOTE : This only works with numbers that are space separated. For others, check out timegeb's answer using regex.
Here is a step by step approach:
text_in = 'I am 25 years old'
text_seq = list(text_in) # make a list of characters
text_nums = [c for c in text_seq if c.isdigit()] # extract the numbers
num_ndx = 0
revers = []
for idx, c in enumerate(text_seq[::-1]): # for each char in the reversed text
if c.isdigit(): # if it is a number
c = text_nums[num_ndx] # replace it by the number not reversed
num_ndx += 1
revers.append(c) # if not a number, preserve the reversed order
print(''.join(revers)) # output the final string
Output :
dlo sraey 25 ma I
You can do it in pythonic way straight forward like below..
def rev_except_digit(text_in):
rlist = text_in[::-1].split() #Reverse the whole string and split into list
for i in range(len(rlist)): # Again reverse only numbers
if rlist[i].isdigit():
rlist[i] = rlist[i][::-1]
return ' '.join(rlist)
Test:
Original: I am 25 years 345 old 290
Reverse: 290 dlo 345 sraey 25 ma I
you can find official python doc here split() and other string methods, slicing[::-1]
text = "I am 25 years old"
new_text = ''
text_rev = text[::-1]
for i in text_rev.split():
if not i.isdigit():
new_text += i + " ";
else:
new_text += i[::-1] + " ";
print(new_text)
I want a code to return sum of all similar sequences in two string. I wrote the following code but it only returns one of them
from difflib import SequenceMatcher
a='Apple Banana'
b='Banana Apple'
def similar(a,b):
c = SequenceMatcher(None,a.lower(),b.lower()).get_matching_blocks()
return sum( [c[i].size if c[i].size>1 else 0 for i in range(0,len(c)) ] )
print similar(a,b)
and the output will be
6
I expect it to be: 11
get_matching_blocks() returns the longest contiguous matching subsequence. Here the longest matching subsequence is 'banana' in both the strings, with length 6. Hence it is returning 6.
Try this instead:
def similar(a,b):
c = 'something' # Initialize this to anything to make the while loop condition pass for the first time
sum = 0
while(len(c) != 1):
c = SequenceMatcher(lambda x: x == ' ',a.lower(),b.lower()).get_matching_blocks()
sizes = [i.size for i in c]
i = sizes.index(max(sizes))
sum += max(sizes)
a = a[0:c[i].a] + a[c[i].a + c[i].size:]
b = b[0:c[i].b] + b[c[i].b + c[i].size:]
return sum
This "subtracts" the matching part of the strings, and matches them again, until len(c) is 1, which would happen when there are no more matches left.
However, this script doesn't ignore spaces. In order to do that, I used the suggestion from this other SO answer: just preprocess the strings before you pass them to the function like so:
a = 'Apple Banana'.replace(' ', '')
b = 'Banana Apple'.replace(' ', '')
You can include this part inside the function too.
When we edit your code to this it will tell us where 6 is coming from:
from difflib import SequenceMatcher
a='Apple Banana'
b='Banana Apple'
def similar(a,b):
c = SequenceMatcher(None,a.lower(),b.lower()).get_matching_blocks()
for block in c:
print "a[%d] and b[%d] match for %d elements" % block
print similar(a,b)
a[6] and b[0] match for 6 elements
a[12] and b[12] match for 0 elements
I made a small change to your code and it is working like a charm, thanks #Antimony
def similar(a,b):
a=a.replace(' ', '')
b=b.replace(' ', '')
c = 'something' # Initialize this to anything to make the while loop condition pass for the first time
sum = 0
i = 2
while(len(c) != 1):
c = SequenceMatcher(lambda x: x == ' ',a.lower(),b.lower()).get_matching_blocks()
sizes = [i.size for i in c]
i = sizes.index(max(sizes))
sum += max(sizes)
a = a[0:c[i].a] + a[c[i].a + c[i].size:]
b = b[0:c[i].b] + b[c[i].b + c[i].size:]
return sum
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.
I have a column formatting issue:
from math import sqrt
n = raw_input("Example Number? ")
n = float(n)
sqaureRootOfN = sqrt(n)
print '-'*50
print ' # of Decimals', '\t', 'New Root', '\t', 'Percent error'
print '-'*50
for a in range(0,10):
preRoot = float(int(sqaureRootOfN * 10**a))
newRoot = preRoot/10**a
percentError = (n - newRoot**2)/n*100
print ' ', a, '\t\t', newRoot, '\t\t', percentError, '%'
It comes out like:
Not in the same column!?!
#Bjorn has the right answer here, using the String.format specification. Python's string formatter has really powerful methods for aligning things properly. Here's an example:
from math import sqrt
n = raw_input("Example Number? ")
n = float(n)
sqaureRootOfN = sqrt(n)
print '-'*75
print ' # of Decimals', ' ' * 8, 'New Root', ' ' * 10, 'Percent error'
print '-'*75
for a in range(0,10):
preRoot = float(int(sqaureRootOfN * 10**a))
newRoot = preRoot/10**a
percentError = (n - newRoot**2)/n*100
print " {: <20}{: <25}{: <18}".format(a, newRoot, str(percentError) + ' %')
Note that instead of tabs I'm using spaces to space things out. This is because tabs are really not what you want to use here, because the rules for how tabs space things are inconsistent (and depend on what your terminal/viewer settings are).
This is what the answer looks like:
---------------------------------------------------------------------------
# of Decimals New Root Percent error
---------------------------------------------------------------------------
0 9.0 18.1818181818 %
1 9.9 1.0 %
2 9.94 0.198383838384 %
3 9.949 0.0175747474747 %
4 9.9498 0.00149490909092 %
5 9.94987 8.7861717162e-05 %
6 9.949874 7.45871112931e-06 %
7 9.9498743 1.4284843602e-06 %
8 9.94987437 2.14314187048e-08 %
9 9.949874371 1.33066711409e-09 %
Using str.format,
import math
n = float(raw_input("Example Number? "))
squareRootOfN = math.sqrt(n)
print('''\
{dashes}
{d:<16}{r:<15}{p:<}
{dashes}'''.format(dashes = '-'*50, d = ' # of Decimals', r = 'New Root', p = 'Percent error'))
for a in range(0,10):
preRoot = float(int(squareRootOfN * 10**a))
newRoot = preRoot/10**a
percentError = (n - newRoot**2)/n
print(' {d:<14}{r:<15}{p:13.9%}'.format(d = a, r = newRoot, p = percentError))
yields
--------------------------------------------------
# of Decimals New Root Percent error
--------------------------------------------------
0 9.0 18.181818182%
1 9.9 1.000000000%
2 9.94 0.198383838%
3 9.949 0.017574747%
4 9.9498 0.001494909%
5 9.94987 0.000087862%
6 9.949874 0.000007459%
7 9.9498743 0.000001428%
8 9.94987437 0.000000021%
9 9.949874371 0.000000001%
A few tricks/niceties:
Instead of three print statements, you can use one print statement on
a multiline string.
The percent symbol in the format {p:13.9%} lets you leave
percentError as a decimal (without multiplication by 100) and it
places the % at the end for you.
This is how tabs work. To get a correct formatting, you should use string.format. For your example, it could look like this:
print "{0:2d} {1:9.8f} {2:f} %".format(a, newRoot, percentError)
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'