Factorial doesn't output an integer - python

I'm not a very experienced programmer but I just wrote this in Python to try and find e, using the definition that e is the sum of 1/0! + 1/1! + 1/2! etc...
The problem I'm having is def factorial doesn't output an integer. I realize it wouldn't given how it's written but I'm not sure how I can make it. total is what I would want outputted as an int from def factorial.
e = 0
def factorial(m):
n = m - 1
total = 1
if n > 0:
total = m
while n > 0:
total = total * n
n = n - 1
for w in range(0,100):
s = factorial(w)
e = e + ( 1 / s )
print(e)

def factorial(m):
n = m - 1
total = 1
if n > 0:
total = m
while n > 0:
total = total * n
n = n - 1
return total
EDIT: The problem is that, in order to get information from factorial, you have to use a return statement. Anything after the return is evaluated, and used as the value of s in s = factorial(w).

The code by Feffernoose works. But to improve the performance in your case, you would better use the "yield" statement to build a iterable object.
e = 0
def factorial(m):
assert(m>1)
current = 0
total = 1
while current<=m:
yield total
current += 1
total *= current
for w in factorial(100):
e = e + ( 1 / w )
print(e)
Update: in the solution with "return", you approximately need O(n*n) time for the factorial value computation. But with "yield", you only need O(n).

Related

Sum of 1+3+5...+n until the sum exceeds 100

Then the sum and the last added number and the number of numbers added must be printed.
I am currently stuck, I managed to get the sum part working. The last added number output is printed "23" but should be "21". And lastly, how can I print the number of numbers added?
Output goal: 121, 21, 11
Here is my code:
n = int()
sum = 0
k = 1
while sum <= 100:
if k%2==1:
sum = sum + k
k = k + 2
print('Sum is:', sum)
print("last number:", k)
Edit: Would like to thank everyone for their help and answers!
Note, that (you can prove it by induction)
1 + 3 + 5 + ... + 2 * n - 1 == n**2
<----- n items ----->
So far so good in order to get n all you have to do is to compute square root:
n = sqrt(sum)
in case of 100 we can find n when sum reach 100 as
n = sqrt(100) == 10
So when n == 10 then sum == 100, when n = 11 (last item is 2 * n - 1 == 2 * 11 - 1 == 21) the sum exceeds 100: it will be
n*n == 11 ** 2 == 121
In general case
n = floor(sqrt(sum)) + 1
Code:
def solve(s):
n = round(s ** 0.5 - 0.5) + 1;
print ('Number of numbers added: ', n);
print ('Last number: ', 2 * n - 1)
print ('Sum of numbers: ', n * n)
solve(100)
We have no need in loops here and can have O(1) time and space complexity solution (please, fiddle)
More demos:
test : count : last : sum
-------------------------
99 : 10 : 19 : 100
100 : 11 : 21 : 121
101 : 11 : 21 : 121
Change your while loop so that you test and break before the top:
k=1
acc=0
while True:
if acc+k>100:
break
else:
acc+=k
k+=2
>>> k
21
>>> acc
100
And if you want the accumulator to be 121 just add k before you break:
k=1
acc=0
while True:
if acc+k>100:
acc+=k
break
else:
acc+=k
k+=2
If you have the curiosity to try a few partial sums, you immediately recognize the sequence of perfect squares. Hence, there are 11 terms and the last number is 21.
print(121, 21, 11)
More seriously:
i, s= 1, 1
while s <= 100:
i+= 2
s+= i
print(s, i, (i + 1) // 2)
Instead of
k = k + 2
say
if (sum <= 100):
k = k +2
...because that is, after all, the circumstance under which you want to add 2.
To also count the numbers, have another counter, perhasp howManyNumbers, which starts and 0 and you add 1 every time you add a number.
Just Simply Change you code to,
n = int()
sum = 0
k = 1
cnt = 0
while sum <= 100:
if k%2==1:
sum = sum + k
k = k + 2
cnt+=1
print('Sum is:', sum)
print("last number:", k-2)
print('Number of Numbers Added:', cnt)
Here, is the reason,
the counter should be starting from 0 and the answer of the last printed number should be k-2 because when the sum exceeds 100 it'll also increment the value of k by 2 and after that the loop will be falls in false condition.
You can even solve it for the general case:
def sum_n(n, k=3, s =1):
if s + k > n:
print('Sum is', s + k)
print('Last number', k)
return
sum_n(n, k + 2, s + k)
sum_n(int(input()))
You can do the following:
from itertools import count
total = 0
for i, num in enumerate(count(1, step=2)):
total += num
if total > 100:
break
print('Sum is:', total)
print("last number:", 2*i + 1)
To avoid the update on k, you can also use the follwoing idiom
while True:
total += k # do not shadow built-in sum
if total > 100:
break
Or in Python >= 3.8:
while (total := total + k) <= 100:
k += 2
Based on your code, this would achieve your goal:
n = 0
summed = 0
k = 1
while summed <= 100:
n += 1
summed = summed + k
if summed <= 100:
k = k + 2
print(f"Sum is: {summed}")
print(f"Last number: {k}")
print(f"Loop count: {n}")
This will solve your problem without changing your code too much:
n = int()
counter_sum = 0
counter = 0
k = 1
while counter_sum <= 100:
k+= 2
counter_sum =counter_sum+ k
counter+=1
print('Sum is:', counter_sum)
print("last number:", k)
print("number of numbers added:", counter)
You don't need a loop for this. The sum of 1...n with step size k is given by
s = ((n - 1) / k + 1) * (n + 1) / k
You can simplify this into a standard quadratic
s = (n**2 - k * n + k - 1) / k**2
To find integer solution for s >= x, solve s = x and take the ceiling of the result. Apply the quadratic formula to
n**2 - k * n + k - 1 = k**2 * x
The result is
n = 0.5 * (k + sqrt(k**2 - 4 * (k - k**2 * x - 1)))
For k = 2, x = 100 you get:
>>> from math import ceil, sqrt
>>> k = 2
>>> x = 100
>>> n = 0.5 * (k + sqrt(k**2 - 4 * (k - k**2 * x - 1)))
>>> ceil(n)
21
The only complication arises when you get n == ceil(n), since you actually want s > x. In that case, you can test:
c = ceil(n)
if n == c:
c += 1

Optimizing Python Code for Competitions

I'm new to Python, and I'm trying to get familiar with it by solving problems on CodeChef. I'm attempting to solve the Easy problem Number Game. The issue is that the execution time is too long for my code.
I have translated the Python solution I wrote into C++, and the submission was accepted, so I know I have a correct answer, and it's just off by a constant multiple.
Is it possible to solve this problem in Python 3 in the allotted time? Can you help me speed up my code to accomplish this?
import time
def getStartValues(A, M):
startVals = [0]*M
b = [0]*len(A)
for i in range(len(A)-1):
b[i+1] = (10*b[i] + A[i]) % M
f = 0
power = 1
for i in range(len(A)-1,0,-1):
startVals[(b[i]*power + f) % M] += 1
f = (A[i]*power + f) % M
power = (power*10 % M)
startVals[f] += 1
return startVals, power
def checkValues(i, startVals, M, powNm1, checked, chklst):
if checked[i] == 1:
return startVals[i]
q = [i]
chk = [0]*M
chk[i] = 1
while len(q) > 0:
val = q.pop(0)
for j in chklst:
val2 = (powNm1*val + j) % M
if checked[val2] > 0:
checked[i] = 1
return startVals[i]
elif chk[val2] == 0:
q.append(val2)
chk[val2] = 1
return 0
def compute(A, M):
startVals, power = getStartValues(A, M)
checked = [0]*M
checked[0] = 1
chklst = [j for j in range(M) if startVals[j] > 0]
total = 0
for i in chklst:
c = checkValues(i, startVals, M, power, checked, chklst)
total += c
return total
start = time.time()
file = open('numbgame.in', 'r')
#T = int(input())
T = int(file.readline())
for i in range(T):
#A, M = input().split()
A, M = file.readline().split()
A = list(map(int,A))
M = int(M)
print(compute(A, M))
tDiff = time.time() - start
print('Total time: %s' % tDiff)
Note that I have modified the code to read from a file and to display execution time, as a convenience, and some small alterations are needed before it can be submitted.
getStartValues takes in the (big) list of digits of the input A and the (small) integer M and returns the values modulo M that can be generated from A by removing a single digit.
checkValues takes an index i, the list startValues, the integer M, the integer powNm1 (which is the value 10^(n-1) mod M, where n is the number of digits in A, a list checked that keeps track of whether a value has already been determined to be solvable, and the list chklst (which contains the indices i such that startValues[i] > 0).
The majority of the time is spent in the function getStartValues, since A could be up to 10^6 digits long. On my desktop, the getStartValues function call takes about 1.2s, while the rest of the compute function takes about 0.04s (for worst case inputs).

perfect squares leetcode missing testcase with recursive solution

Trying to solve this problem with recursion but for input 7168 getting wrong answer.
Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.
For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.
def recursive(self, n, result, dp):
if n in dp:
return dp[n]
#very large number
large_no = 1 << 31
if n < 1:
return 0
#checking if n is a square or not?
r = n**0.5
if int(r)*int(r) == n:
return result + 1
#iterate from square root till 1 checking all numbers
r = int(r)
while r >= 1:
large_no = min(large_no, self.recursive(n - int(r)*int(r), result + 1, dp))
r -= 1
#memoize the result
dp[n] = large_no
return large_no
I am calling above function as this: self.recursive(7168, 0, {})
Answer should be 4 but I am getting 5. Please don't suggest alternative ways to solve this problem as I have tried them already and it works. I am here to just know the problem with this logic.
First, you have a typo: m should be large_no.
But you're using dp incorrectly: you should be caching the smallest way to write i as the sum of squares, but you're actually caching the result of whatever path you happen to get there.
That means you may cache an accidentally larger value than necessary, and your algorithm is wrong. Although the algorithm is wrong, 7168 is the first value for which it produces the wrong result.
Drop the result argument, change return result+1 to return 1 and your recursive call to:
large_no = min(large_no, 1+self.recursive(n - int(r)*int(r), dp))
A cleaned-up, working version of your code:
def recursive(n, dp):
if n in dp:
return dp[n]
if n == 0: return 0
best = n
for r in xrange(int(n**0.5), 0, -1):
best = min(best, 1 + recursive(n - r*r, dp))
dp[n] = best
return dp[n]
I think the problem is that you're passing result down into your recursion but do not take it into account in memoizing.
recursive(X, Y, dp) and recursive(X, Z, dp) both return dp[X] if X in dp but return dp[X] + y and dp[X] + z, respectively, if dp[X] is not yet memoized (where y = R - Y and z = R - Z, with R the value of result when dp[X] got memoized).
I would get rid of result altogether:
def recursive(self, n, dp):
if n in dp:
return dp[n]
#very large number
large_no = 1 << 31
if n < 1:
return 0
#checking if n is a square or not?
r = n**0.5
if int(r)*int(r) == n:
return 1
#iterate from square root till 1 checking all numbers
r = int(r)
while r >= 1:
large_no = min(large_no, self.recursive(n - int(r)*int(r), dp))
r -= 1
#memoize the result
dp[n] = large_no + 1
return large_no + 1

Codewars. Some tests are passed, but i need to get tests which outputs the following mistake: 3263 should equal -1

Can you explain it what problems are here? To my mind, this code is like a heap of crap but with the right solving. I beg your pardon for my english.
the task of this kata:
Some numbers have funny properties. For example:
89 --> 8¹ + 9² = 89 * 1
695 --> 6² + 9³ + 5⁴= 1390 = 695 * 2
46288 --> 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51
Given a positive integer n written as abcd... (a, b, c, d... being digits) and a positive integer p we want to find a positive integer k, if it exists, such as the sum of the digits of n taken to the successive powers of p is equal to k * n. In other words:
Is there an integer k such as : (a ^ p + b ^ (p+1) + c ^(p+2) + d ^ (p+3) + ...) = n * k
If it is the case we will return k, if not return -1.
Note: n, p will always be given as strictly positive integers.
dig_pow(89, 1) should return 1 since 8¹ + 9² = 89 = 89 * 1
dig_pow(92, 1) should return -1 since there is no k such as 9¹ + 2² equals 92 * k
dig_pow(695, 2) should return 2 since 6² + 9³ + 5⁴= 1390 = 695 * 2
dig_pow(46288, 3) should return 51 since 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51
def dig_pow(n, p):
if n > 0 and p > 0:
b = []
a = str(n)
result = []
for i in a:
b.append(int(i))
for x in b:
if p != 1:
result.append(x ** p)
p += 1
else:
result.append(x ** (p + 1))
if int((sum(result)) / n) < 1:
return -1
elif int((sum(result)) / n) < 2:
return 1
else:
return int((sum(result)) / n)
test results:
Test Passed
Test Passed
Test Passed
Test Passed
3263 should equal -1
I don't know what exact version of Python you're using. This following code are in Python 3. And if I get you correctly, the code can be as simple as
def dig_pow(n, p):
assert n > 0 and p > 0
digits = (int(i) for i in str(n)) # replaces your a,b part with generator
result = 0 # you don't use result as a list, so an int suffice
for x in digits: # why do you need if in the loop? (am I missing something?)
result += x ** p
p += 1
if result % n: # you just test for divisibility
return -1
else:
return result // n
The major problem is that, in your objective, you have only two option of returning, but you wrote if elif else, which is definitely unnecessary and leads to problems and bugs. The % is modulus operator.
Also, having an if and not returning anything in the other branch is often not a good idea (see the assert part). Of course, if you don't like it, just fall back to if.
I believe this could work as well and I find it a little easier to read, however it can definitely be improved:
def dig_pow(n, p):
value = 0
for digit in str(n):
value += int(digit)**p
p += 1
for k in range(1,value):
if value/k == n:
return k
return -1
this is some example simple example than using:
digits = (int(i) for i in str(n))
I'm opting to use this version since I am still a beginner which can be done with this alt way:
result = 0
for digits in str(n):
#iterate through each digit from n
# single of digits turn to int & power to p
for number in digits:
result += int(number) ** p
p += 1
as for the full solution, it goes like this:
def dig_pow(n, p):
# example n = 123 , change it to string = 1, 2, 3
# each string[] **p, and p iterate by 1
# if n % p not equal to p return - 1
result = 0
for digits in str(n):
#iterate through each digit from n
# single digit turn to int & power to p
for number in digits:
result += int(number) ** p
p += 1
if result % n:
return -1
else:
return result // n

Optimise the solution to Project Euler 12 (Python)

I have the following code for Project Euler Problem 12. However, it takes a very long time to execute. Does anyone have any suggestions for speeding it up?
n = input("Enter number: ")
def genfact(n):
t = []
for i in xrange(1, n+1):
if n%i == 0:
t.append(i)
return t
print "Numbers of divisors: ", len(genfact(n))
print
m = input("Enter the number of triangle numbers to check: ")
print
for i in xrange (2, m+2):
a = sum(xrange(i))
b = len(genfact(a))
if b > 500:
print a
For n, I enter an arbitrary number such as 6 just to check whether it indeed returns the length of the list of the number of factors.
For m, I enter entered 80 000 000
It works relatively quickly for small numbers. If I enter b > 50 ; it returns 28 for a, which is correct.
My answer here isn't pretty or elegant, it is still brute force. But, it simplifies the problem space a little and terminates successfully in less than 10 seconds.
Getting factors of n:
Like #usethedeathstar mentioned, it is possible to test for factors only up to n/2. However, we can do better by testing only up to the square root of n:
let n = 36
=> factors(n) : (1x36, 2x18, 3x12, 4x9, 6x6, 9x4, 12x3, 18x2, 36x1)
As you can see, it loops around after 6 (the square root of 36). We also don't need to explicitly return the factors, just find out how many there are... so just count them off with a generator inside of sum():
import math
def get_factors(n):
return sum(2 for i in range(1, round(math.sqrt(n)+1)) if not n % i)
Testing the triangular numbers
I have used a generator function to yield the triangular numbers:
def generate_triangles(limit):
l = 1
while l <= limit:
yield sum(range(l + 1))
l += 1
And finally, start testing:
def test_triangles():
triangles = generate_triangles(100000)
for i in triangles:
if get_factors(i) > 499:
return i
Running this with the profiler, it completes in less than 10 seconds:
$ python3 -m cProfile euler12.py
361986 function calls in 8.006 seconds
The BIGGEST time saving here is get_factors(n) testing only up to the square root of n - this makes it heeeaps quicker and you save heaps of memory overhead by not generating a list of factors.
As I said, it still isn't pretty - I am sure there are more elegant solutions. But, it fits the bill of being faster :)
I got my answer to run in 1.8 seconds with Python.
import time
from math import sqrt
def count_divisors(n):
d = {}
count = 1
while n % 2 == 0:
n = n / 2
try:
d[2] += 1
except KeyError:
d[2] = 1
for i in range(3, int(sqrt(n+1)), 2):
while n % i == 0 and i != n:
n = n / i
try:
d[i] += 1
except KeyError:
d[i] = 1
d[n] = 1
for _,v in d.items():
count = count * (v + 1)
return count
def tri_number(num):
next = 1 + int(sqrt(1+(8 * num)))
return num + (next/2)
def main():
i = 1
while count_divisors(i) < 500:
i = tri_number(i)
return i
start = time.time()
answer = main()
elapsed = (time.time() - start)
print("result %s returned in %s seconds." % (answer, elapsed))
Here is the output showing the timedelta and correct answer:
$ python ./project012.py
result 76576500 returned in 1.82238006592 seconds.
Factoring
For counting the divisors, I start by initializing an empty dictionary and a counter. For each factor found, I create key of d[factor] with value of 1 if it does not exist, otherwise, I increment the value d[factor].
For example, if we counted the factors 100, we would see d = {25: 1, 2: 2}
The first while loop, I factor out all 2's, dividing n by 2 each time. Next, I begin factoring at 3, skipping two each time (since we factored all even numbers already), and stopping once I get to the square root of n+1.
We stop at the square_root of n because if there's a pair of factors with one of the numbers bigger than square_root of n, the other of the pair has to be less than 10. If the smaller one doesn't exist, there is no matching larger factor.
https://math.stackexchange.com/questions/1343171/why-only-square-root-approach-to-check-number-is-prime
while n % 2 == 0:
n = n / 2
try:
d[2] += 1
except KeyError:
d[2] = 1
for i in range(3, int(sqrt(n+1)), 2):
while n % i == 0 and i != n:
n = n / i
try:
d[i] += 1
except KeyError:
d[i] = 1
d[n] = 1
Now that I have gotten each factor, and added it to the dictionary, we have to add the last factor (which is just n).
Counting Divisors
Now that the dictionary is complete, we loop through each of the items, and apply the following formula: d(n)=(a+1)(b+1)(c+1)...
https://www.wikihow.com/Determine-the-Number-of-Divisors-of-an-Integer
All this formula means is taking all of the counts of each factor, adding 1, then multiplying them together. Take 100 for example, which has factors 25, 2, and 2. We would calculate d(n)=(a+1)(b+1) = (1+1)(2+1) = (2)(3) = 6 total divisors
for _,v in d.items():
count = count * (v + 1)
return count
Calculate Triangle Numbers
Now, taking a look at tri_number(), you can see that I opted to calculate the next triangle number in a sequence without manually adding each whole number together (saving me millions of operations). Instead I used T(n) = n (n+1) / 2
http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/runsums/triNbProof.html
We are providing a whole number to the function as an argument, so we need to solve for n, which is going to be the whole number to add next. Once we have the next number (n), we simply add that single number to num and return
S=n(n+1)2
S=n2+n2
2S=n2+n
n2+n−2S=0
At this point, we use the quadratic formula for : ax2+bx+c=0.
n=−b±√b2−4ac / 2a
n=−1±√1−4(1)(−2S) / 2
n=−1±√1+8S / 2
https://socratic.org/questions/how-do-you-solve-for-n-in-s-n-n-1-2
So all tri_number() does is evaluate n=1+√1+8S / 2 (we ignore the negative equation here). The answer that is returned is the next triangle number in the sequence.
def tri_number(num):
next = 1 + int(sqrt(1+(8 * num)))
return num + (next/2)
Main Loop
Finally, we can look at main(). We start at whole number 1. We count the divisor of 1. If it is less than 500, we get the next triangle number, then try again and again until we get a number with > 500 divisors.
def main():
i = 1
while count_divisors(i) < 500:
i = tri_number(i)
return i
I am sure there are additional ways to optimize but I am not smart enough to understand those ways. If you find any better ways to optimize python, let me know! I originally solved project 12 in Golang, and that run in 25 milliseconds!
$ go run project012.go
76576500
2018/07/12 01:56:31 TIME: main() took 23.581558ms
one of the hints i can give is
def genfact(n):
t = []
for i in xrange(1, n+1):
if n%i == 0:
t.append(i)
return t
change that to
def genfact(n):
t=[]
for i in xrange(1,numpy.sqrt(n)+1):
if(n%i==0):
t.append(i)
t.apend(n/i)
since if a is a divisor than so is b=n/a, since a*b=a*n/b=n, That should help a part already (not sure if in your case a square is possible, but if so, add another case to exclude adding the same number twice)
You could devise a recursive thing too, (like if it is something like for 28, you get 1,28,2,14 and at the moment you are at knowing 14, you put in something to actually remember the divisors of 14 (memoize), than check if they are alraedy in the list, and if not, add them to the list, together with 28/d for each of the divisors of 14, and at the end just take out the duplicates
If you think my first answer is still not fast enough, ask for more, and i will check how it would be done to solve it faster with some more tricks (could probably make use of erastothenes sieve or so too, and some other tricks could be thought up as well if you would wish to really blow up the problem to huge proportions, like to check the first one with over 10k divisors or so)
while True:
c=0
n=1
m=1
for i in range(1,n+1):
if n%i==0:
c=c+1
m=m+1
n=m*(m+1)/2
if c>500:
break
print n
this is not my code but it is so optimized.
source: http://code.jasonbhill.com/sage/project-euler-problem-12/
import time
def num_divisors(n):
if n % 2 == 0: n = n / 2
divisors = 1
count = 0
while n % 2 == 0:
count += 1
n = n / 2
divisors = divisors * (count + 1)
p = 3
while n != 1:
count = 0
while n % p == 0:
count += 1
n = n / p
divisors = divisors * (count + 1)
p += 2
return divisors
def find_triangular_index(factor_limit):
n = 1
lnum, rnum = num_divisors(n), num_divisors(n + 1)
while lnum * rnum < 500:
n += 1
lnum, rnum = rnum, num_divisors(n + 1)
return n
start = time.time()
index = find_triangular_index(500)
triangle = (index * (index + 1)) / 2
elapsed = (time.time() - start)
print("result %s returned in %s seconds." % (triangle, elapsed))

Categories