incrementing to numbers that are led by zeros - python

There are many questions regarding to turning an integer to a number led by zeros, But i couldn't find any solutions to incrementing string that is already led by zeros.
Python already transforms number led by zero to normal integer:
>>> 0001
1
>>> int(0001)
1
By considering that, whenever i add two numbers led by zero to each other, i get a normal integer:
>>> 0001 + 0001
2
>>> int('0001') + int('0001')
2
But, what i am trying to find out is for example, how to get a sum such as 0002 when adding two 0001's to each other.
Obviously it should be printed out as string type, since Python transforms number led by zero to normal integer.
Please also consider some cases like this:
x = 0001
How can i increment x by 1 without specifying zeros?
Is there any Pythonic way to do this? With solution working on all cases of numbers led by zero? ('0001' + '0001' == '0002' and '01' + '01' == '02', For example).

If the strings have the same length, you can simply apply zfill on the output using the length of one of the operands:
def add(x, y) -> str: # remove type hint for Python 2
return str(int(x) + int(y)).zfill(len(x))
print(add('0001', '0025'))
# '0026'
To accomodate string inputs of mismatching lengths, you can pass max(len(x), len(y)) to zfill so that the output is zero padded using the length of the longer string:
def add(x, y) -> str:
return str(int(x) + int(y)).zfill(max(len(x), len(y)))
print(add('0001', '25'))
# 0026

How about this:
x = '00001'
y = '00002'
print '{0:0{width}}'.format(int(x)+int(y), width=max(len(x), len(y)))
prints 00003

Related

Python while loop not working as intended

I don't know how to get over this problem with while loop.
So basically I want to return the number of zeros at the end of a number's factorial.
import math
def zeros(n):
total_zero = 0
n = math.factorial(n)
while str(n)[-1] == '0': # to check if the last number is 0 or not
n = n * 0.1
total_zero += 1
return total_zero
output = zeros(30)
print(output)
After the while loop runs only 1 time, it breaks; I don't know why.
Help would be very appreciated. Thanks!
After multiplying your value by 0.1 it becomes a float, and it's string representation becomes the scientific notation 2.6525285981219107e+31 which doesn't end by a 1
You'd better do the integer division by 10 to keep an int
def zeros(n):
total_zero = 0
n = math.factorial(n)
while str(n)[-1] == '0': # to check if the last number is 0 or not
n = n // 10
total_zero += 1
print(f"testting {str(n)}")
return total_zero
>> zeros(30)
testting 26525285981219105863630848000000
testting 2652528598121910586363084800000
testting 265252859812191058636308480000
testting 26525285981219105863630848000
testting 2652528598121910586363084800
testting 265252859812191058636308480
testting 26525285981219105863630848
7
Better You can also use str.rstrip : you remove the leading zeros and check the length difference
def zeros(n):
value = str(math.factorial(n))
return len(value) - len(value.rstrip("0"))
My first answer above was literally solving the question that the user asked: "Why doesn't my code work?" But there is a much much simpler way of solving the question "How many zeros does n! have at the end" which is so simple you can do the math in your head.
Look at the prime factorization of any number f. To get a "0" at the end of a number, you must have 2 x 5 in the prime factorization. So the number of zeros at the end of f is just the minimum of the number of 2s and the number of 5s in the prime factorization. For factorials, you always get more factors of 2 than of 5, so we're down to the question: How many 5s are there in the prime factorization of n!
That's easy! Legendre's formula says it is:
floor(n/5) + floor(n/25) + floor(n/125) + ...
and although this is an infinite series, after a couple of terms, they're all zero. For 30!, you get 6 + 1 + 0 + 0 + ... = 7.
If asked how many 0s there are at the end of 1000!, the answer is `200 + 40 + 8 + 1 = 249'
Why didn't you bother to do any debugging? See this lovely debugging site for help. A simple print to trace n shows the problem.
You're doing a float computation on an integer; the result you get back is not guaranteed to be exact. Instead, use
n = n // 10
After you multiply by .1, you have a floating point number. You will be losing precision with a number as large as 30! You want to divide by 10 using //.
Also rather than looking at the last digit in the string, you can just look at the number mod 10. Much faster
In python, the * operator on an int and float outputs a float. Casting to str converts long floats into scientific notation. Therefore on your second iteration you have:
> str(math.factorial(30)*.1)
'2.6525285981219107e+31'
> str(math.factorial(30)*.1)[-1]
'1'
Since math.factorial always returns an int, which str converts to a string of the full integer value, you might try first converting the output of math.factorial to a string, and then iterating backward through that string. Something like:
def count_zeros(n):
count = 0
n = str(math.factorial(n))
while n[-1] == '0':
count += 1
n = n[:-1]
return count
This could be solved a bit more compactly as follows
from math import factorial
from itertools import takewhile
def zeros(n):
return sum(1 for _ in takewhile(lambda i: i == '0', reversed(str(factorial(n)))))
For example
>>> zeros(30)
7
This basically computes the factorial, converts that to a string, then counts the '0' characters from the string backwards until it encounters a non-zero character.

Converting decimal number to binary in Python

I am writing a program that converts a decimal number into a binary. I made it that far and I stuck with a problem. In the code with print(aa).
I tried to get a binary form of given number but it prints 1. I think I have "return" function problem here how can I solve it. Also, when I print binaryform it prints like the way below. Shouldn't it print reversely I mean first 1 and then 11 and then 111 .......10111.
# Python program to convert decimal number into binary number using recursive function
def binary(n, binaryform,i):
if n >= 1:
digit= n % 2
binaryform += digit*i
#print(binaryform)
i*=10
binary(n/2, binaryform, i)
print("xxx", binaryform)
return binaryform
dec = int(input("Enter an integer: "))# Take decimal number from user
aa = binary(dec, 0, 1)
print(aa)
OUTPUT:
Enter an integer: 23
('xxx', 10111)
('xxx', 111)
('xxx', 111)
('xxx', 11)
('xxx', 1)
1
Convert an integer number to a binary string. The result is a valid Python expression. If x is not a Python int object, it has to define an index() method that returns an integer. Python Documentation
You're writing a recursive function - that's fun and good.
Now consider what you do: you check the LOW part of the number. If the LOW part of the number is 1 or 0 you do something, but then you shrink the number and recurse, checking a new LOW part, but the new low part came from a HIGHER part originally.
So whatever you determine should actually be at the end of the string, not the beginning, when you come back from recursion.
That's your question about printing reversely, I think. And yes, except you should just assemble it reversely, and then print it normally.
Also, you're actually trying to construct a decimal integer that will print out as if it were a binary number. It would be a lot simpler if you just constructed a string: "10101".
If you just want to convert integer to binary, try this code here . It looks like this :
def binary(n):
b = ''
while n > 0:
b = str(n % 2) + b
n >>= 1
print(b)
binary(10)

HackerRank "AND product"

When I submit the below code for testcases in HackerRank challenge "AND product"...
You will be given two integers A and B. You are required to compute the bitwise AND amongst all natural numbers lying between A and B, both inclusive.
Input Format:
First line of the input contains T, the number of testcases to follow.
Each testcase in a newline contains A and B separated by a single space.
from math import log
for case in range(int(raw_input())):
l, u = map(int, (raw_input()).split())
if log(l, 2) == log(u, 2) or int(log(l,2))!=int(log(l,2)):
print 0
else:
s = ""
l, u = [x for x in str(bin(l))[2:]], [x for x in str(bin(u))[2:]]
while len(u)!=len(l):
u.pop(0)
Ll = len(l)
for n in range(0, len(l)):
if u[n]==l[n]:
s+=u[n]
while len(s)!=len(l):
s+="0"
print int(s, 2)
...it passes 9 of the test cases, Shows "Runtime error" in 1 test case and shows "Wrong Answer" in the rest 10 of them.
What's wrong in this?
It would be better for you to use the Bitwise operator in Python for AND. The operator is: '&'
Try this code:
def andProduct(a, b):
j=a+1
x=a
while(j<=b):
x = x&j
j+=1
return x
For more information on Bitwise operator you can see: https://wiki.python.org/moin/BitwiseOperators
Yeah you can do this much faster.
You are doing this very straightforward, calculating all ands in a for loop.
It should actually be possible to calculate this in O(1) (I think)
But here are some optimisations:
1) abort the for loop if you get the value 0, because it will stay 0 no matter what
2)If there is a power of 2 between l and u return 0 (you don't need a loop in that case)
My Idea for O(1) would be to think about which bits change between u and l.
Because every bit that changes somewhere between u and l becomes 0 in the answer.
EDIT 1: Here is an answer in O(same leading digits) time.
https://math.stackexchange.com/questions/1073532/how-to-find-bitwise-and-of-all-numbers-for-a-given-range
EDIT 2: Here is my code, I have not tested it extensively but it seems to work. (O(log(n))
from math import log
for case in [[i+1,j+i+1] for i in range(30) for j in range(30)]:
#Get input
l, u = case
invL=2**int(log(l,2)+1)-l
invU=2**int(log(u,2)+1)-u
#Calculate pseudo bitwise xnor of input and format to binary rep
e=format((u&l | invL & invU),'010b')
lBin=format(l,'010b')
#output to zero
res=0
#boolean to check if we have found any zero
anyZero=False
#boolean to check the first one because we have leading zeros
firstOne=False
for ind,i in enumerate(e):
#for every digit
#if it is a leading one
if i=='1' and (not anyZero):
firstOne=True
#leftshift result (multiply by 2)
res=res<<1
#and add 1
res=res+int(lBin[ind])
#else if we already had a one and find a zero this happens every time
elif(firstOne):
anyZero=True
#leftshift
res=res<<1
#test if we are in the same power, if not there was a power between
if(res!=0):
#print "test",(int(log(res,2))!=int(log(l,2))) | ((log(res,2))!=int(log(u,2)))
if((int(log(res,2))!=int(log(l,2))) or (int(log(res,2))!=int(log(u,2)))):
res=0
print res
Worked for every but a single testcase. Small change needed to get the last one. You'll have to find out what that small change is yourself. Seriously

Python: How to convert a string of zeros and ones to binary [duplicate]

I'd simply like to convert a base-2 binary number string into an int, something like this:
>>> '11111111'.fromBinaryToInt()
255
Is there a way to do this in Python?
You use the built-in int() function, and pass it the base of the input number, i.e. 2 for a binary number:
>>> int('11111111', 2)
255
Here is documentation for Python 2, and for Python 3.
Just type 0b11111111 in python interactive interface:
>>> 0b11111111
255
Another way to do this is by using the bitstring module:
>>> from bitstring import BitArray
>>> b = BitArray(bin='11111111')
>>> b.uint
255
Note that the unsigned integer (uint) is different from the signed integer (int):
>>> b.int
-1
Your question is really asking for the unsigned integer representation; this is an important distinction.
The bitstring module isn't a requirement, but it has lots of performant methods for turning input into and from bits into other forms, as well as manipulating them.
Using int with base is the right way to go. I used to do this before I found int takes base also. It is basically a reduce applied on a list comprehension of the primitive way of converting binary to decimal ( e.g. 110 = 2**0 * 0 + 2 ** 1 * 1 + 2 ** 2 * 1)
add = lambda x,y : x + y
reduce(add, [int(x) * 2 ** y for x, y in zip(list(binstr), range(len(binstr) - 1, -1, -1))])
If you wanna know what is happening behind the scene, then here you go.
class Binary():
def __init__(self, binNumber):
self._binNumber = binNumber
self._binNumber = self._binNumber[::-1]
self._binNumber = list(self._binNumber)
self._x = [1]
self._count = 1
self._change = 2
self._amount = 0
print(self._ToNumber(self._binNumber))
def _ToNumber(self, number):
self._number = number
for i in range (1, len (self._number)):
self._total = self._count * self._change
self._count = self._total
self._x.append(self._count)
self._deep = zip(self._number, self._x)
for self._k, self._v in self._deep:
if self._k == '1':
self._amount += self._v
return self._amount
mo = Binary('101111110')
Here's another concise way to do it not mentioned in any of the above answers:
>>> eval('0b' + '11111111')
255
Admittedly, it's probably not very fast, and it's a very very bad idea if the string is coming from something you don't have control over that could be malicious (such as user input), but for completeness' sake, it does work.
A recursive Python implementation:
def int2bin(n):
return int2bin(n >> 1) + [n & 1] if n > 1 else [1]
If you are using python3.6 or later you can use f-string to do the
conversion:
Binary to decimal:
>>> print(f'{0b1011010:#0}')
90
>>> bin_2_decimal = int(f'{0b1011010:#0}')
>>> bin_2_decimal
90
binary to octal hexa and etc.
>>> f'{0b1011010:#o}'
'0o132' # octal
>>> f'{0b1011010:#x}'
'0x5a' # hexadecimal
>>> f'{0b1011010:#0}'
'90' # decimal
Pay attention to 2 piece of information separated by colon.
In this way, you can convert between {binary, octal, hexadecimal, decimal} to {binary, octal, hexadecimal, decimal} by changing right side of colon[:]
:#b -> converts to binary
:#o -> converts to octal
:#x -> converts to hexadecimal
:#0 -> converts to decimal as above example
Try changing left side of colon to have octal/hexadecimal/decimal.
For large matrix (10**5 rows and up) it is better to use a vectorized matmult. Pass in all rows and cols in one shot. It is extremely fast. There is no looping in python here. I originally designed it for converting many binary columns like 0/1 for like 10 different genre columns in MovieLens into a single integer for each example row.
def BitsToIntAFast(bits):
m,n = bits.shape
a = 2**np.arange(n)[::-1] # -1 reverses array of powers of 2 of same length as bits
return bits # a
For the record to go back and forth in basic python3:
a = 10
bin(a)
# '0b1010'
int(bin(a), 2)
# 10
eval(bin(a))
# 10

How to perform addition and division in python

I want to get the sum of all numbers within a list. My code is shown below; however, I am getting an error when I try to run it:
c = [795557,757894,711411,556286,477322,426243,361643,350722]
for c1 in c:
x = x + c1
I am also trying to divide one number by another. However, the result is always zero:
y=(273591/21247633)*100
In the first case, you need to define x before you use it and use c1 instead of c:
x = 0
c=[795557,757894,711411,556286,477322,426243,361643,350722]
for c1 in c:
x=x+c1
print x
You can try this code online here.
In the second case, you need to use floating point numbers instead of integers:
y=(273591/21247633.0)*100
print y
This is because the result of an integer-integer division in Python 2.x is also an integer. In this case, 273591 รท 21247633 = 0.0128763048571 so the result is rounded down to 0.
This has changed in Python 3.x, and you can enable the same behavior in Python 2.x as follows:
from __future__ import division
y=(273591/21247633)*100
print y
You forgot to initialize x to 0 and this statement should be x = x + c1 and not x = x + c
Probably those numbers are used as integers. Using their float value should help.
y = (float(273591)/21247633)*100
If you want to get a sum of numbers in a list, then use sum:
c = [795557,757894,711411,556286,477322,426243,361643,350722]
x = sum(c)
For the second one, int/int returns an int rounded down, so 273591/21247633 returns 0. Convert one (or all) of the numbers to float and it will work as awaited:
y = (273591. / 21247633.) * 100.

Categories