Natural Binary Code - finding first n numbers - python

Outputting/finding first n numbers of Natural Binary Code:
import math
def binary_print(n):
m = int(math.ceil(math.log(n, 2)))
for i in range(n):
b = str(bin(i)[2:])
print((m - len(b)) * '0' + b)
My question is:
Do you know any other way to do this in Python? Maybe faster? Or shorter (less code)?

Well this is shorter, not sure about faster:
def binary_print(n):
print '\n'.join('{:0{}b}'.format(x, (n-1).bit_length()) for x in range(n))
Example usage:
>>> binary_print(6)
000
001
010
011
100
101

def binary_values(n):
fmt = "{0:0"+str((n-1).bit_length())+"b}"
for i in range(n):
print fmt.format(i)
Note: (n-1).bit_length() fixes a fencepost error (otherwise if n is a power of two it prints 1 too many leading zeros).
Might also be able to speed it up a bit more by unrolling a lookup,
def binary_values(n):
fmt = ("{0:0"+str((n-1).bit_length())+"b}").format
for i in range(n):
print fmt(i)

Related

Python removing first 3 digits in a number

Hopefully a simple one, I have a number, say 1234567.890 this number could be anything but will be this length.
How do I truncate the first 3 numbers so it turns into 4567.890?
This could be any number so subtracting 123000 will not work.
I'm working with map data in UTM coordinates (but that should not matter)
Example
x = 580992.528
y = 4275267.719
For x, I want 992.528
For y, I want 267.719
Note: y has an extra digit to the left of the decimal so 4 need removing
You can use slices for this:
x = 1234567.890
# This is still a float
x = float(str(x)[3:])
print(x)
Outputs:
4567.89
As [3:] gets the starts the index at 3 and continues to the end of the string
Update after your edit
The simplest way is to use Decimal:
from decimal import Decimal
def fmod(v, m=1000, /):
return float(Decimal(str(v)) % m)
print(fmod(x))
print(fmod(y))
Output
992.528
267.719
If you don't use string, you will have some problems with floating point in Python.
Demo:
n = 1234567.890
i = 0
while True:
m = int(n // 10**i)
if m < 1000:
break
i += 1
r = n % 10**i
Output:
>>> r
4567.889999999898
>>> round(r, 3)
4567.89
Same with Decimal from decimal module:
from decimal import Decimal
n = 1234567.890
n = Decimal(str(n))
i = 0
while True:
m = int(n // 10**i)
if m < 1000:
break
i += 1
r = n % 10**i
Output:
>>> r
Decimal('4567.89')
>>> float(r)
4567.89
This approach simply implements your idea.
int_len is the length of the integer part that we keep
sub is the rounded value that we will subtract the original float by
Code
Here is the code that implements your idea.
import math
def trim(n, digits):
int_len = len(str(int(n))) - digits # length of 4567
sub = math.floor(n / 10 **int_len) * 10**int_len
print(n - sub)
But as Kelly Bundy has pointed out, you can use modulo operation to avoid the complicated process of finding the subtrahend.
def trim(n, digits):
int_len = len(str(int(n))) - digits # length of 4567
print(n % 10**int_len)
Output
The floating point thing is a bit cursed and you may want to take Corralien's answer as an alternative.
>>> n = 1234567.890
>>> trim(n, 3)
4567.889999999898
def get_slice(number, split_n):
return number - (number // 10**split_n) * 10**split_n

Calculating a^b mod p for a large prime p

I'm trying to write a python code that calculates a^b mod p, where p = 10^9+7 for a list of pairs (a,b). The challenge is that the code has to finish the calculation and output the result in < 1 second. I've implemented successive squaring to calculate a^b mod p quickly. Please see my code below:
from sys import stdin, stdout
rl = stdin.readline
wo = stdout.write
m = 10**9+7
def fn(a,n):
t = 1
while n > 0:
if n%2 != 0: #exponent is odd
t = t*a %m
a = a*a %m
n = int(n/2)
return t%m
t = int(rl()) # number of pairs
I = stdin.read().split() # reading all pairs
I = list(map(int,I)) # making pairs a list of integers
# calculating a^b mod p. I used map because I read its faster than a for loop
s = list(map(fn,I[0:2*t:2],I[1:2*t:2]))
stdout.write('\n'.join(map(str,s))) # printing output
for 200000 pairs (a,b) with a,b<10^9, my code takes > 1 second. I'm new to python and was hoping someone could help me identify the time bottle neck in my code. Is it reading input and printing output or the calculation itself? Thanks for the help!
I don't see something wrong with your code from an efficiency standpoint, it's just unnecessarily complicated.
Here's what I'd call the straight-forward solution:
n = int(input())
for _ in range(n):
a, b = map(int, input().split())
print(pow(a, b, 10**9 + 7))
That did get accepted with PyPy3 but not with CPython3. And with PyPy3 it still took 0.93 seconds.
I'd say their time limit is inappropriate for Python. But try yours with PyPy3 if you haven't yet.
In case someone's wondering whether the map wastes time, the following got accepted in 0.92 seconds:
n = int(input())
for _ in range(n):
a, b = input().split()
print(pow(int(a), int(b), 10**9 + 7))

calculating factorial of large numbers in 0.5 second with python

I've been trying to find a super fast code that can calculate the factorial of a big number like 70000 in 0.5 second,My own code could do it in 10 seconds.I've searched everywhere, every code I find has memory error problem or is not as fast as I want. Can anyone help me with this?
enter code here
import math
num =int(raw_input())
usefrm=0
if len(str(num)) > 2:
if int(str(num)[-2]) % 2 == 0:
usefrm = 'even'
else:
usefrm = 'odd'
else:
if num % 2 == 0:
usefrm = 'even1'
else:
usefrm = 'odd1'
def picknumber(num):
s = str(math.factorial(num))
l = []
for n in s:
if int(n) != 0:
l.append(int(n))
return l[-1]
def picknumber1(num):
s = str(num)
l = []
for n in s:
if int(n) != 0:
l.append(int(n))
return l[-1]
if usefrm == 'even':
e=picknumber1(6*picknumber(int(num/5))*picknumber(int(str(num)[-1])))
if usefrm == 'odd':
e=picknumber1(4*picknumber(int(num/5))*picknumber(int(str(num)[-1])))
else:
e=picknumber1(math.factorial(num))
print e
For most practical use, the Stirling's approximation is very fast and quite accurate
import math
from decimal import Decimal
def fact(n):
d = Decimal(n)
return (Decimal(2 * math.pi) * d).sqrt() * (d / Decimal(math.e)) ** d
print(fact(70000))
1.176811014417743803074731978E+308759
Try to use the commutativity property of integer multiplication.
When multiplied numbers are long (they do not fit in a single word), the time necessary to perform the operation grows superlinearly with their length.
If you multiply the smallest (shortest in terms of memory representation) factors (and partial products) first, you may save a lot of time.
You may use math.factorial(). For example:
from math import factorial
factorial(7000)
with execution time of 20.5 msec for calculating the factorial of 7000:
python -m timeit -c "from math import factorial; factorial(7000)"
10 loops, best of 3: 20.5 msec per loop
If you don't want a perfect precision, you can use the Stirling's approximation
https://en.wikipedia.org/wiki/Stirling's_approximation
import np
n! ~ np.sqrt(2*np.pi*n)*(n/np.e)**n
for large n values. This calculation is literally instantaneous.
Maybe you can try to make use of threads.

Palindromic numbers in two bases, Project Euler #36

Here is my solution for Project Euler problem 36, which reads:
The decimal number, 585 = 1001001001₂ (binary), is palindromic in both bases.
Find the sum of all numbers, less than one million, which are palindromic in base 10 and base 2.
(Please note that the palindromic number, in either base, may not include leading zeros.)
My result is somehow wrong. Could anyone help?
def findnum(n):
a = 0
for i in range(0, n + 1):
temp = '{0:08b}'.format(i)
if str(i) == str(i)[::-1] and str(temp) == str(temp)[::-1]:
a += i
return a
print findnum(1000000)
The result I got is 872096, but the correct answer seems to be 872187. But the difference of these two, 91, is not a palindrome. What am I doing wrong?
You missed something in the problem description:
Please note that the palindromic number, in either base, may not include leading zeros.
Yet you are using leading zeros:
temp = '{0:08b}'.format(i)
Drop the 08 from the format; there is no need to pad it to a width at all here:
temp = '{0:b}'.format(i)
With this change you'll get the correct answer.
You may as well just use the format() function instead, as you are not putting the string into a larger template. You don't need to feed it to str() as format() already produces a string. I'd swap the tests to test for a binary palindrome first and avoid extra str() calls. The n + 1 in the range() call is not needed; the problem description asks for all such numbers below 1 million:
for i in range(n):
temp = format(i, 'b')
if temp == temp[::-1] and str(i) == str(i)[::-1]:
a += i
or you could first test for the decimal palindrome, then format:
for i in range(n):
decimal = str(i)
if decimal != decimal[::-1]:
continue
binary = format(i, 'b')
if binary == binary[::-1]:
a += i
This shaves off quite a few calls from the overall runtime, making the final version more than twice as fast:
>>> from timeit import timeit
>>> def findnum_orig(n):
... a = 0
... for i in range(0, n + 1):
... temp = '{0:b}'.format(i)
... if str(i) == str(i)[::-1] and str(temp) == str(temp)[::-1]:
... a += i
... return a
...
>>> def findnum_optimised(n):
... a = 0
... for i in range(n):
... decimal = str(i)
... if decimal != decimal[::-1]:
... continue
... binary = format(i, 'b')
... if binary == binary[::-1]:
... a += i
... return a
...
>>> timeit('fn(1000000)', 'from __main__ import findnum_orig as fn', number=10)
10.886759996414185
>>> timeit('fn(1000000)', 'from __main__ import findnum_optimised as fn', number=10)
3.7782959938049316
That's because str() is a lot faster than format():
>>> timeit('for i in range(1000): str(i)', number=1000)
0.17951107025146484
>>> timeit('for i in range(1000): format(i, 'b')', number=1000)
0.2837510108947754
As there are only 1999 decimal and 2000 binary palindromes below 1 million:
>>> sum(1 for i in range(1000000) if str(i) == str(i)[::-1])
1999
>>> sum(1 for i in range(1000000) if format(i, 'b') == format(i, 'b')[::-1])
2000
avoiding the slower operation all but those 1999 decimal palindromes saves you a lot of time.
We can make it faster still by switching how you convert the integer to binary; the bin() function produces a binary number too, albeit with the 0b prefix. Even with having to remove that prefix using that function is faster than using format():
>>> timeit('for i in range(1000): format(i, "b")', number=1000)
0.46987009048461914
>>> timeit('for i in range(1000): bin(i)[2:]', number=1000)
0.24124693870544434
and if you are using Python 2.x, you should also use the xrange() function to avoid creating a list with 1.000.000 integers. This brings the final timings to:
>>> def findnum_bin_xrange(n):
... a = 0
... for i in xrange(n):
... decimal = str(i)
... if decimal != decimal[::-1]:
... continue
... binary = bin(i)[2:]
... if binary == binary[::-1]:
... a += i
... return a
...
>>> findnum_bin_xrange(1000000)
872187
>>> timeit('fn(1000000)', 'from __main__ import findnum_bin_xrange as fn', number=10)
3.5071611404418945
That's down to about 1/3rd of your original code timings.
My solution is roughly 20 times faster than Martijn's.
The approach is also slightly different, using the fact that the number has to read the same backwards. Instead of checking all numbers to see if they are a palindrome, I generate them myself. This introduces some extra lines of code since you have to treat 3 different cases:
single digit (1,2,3 etc.),
even digit (4334,5115 etc.),
and uneven digit (121,87378 etc.) palindromes.
The main for-loop range can be reduced to 1000.
First all the Palindromic numbers (base10) are generated using the above strategy. The generated numbers are then checked in base2. If they are a palindromic number they are added to an array. (Further speed increase if you skip the array and just sum it in a variable.)
import time
#calculate digits
def digits(num):
return len(str(num))
#reverse order
def reverse(num):
return int(str(num)[::-1])
#check binary counterpartner
def bin_pal_chk(number):
b = int(bin(number)[2:])
if (b == reverse(b)):
return True
else:
return False
#list with all base 10 palindromes
palin = []
#calculate palindromes
t = time.clock()
for i in range(1,1000):
#single digits
if (i < 10):
if bin_pal_chk(i):
palin.append(i)
#even digits
num = i*10**digits(i) + reverse(i)
if bin_pal_chk(num):
palin.append(num)
#uneven digits
if (i < 100):
for j in range(10):
num = i*10**(digits(i)+1) + j*10**digits(i) + reverse(i)
if bin_pal_chk(num):
palin.append(num)
print time.clock() - t

Generating digits of square root of 2

I want to generate the digits of the square root of two to 3 million digits.
I am aware of Newton-Raphson but I don't have much clue how to implement it in C or C++ due to lack of biginteger support. Can somebody point me in the right direction?
Also, if anybody knows how to do it in python (I'm a beginner), I would also appreciate it.
You could try using the mapping:
a/b -> (a+2b)/(a+b) starting with a= 1, b= 1. This converges to sqrt(2) (in fact gives the continued fraction representations of it).
Now the key point: This can be represented as a matrix multiplication (similar to fibonacci)
If a_n and b_n are the nth numbers in the steps then
[1 2] [a_n b_n]T = [a_(n+1) b_(n+1)]T
[1 1]
which now gives us
[1 2]n [a_1 b_1]T = [a_(n+1) b_(n+1)]T
[1 1]
Thus if the 2x2 matrix is A, we need to compute An which can be done by repeated squaring and only uses integer arithmetic (so you don't have to worry about precision issues).
Also note that the a/b you get will always be in reduced form (as gcd(a,b) = gcd(a+2b, a+b)), so if you are thinking of using a fraction class to represent the intermediate results, don't!
Since the nth denominators is like (1+sqrt(2))^n, to get 3 million digits you would likely need to compute till the 3671656th term.
Note, even though you are looking for the ~3.6 millionth term, repeated squaring will allow you to compute the nth term in O(Log n) multiplications and additions.
Also, this can easily be made parallel, unlike the iterative ones like Newton-Raphson etc.
EDIT: I like this version better than the previous. It's a general solution that accepts both integers and decimal fractions; with n = 2 and precision = 100000, it takes about two minutes. Thanks to Paul McGuire for his suggestions & other suggestions welcome!
def sqrt_list(n, precision):
ndigits = [] # break n into list of digits
n_int = int(n)
n_fraction = n - n_int
while n_int: # generate list of digits of integral part
ndigits.append(n_int % 10)
n_int /= 10
if len(ndigits) % 2: ndigits.append(0) # ndigits will be processed in groups of 2
decimal_point_index = len(ndigits) / 2 # remember decimal point position
while n_fraction: # insert digits from fractional part
n_fraction *= 10
ndigits.insert(0, int(n_fraction))
n_fraction -= int(n_fraction)
if len(ndigits) % 2: ndigits.insert(0, 0) # ndigits will be processed in groups of 2
rootlist = []
root = carry = 0 # the algorithm
while root == 0 or (len(rootlist) < precision and (ndigits or carry != 0)):
carry = carry * 100
if ndigits: carry += ndigits.pop() * 10 + ndigits.pop()
x = 9
while (20 * root + x) * x > carry:
x -= 1
carry -= (20 * root + x) * x
root = root * 10 + x
rootlist.append(x)
return rootlist, decimal_point_index
As for arbitrary big numbers you could have a look at The GNU Multiple Precision Arithmetic Library (for C/C++).
For work? Use a library!
For fun? Good for you :)
Write a program to imitate what you would do with pencil and paper. Start with 1 digit, then 2 digits, then 3, ..., ...
Don't worry about Newton or anybody else. Just do it your way.
Here is a short version for calculating the square root of an integer a to digits of precision. It works by finding the integer square root of a after multiplying by 10 raised to the 2 x digits.
def sqroot(a, digits):
a = a * (10**(2*digits))
x_prev = 0
x_next = 1 * (10**digits)
while x_prev != x_next:
x_prev = x_next
x_next = (x_prev + (a // x_prev)) >> 1
return x_next
Just a few caveats.
You'll need to convert the result to a string and add the decimal point at the correct location (if you want the decimal point printed).
Converting a very large integer to a string isn't very fast.
Dividing very large integers isn't very fast (in Python) either.
Depending on the performance of your system, it may take an hour or longer to calculate the square root of 2 to 3 million decimal places.
I haven't proven the loop will always terminate. It may oscillate between two values differing in the last digit. Or it may not.
The nicest way is probably using the continued fraction expansion [1; 2, 2, ...] the square root of two.
def root_two_cf_expansion():
yield 1
while True:
yield 2
def z(a,b,c,d, contfrac):
for x in contfrac:
while a > 0 and b > 0 and c > 0 and d > 0:
t = a // c
t2 = b // d
if not t == t2:
break
yield t
a = (10 * (a - c*t))
b = (10 * (b - d*t))
# continue with same fraction, don't pull new x
a, b = x*a+b, a
c, d = x*c+d, c
for digit in rdigits(a, c):
yield digit
def rdigits(p, q):
while p > 0:
if p > q:
d = p // q
p = p - q * d
else:
d = (10 * p) // q
p = 10 * p - q * d
yield d
def decimal(contfrac):
return z(1,0,0,1,contfrac)
decimal((root_two_cf_expansion()) returns an iterator of all the decimal digits. t1 and t2 in the algorithm are minimum and maximum values of the next digit. When they are equal, we output that digit.
Note that this does not handle certain exceptional cases such as negative numbers in the continued fraction.
(This code is an adaptation of Haskell code for handling continued fractions that has been floating around.)
Well, the following is the code that I wrote. It generated a million digits after the decimal for the square root of 2 in about 60800 seconds for me, but my laptop was sleeping when it was running the program, it should be faster that. You can try to generate 3 million digits, but it might take a couple days to get it.
def sqrt(number,digits_after_decimal=20):
import time
start=time.time()
original_number=number
number=str(number)
list=[]
for a in range(len(number)):
if number[a]=='.':
decimal_point_locaiton=a
break
if a==len(number)-1:
number+='.'
decimal_point_locaiton=a+1
if decimal_point_locaiton/2!=round(decimal_point_locaiton/2):
number='0'+number
decimal_point_locaiton+=1
if len(number)/2!=round(len(number)/2):
number+='0'
number=number[:decimal_point_locaiton]+number[decimal_point_locaiton+1:]
decimal_point_ans=int((decimal_point_locaiton-2)/2)+1
for a in range(0,len(number),2):
if number[a]!='0':
list.append(eval(number[a:a+2]))
else:
try:
list.append(eval(number[a+1]))
except IndexError:
pass
p=0
c=list[0]
x=0
ans=''
for a in range(len(list)):
while c>=(20*p+x)*(x):
x+=1
y=(20*p+x-1)*(x-1)
p=p*10+x-1
ans+=str(x-1)
c-=y
try:
c=c*100+list[a+1]
except IndexError:
c=c*100
while c!=0:
x=0
while c>=(20*p+x)*(x):
x+=1
y=(20*p+x-1)*(x-1)
p=p*10+x-1
ans+=str(x-1)
c-=y
c=c*100
if len(ans)-decimal_point_ans>=digits_after_decimal:
break
ans=ans[:decimal_point_ans]+'.'+ans[decimal_point_ans:]
total=time.time()-start
return ans,total
Python already supports big integers out of the box, and if that's the only thing holding you back in C/C++ you can always write a quick container class yourself.
The only problem you've mentioned is a lack of big integers. If you don't want to use a library for that, then are you looking for help writing such a class?
Here's a more efficient integer square root function (in Python 3.x) that should terminate in all cases. It starts with a number much closer to the square root, so it takes fewer steps. Note that int.bit_length requires Python 3.1+. Error checking left out for brevity.
def isqrt(n):
x = (n >> n.bit_length() // 2) + 1
result = (x + n // x) // 2
while abs(result - x) > 1:
x = result
result = (x + n // x) // 2
while result * result > n:
result -= 1
return result

Categories