Improving perfomance(speed) of exponent problem - python

I'm currently learning Python on repl.it and I have a problem with one of my work.
My code is supposed to:
1.Input a given integer X
2.Find the greatest integer n where 2ⁿ is less than or equal to X.
3.Print the exponent value(n) and the result of the expression 2ⁿ.
But my code fail as the machine insert too big number like 10^8+2. The program completely failed
Here is the piece of code that I'm working on:
X = int(input())
a = X//2
while a > -1:
if (2**a) < =x:
print(a)
print(2**a)
break
else:
a -= 1
Can anyone find me another solution to this problem, or improve the bit of code I'm working on by its runtime? It works with small number(less than 10^6) but otherwise the program freeze.
Thanks in advance!

Of course, I can't refer to the "too big input" that you mention (since you didn't provide it), but as for the problem itself, it could be easier solved in the following way:
import numpy as np
a = int(np.log2(your_input))

The first issue I see is that in you code
if (2**a) < =x:
print(a)
print(2**a)
you calculate the value of 2**a twice. A good start could be to save the value of 2**a into a variable. However, since you are only doing powers of 2 you could also take a look at bitwise operations. So instead of doing a = X//2 you could also write
a= X >> 2
and instead of doing 2**a write
temp = 1 << a
When working with powers of 2 it can be significantly faster to work with bitwise operations.

I did it! (using some of your solutions of course)
This is my teachers code :
x = int(input())
n = 1
while 2 ** n <= x:
n += 1
print(n - 1, 2 ** (n - 1))

Related

Why do these python and kotlin functions perform differently on hackerrank?

I am trying to solve a contest challenge on Hackerrank (Hack the Interview II - Global Product Distribution) using Kotlin
I started getting annoyed because my code always passed on the test cases with a small number of inputs and failed on the larger ones, even timing out on one.
So I went online and found this python code that solved all test cases neatly. I went as far as converting the Python code line for line into Kotlin. But my Kotlin code always retained the same poor performance as before.
These are the two pieces of code.
Python:
def maxScore(a, m):
a.sort()
print(a)
x=len(a)
if x%m==0:
y=int(x/m)
else:
y=int(x/m)-1
summ=0
count=1
#print(y)
i=0
for _ in range(y):
summ=summ+(sum(a[i:i+m])*count)
count=count+1
i=i+m
print(summ)
summ=summ+sum(a[i:])*count
print(summ)
return summ%1000000007
Kotlin:
fun maxScore(a: Array<Int>, m: Int): Int {
a.sort()
// print(a)
val x = a.size
val y = if (x % m == 0) x / m
else (x / m) - 1
var summ = 0
var count = 1
// print(y)
var i = 0
for (s in 0 until y) {
summ += a.sliceArray(i until (i + m)).sum() * count
count++
i += m
// print(summ)
}
summ += a.sliceArray(i until a.size).sum() * count
// print(summ)
return summ % 1000000007
}
Is there something wrong with the code translation? How can I make the Kotlin code work on the larger test cases?
UPDATE: copyOfRange() performs better than sliceArray(). Code no longer times out on any test case, but still fails on all the large test cases
There's three issues I can see here. I'll point you in the right direction for now.
Both the Python and the Kotlin copy the array each time. This might or might not be a problem. You have up to a million elements and each is copied only once. I'd be surprised if that exceeds your time limits but it might do. It looks like you can avoid the copy with .subList().
It looks like you're treating the leftover items as if they're in a bin of their own. But this bin is smaller than m, which isn't allowed. Check that this is really what you intend.
Kotlin Ints are 32-bit signed integers. You can only store numbers up to about 2 billion before they overflow. You need to avoid this! Look at the constraints - you can have up to a million products with individual values up to a billion each. (This is different from Python ints, which never overflow, and so will always give the right answer, but can use a lot of memory and slow down if you try to do operations on really big numbers, which might well be causing your program to time out.) Here is a hint: (a + b) % n is equal to ((a % n) + (b % n)) % n

Python while loop speed

I would like it if someone could please explain to me why the following code has so much additional overhead. At 100k iterations, the speed is the same for either case (2.2 sec). When increasing to 1E6 iterations case "B" never finishes, while case "A" takes only 29 seconds.
Case "A"
while n is not 1:
foo
Case "B"
while n > 1:
foo
Complete code if of any help
def coll(n):
count = 0
# while n is not 1:
while n > 1:
count += 1
if not n % 2:
n /= 2
else:
n = 3*n + 1
return count
for x in range(1,100000):
count = coll(x)
First of all, you should use n > 1 or n != 1, not n is not 1. The fact that the latter works is an implementation detail, and obviously it's not working for you.
The reason it's not working is because there are values of x in your code that cause the Collatz sequence to go over the value of sys.maxint, which turns n into a long. Then, even when it ends up going back down to 1, it's actually 1L; a long, not an int.
Try using while n is not 1 and repr(n) != '1L':, and it'll work as you expect. But don't do that; just use n > 1 or n != 1.
Generally in Python, is is extremely fast to check, as it uses referential equality, so all that needs to be checked is that two objects have the same memory location. Note that the only reason your code works is that most implementations of Python generally maintain a pool of the smaller integers, so that every 1 always refers to the same 1, for example, where there may be multiple objects representing 1000. In those cases, n is 1000 would fail, where n == 1000 would work. Your code is relying on this integer pool, which is risky.
> involves a function call, which is fairly slow in Python: n > 1 translates to n.__gt__(1).

how to multiply all the numbers in a sequence (python)

Like if i told the program n=10, how would I make it return 10*9*8*7*6*5....1?
I thought a while loop but I feel I messed up somewhere because it doesn't sum up all of the numbers in the sequence.
My current code looks like this
def product(n):
i=n
a=n-1
while a>0:
return i * a
b=i * a
a=a-1
i=i-1
Are there any better ways to do it without using recursion? Sorry for the incredibly beginner question, but I'm trying to teach myself how to code. You gotta start somewhere!
Thanks!
Since you are trying to learn to code, I won't give you a total solution, but
I'll give you a few hints instead:
Have a for loop that runs up from 1 to n (using range(1, n+1)) instead of your while-loop. This will generate the values that you want to multiply and iterate the right number of times (which can be a bit tricky with while loops sometimes).
Have a variable named product to store the result of the multiplications each time through the loop.
Initialize product before you enter the for-loop. Once inside you'll be just updating the value of product.
After you are done with the loop, you can use the return statement to return the value of product.
Finally, for testing purposes, you may want to start out with a small value of n, like 4, and print out the values you are computing inside the loop to verify how your code is working.
There are more terse and pythonic ways to do this, but this uses the code structure you have already set up. And of course recursively as well as you mention too.
Once you master the basics, you'll appreciate the more idiomatic ways of writing this, or calling the appropriate functions that do this for you.
Well, here's another Pythonic approach.
>>> import operator
>>> numbers = range(1, 11)
>>> numbers
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> reduce(operator.mul, numbers)
3628800
Assuming you what you meant is factorial function, you can simply just use the math.factorial():
>>> import math
>>> math.factorial(10)
3628800
You are trying to find the factorial of a number n, essentially. For finding the factorial of a number, there are 2 methods
Using a Loop structure
Using Recursion (as you've mentioned)
As a new programmer, you would be better off with a simple loop structure that runs from 1 to n and puts the multiplied value at each iteration into a variable. That variable is your answer. But also know that recursion will also work and make the code look elegant. Happy Programming !
This is called the factorial. 10! is equivalent to 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1.
def factorial(n):
product = 1
while n > 0:
product *= n
n -= 1
return product
By the way, in practice, just use math.factorial.
def factorial(n):
if n <= 1: return 1
return n * factorial(n-1)
I always think of factorial as the quintessential example in learning recursion ...
Another way to do this is to use scipy.product.
>>> import scipy
>>> scipy.product(xrange(1,11))
3628800
As a learner you should do it without using any inbuilt functions it will help you to learn programming rather just tool as learning a tool is much easier one you become good programmer. there are two ways of doing this I have implemented simpler versions.
Using Recursion:
def product(n):
if n== 1:
return 1
return n * product(n-1)
Using Simple Loop:
def product(n):
res = 1
while n>1:
res = res * n
n = n - 1
return res
For factorials too large to compute directly, there is another way to do that by using the Stirling's approximation.
n! := sqrt(2πn)*(n/e)^n, where e = 2.71828

Summing up digits !

Hi I have been trying out this problem:
Suppose P(n) is sum of digits of 2^n
For example:
As 2^15 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26,so P(15)=26.
Catulate sum of the P(n) for n=1 to 10000.
Here is my python code which is giving 67783431 as answer but the judge doesn't seems to be agree on this:
def P(n):
n = int(1<<n)
S = 0
while n != 0:
S += (n%10)
n /= 10
return S
Sum = 0
for i in range(1,10001):
Sum += P(i)
else:
print(Sum)
Could anybody tell me what's wrong in my approach? I would be appreciate if somebody points me to a mathematical solution for the same.
If you had shown the comments, you would've noticed that the site owners, or problem maintainer, is a moron.
He meant to say from "0 to 10000", not "1 to 10000", but apparently the problem cannot be edited, or the maintainer don't want to do it.
The sum is off by 1 since 1<<0 is 1, which adds 1 to the sum.
Try submitting 67783432.
Note: I realize that calling the site owners or the maintainer a moron might sound harsh, but when posting content on a site about "Mathematics", accuracy is kinda important. Having such a site without the ability, or the requirement, to fix wrong problems, seems kinda stupid to me.
A more elegant solution in terms of functional programming might be:
>>> P = lambda n: sum(map(int, str(1 << n)))
>>> sum(P(i) for i in xrange(10001))
67783432
(Notice this computes the sum of P(i) for i=0 to 10000.)
Your solution takes quite some time to run (more than a minute, anyway). Is there a time limit imposed by the judge on the length of time solutions can take to run?
Also, if you're using Python 3, then the division operator (/=) always produces a floating point result. In Python 2, the result would be truncated to an integer with integer inputs.
Actually, with Python 3 I get an overflow error:
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 6, in P
OverflowError: int/int too large for a float
Here's an alternative implementation that confirms your answer is correct:
>>> sum(reduce(lambda x, y: x + int(y), str(2**n), 0) for n in xrange(1, 10001))
67783431
Or one that memoizes:
>> reduce(lambda x, y: (sum(int(c) for c in str(x[1]*2)) + x[0], x[1]*2), xrange(0, 10000), (0,1))[0]
67783431
Actually, since Java cannot produce such large numbers (unless you use BigInteger class - which I have never used ), its better if you use flexible languages like Python
Python gave me 2**1000. its a very huge number whose solution is 1366
try this in python
a = 2**1000
print( a )
then take the output from python as a string and take sum each digit

Ordering of evaluation using boolean or

So I've got this snippet of code. And it works (It says 1 is non-prime).:
n = 1
s = 'prime'
for i in range(2, n / 2 + 1):
if n == 1 or n % i == 0:
s= 'non-' +s
break
print s
My problem is that if I change the fourth line to: if n % i == 0 or n == 1:, it doesn't work (it says 1 is prime.)
Why is that? Since I'm using or should it be that either one of them is True so the order doesn't count?
(I'm still learning about boolean so I may be making some basic mistake.)
Thanks in advance!
EDIT: Thanks for the answers; I never realized my issue with the range() function. And about the code working and not working: I have no idea what happened. I may have made some mistake somewhere along the way (maybe forgot to save before running the script. Although I could've sworn that it worked differently :P ). Maybe I'm just getting tired...
Thanks for the answers anyways!
In both cases, the body of the loop does not run, because when 'n' is 1, it does not fall within the range of (n,n/2+1)
The code you posted says that 1 is prime (again, because the loop body does not execute at all)
The precedence is fine. % is evaluated first, then ==, then or, so it breaks down into:
___or___
/ \
== ==
/ \ / \
n 1 % 0
/ \
n i
Your problem is that your for loop is not being executed at all, so that s is still set to "prime".
The range 2,n/2+1 when n is 1 equates to 2,1 which will result in the body not being executed.
In fact it won't be executed where n is 2 either since 2/2+1 is 2 and the range 2,2 doesn't execute. The values are the start and terminating value, not start and end (last) value - it's just fortuitous there that 2 is considered a prime by virtue of the initialisation of s :-)
Try this instead:
#!usr/bin/python
n = 9
s = 'prime'
if n == 1:
s = 'non-prime'
else:
i = 2
while i * i <= n:
if n % i == 0:
s= 'non-prime'
break
i = i + 1
print s
It's wasteful going all the way up to n/2, the square root of n is all that's needed.
i think the problem is when n is 1, the loop is skipped.
Other answers already correctly addressed your specific problem (which, in other words, is that the loop executes only if n/2 + 1 > 2, that is, n/2 > 1, which means n > 2 with new-style division [[python 3 or suitable imports from the future or flags...]], n > 3 with classic style truncating division).
Wrt the specific question you posed:
Since I'm using or should it be that
either one of them is True so the
order doesn't count?
The order does count because or (like and) is a short-circuiting operator: specifically, or is guaranteed to go left to right, and stop if the left operand is true (because it does not need to know about the right one). This doesn't matter for your specific code, but it's crucial in cases such as, e.g.:
if i == 0 or n / i > 3: ...
If or wasn't going left-to-right (and stopping ASAP), the right-hand operand might get executed even when i equals 0 -- but then the division would raise an exception! With Python's rules, this code snippet won't raise exceptions (if i is an int, at least;-).
Again: this has nothing to do with the specific problem you're having (see other answers and the start of this one), but it's important for you to know for the future, so, since you asked, I took the opportunity to explain!-)
for n in range(101):
s = 'prime'
if n < 2 or not (n & 1): ## not(n & 1) == is even number (last bit 0) == not (n % 2)
s = 'non-'+s
else:
for i in range(3, int(n**0.5) + 1,2):
if not(n % i):
s= 'non-' +s
break
print "%i is %s" % (n,s)
You need not check all even numbers and you can stop the check at square root of n.

Categories

Resources