How can I reduce my execution time for this code? - python

import math
class Solution:
def countSquares(self, N):
list = []
count = 0
for i in range(1,(int)(math.sqrt(N))):
square = i ** 2
list.append(square)
count = count + 1
return count
I am trying to count the number of perfect squares that are less than a given 'N'.
For example, if N = 9, the output is 2. Because only 1 & 4 are the perfect squares present.

list(map(lambda x:x*x, range(1,1+int(math.sqrt(n-1)))))

I think this should do it.
math.ceil(math.sqrt(n)) - 1
math.sqrt will output the square root of the current number.
math.ceil converts that number into the next whole number.
- 1 gives you the previous whole number, which is also the (inclusive) count of whole numbers which can be squared to a number less than n.
If you need to get the list of the square roots instead of the count the modifications are simple.
list(range(1, math.ceil(math.sqrt(n))))
In this case - 1 doesn't need to be performed so range ends with the correct number.

count = 0
for i in range(1, X):
#...
count = count + 1
ends with count == X - 1. Therefore, you don't really need a loop. You also never actually use the list, so storing it will slow down the program further.
sq = math.sqrt(N)
if math.floor(sq) < sq <= math.ceil(sq):
return int(sq)
return int(sq) - 1

Try this:
import math
class Solution:
def countSquares(self, N):
n = math.floor(math.sqrt(N))
if n * n == N:
return n - 1
else:
return n

Related

Happy Number from Python list

i am an absolute Beginner in Python and im trying to, find happy numbers from a given List. but it doesn't give anything back, i searched for a solution but i couldnt find one. My code is this :
a = [1,4,7,82]
def is_happy(a):
for i in range (len(a)):
sum = a[i]
for digit in str(a[i]):
sum = 0
while sum != 1 and sum !=4:
sum = sum + int(digit) ** 2
if sum ==1:
b.append(a[i])
return b
print(is_happy(a))
May you can help me. Thank you!
Converting the integers to strings in order to calculate the sum of squares is not a great idea - better to combine division and modulus. Write a discrete function to do that.
Then write a function that handles one value at a time. Call that multiple times - once for each item in your list.
Here's an approach you could use:
def ss(n):
r = 0
while n > 0:
d = n % 10
r += d * d
n //= 10
return r
def is_happy(n):
if n > 0:
while True:
if (n := ss(n)) == 1:
return True
if n == 4:
break
return False
a = [1, 4, 7, 82]
for n in a:
print(n, is_happy(n))
Output:
1 True
4 False
7 True
82 True
the indents of Python made me suffer..
my solution now looks like:
a = [8,2,7,82]
b = []
def is_happy(a):
for i in range (len(a)):
sum = a[i]
while sum!=1 and sum !=4:
tempsum = 0
for digit in str(sum):
tempsum += int(digit) ** 2
sum = tempsum
if sum == 1:
b.append(a[i])
return b
print(is_happy(a))
and works fine. Thanks for your help and suggestions
Eminos,
I will help with some suggestions.
In Python, white space is very important, and it takes some time for any newbie to get used to.
In for i in range (len(a)):, there is an extra space between "range" and "(". It could still run, but is not the preferred style, since it is defined as a range() function.
Code blocks need consistent spacing (left indent). Each level should be 2 or 4 spaces, with 4 spaces recommended by PEP8 (not tabs). The below examples have too many spaces in left indent.
sum = 0
sum = sum + int(digit) ** 2
b.append(a[i])
To calculate the squre of a number, it is not necessary to change data type from integer to string.
squared = a[i]**2
To keep track of your squared numbers list, try:
tally = 0
for i in range(len(a)):
squared = a[i]**2 # squares each number in list
tally += squared # keeps a running sum of squared numbers
Generally, I think a function like is_happy should return a true/false statement(s). So a sample returned list can be ["True", "False", "True", "True"] for your input example [1, 4, 7, 82].
More work to do, but hope that will get you started. :-)

How to sum even and odd values with one for-loop and no if-condition?

I am taking a programming class in college and one of the exercises in the problem sheet was to write this code:
number = int(input())
x = 0
y = 0
for n in range(number):
if n % 2 == 0:
x += n
else:
y += n
print(x)
print(y)
using only one "for" loop, and no "while" or "if".
The purpose of the code is to find the sum of the even and the sum of
the odd numbers from zero to the number inputted and print it to the
screen.
Be reminded that at this time we aren't supposed to know about
functions.
I've been trying for a long time now and can't seem to find a way of doing it without using "if" statements to know if the loop variable is even or odd.
Purely for educational purposes (and a bit of fun), here is a solution that does not use any for loops at all. (Granted, in the underlying logic of the functions, there are at least five loops.)
num = list(range(int(input('Enter number: '))))
even = num[::2]
odd = num[1::2]
print('Even list:', even)
print('Odd list:', odd)
print('Even:', sum(even))
print('Odd:', sum(odd))
Output:
Enter number: 10
Even list: [0, 2, 4, 6, 8]
Odd list: [1, 3, 5, 7, 9]
Even: 20
Odd: 25
How does it work?
The input() function returns a str object, which is converted into an integer using the int() function.
The integer is wrapped in the range() and list() functions to convert the given number into a list of values within that range.
This is a convention you will use/see a lot through your Python career.
List slicing is used to get every second element in the list. Given the list is based at zero, these will be even numbers.
Slice the same list again, starting with the second element, and get every second element ... odd numbers.
Link to a nice SO answer regarding slicing in Python.
The simply use the sum() function to get the sums.
for n in range(number):
x += (1 - n % 2) * n
y += (n % 2) * n
You asked for a solution with one loop, but how about a solution with no loop?
It is well known that the sum of the numbers from 1 to n is (n+1)*n/2. Thus, the sum of even numbers is 2 * (m+1)*m/2 with m = n//2 (i.e. floor(n/2)). The sum of odd can then be calculated by the sum of all numbers minus the sum of even numbers.
n = 12345
m = n // 2
e = (m+1)*m
o = (n+1)*n//2 - e
Verification:
>>> e, e==sum(i for i in range(n+1) if i % 2 == 0)
38112102 True
>>> o, o==sum(i for i in range(n+1) if i % 2 == 1)
38105929 True
Note: This calculates the sums for number up to and including n.
for n in range(1,number,2):
x += n
y += n-1
print(y)
print(x)
This code has the same output with the example.
Ternary operator:
for n in range(number):
x += (n,0)[n%2]
y += (0,n)[n%2]
I think you are a beginner. I wouldn't like to confuse you with slicing operators complex implementation.
As you mentioned
The purpose of the code is to find the sum of the even and the sum of
the odd numbers from zero to the number inputted and print it to the
screen.
There is no need to find the initial number is odd/even
And your program is wrong if you want to include the input number in calculating the even/odd sum.
Example
Input
5
Expected Output
6
9
Explanation
Even Sum : 2+4 = 6
Odd Sum : 1+3+5 = 9
Your Output
6 4 (wrong output)
The range() function will exclude the number. It will only iterate from 0 to 4 while the input is 5. so if you want to include 5, you should add 1 to the number while passing it in the range() function.
number = int(input())
x = 0
y = 0
for n in range(number+1):
x += (1 - n % 2) * n #this will add 0 if not even
y += (n % 2) * n #this will add 0 if not odd
print(x)
print(y)
There is also mathematical way:
num = int(input("Enter number:"))
odd = ((num+1)/2)**2
even = num*(num+1)/2 - odd
The sum of the first n odd numbers is n^2. To get count of odd numbers we use (num+1)/2. To get sum of even numbers, we could use similar approach, but I preferred, subtracting odd from the sum of the first n numbers, which is n*(n+1)/2.
Here is my 2cents if we are allowed to use numpy.
import numpy as np
number = int(input())
l = np.array(range(number))
print('odd:',sum(l % 2 * l))
print('even:', sum((1- l % 2) * l))
If you're allowed to use a list
number = int( input() )
counts = [ 0, 0 ]
for n in range( number ):
counts[ n % 2 ] += n
print( counts[ 0 ] )
print( counts[ 1 ] )
There's another way which sums the odd and even indices together in the for loop based on the remainder modulo 2:
number = int(input())
odd = 0
even = 0
for i in range(len(number)):
odd += i * (i % 2)
even += i * ((i + 1) % 2)
print (odd, even)
number = 1000000
x = 0
y = 0
[(x:=x+n, y:=y+(n+1)) for n in range(0,number,2)]
print(f'{x}, {y}')
This uses a list comprehension and the new Python assignment operator.
Sum of first n numbers is n(n+1)/2 (Mathematically derived). So if we know the value of n then we can find the sum of all numbers from 1 to n.
If we find the sum of all odd numbers before n and subratract it from the sum of first n we get he sum of all even numbers before n.
Here's the code:
n = int(input("Enter a number: "))
odd = 0
for i in range(1,n+1,2):
odd += i
even = int(n*(n+1)/2) - odd
print("even:",even,"odd:",odd)

Is there a way to make this reverse factorial code run more efficiently

I am just starting to learn python and made a program where it calculates the factorial number based on the factorial.
For example if I give the program the number 120 it will tell me it's factorial is 5
anyways my question is how can I make this code more efficient and faster.
Num = int(input())
i=0
for i in range(0,Num):
i = i + 1
x = Num/i
Num = x
if (x==1):
print(i)
Multiplications are much faster than divisions. You should try to reach the number with a factorial instead of dividing it iteratively:
def unfactorial(n):
f,i = 1,1
while f < n:
i += 1
f *= i
return i if f == n else None
unfactorial(120) # 5
A few things you can do:
Num = int(input())
i=0 # your for loop will initialize i, you don't need to do this here
for i in range(0,Num):
i = i + 1 # your for loop will increment i, no need to do this either
x = Num/i # you don't need the extra variable 'x' here
Num = x
if (x==1):
print(i)
You can rewrite this to look something like:
for index in range(1, number): # start range at 1
number /= index # this means; number = number / index
if number==1:
return index
Compute the factorials in ascending order until you reach (or exceed) the factorial you are looking for, using the previous factorial to efficiently compute the next.
def reverse_factorial(num):
i = 1
while num > 1:
i += 1
num /= i
return i
print(reverse_factorial(int(input())))

Trying to write a code that will find the sum of the even numbers of the Fibonacci sequence?

I'm new to programming and I'm trying to write a program in Python that will find the sum of the even numbers of the numbers below 4,000,000 in the Fibonacci sequence. I'm not sure what I'm doing wrong but nothing will print. Thanks for any help.
def fib():
listx = []
for x in range(4000000):
if x == 0:
return 1
elif x == 1:
return 1
else:
listx.append(fib(x - 1) + fib(x - 2))
return listx
def evens(fib):
y = 0
for x in fib():
if x % 2 == 0:
y += x
else:
continue
print (y)
Here's an approach that uses a generator to keep memory usage to a minimum:
def fib_gen(up_to):
n, m = 0, 1
while n <= up_to:
yield n
n, m = m, n + m
total = 0
for f in fib_gen(4000000):
if f % 2 == 0:
total += f
Another option:
def fib_gen(up_to, filter):
n, m = 0, 1
while n <= up_to:
if filter(n):
yield n
n, m = m, n + m
sum(fib_gen(4000000, lambda f: f % 2 == 0)) # sum of evens
sum(fib_gen(4000000, lambda f: f % 2)) # sum of odds
First things first, there appears to be some contention between your requirements and the code you've delivered :-) The text of your question (presumably taken from an assignment, or Euler #2) requests the ...
sum of the even numbers of the numbers below 4,000,000 in the Fibonacci sequence.
Your code is summing the even numbers from the first four million Fibonacci numbers which is vastly different. The four millionth Fibonacci number has, according to Binet's formula, north of 800,000 digits in it (as opposed to the seven digits in the highest one below four million).
So, assuming the text to be more correct than the code, you don't actually need to construct a list and then evaluate every item in it, that's rather wasteful on memory.
The Fibonacci numbers can be generated on the fly and then simply accumulated if they're even. It's also far more useful to be able to use an arbitrary method to accumulate the numbers, something like the following:
def sumFibWithCond(limit, callback):
# Set up initial conditions.
grandparent, parent, child = 0, 0, 1
accum = 0
# Loop until number is at or beyond limit.
while child < limit:
# Add any suitable number to the accumulator.
accum = accum + callback(child)
# Set up next Fibonacci cycle.
grandparent, parent = parent, child
child = grandparent + child
# Return accumulator when done.
return accum
def accumulateEvens(num):
# Return even numbers as-is, zero for odd numbers.
if num % 2 == 0:
return num
return 0
sumEvensBelowFourMillion = sumFibWithCond(4000000, accumulateEvens)
Of special note is the initial conditions. The numbers are initialised to 0, 0, 1 since we want to ensure we check every Fibonacci number (in child) for the accumulating condition. This means the initial value of child should be one assuming, as per the question, that's the first number you want.
This doesn't make any difference in the current scenario since one is not even but, were you to change the accumulating condition to "odd numbers" (or any other condition that allowed for one), it would make a difference.
And, if you'd prefer to subscribe to the Fibonacci sequence starting with zero, the starting values should be 0, 1, 0 instead.
Maybe this will help you.
def sumOfEvenFibs():
# a,b,c in the Fibonacci sequence
a = 1
b = 1
result = 0
while b < 4000000:
if b % 2 == 0:
result += b
c = a + b
a = b
b = c
return result

Find the highest degree of A that divides N factorial

I've been working on this code to find the max exponent of A that divides into N! but it doesn't seem to be working. I've gotten to the point where I can find the different factors but I just get the same empty array returned. What am I doing wrong?
import math
def highestPower(N,A):
factors = []
x = math.factorial(N)
for i in range(0,N,-1):
if x % A**i == 0:
factors += [i]
return factors
Avoid computing the exponentiation, get rid of the for loop, just divide as long as you can.
import math
def highestPower(N,A):
result = 0
x = math.factorial(N)
while x % A == 0:
x /= A
result += 1
return result
You could also avoid computing the factorial with a loop from 1 to N.
Your range is reversed:
for i in range(0,N,-1):
Should be:
for i in range(N,0,-1):
Also, if you only require the highest, you can return immediately:
import math
def highestPower(N,A):
x = math.factorial(N)
for i in range(0, N, -1):
if x % A**i == 0:
return i
Range should be range(N,0,-1):
The docs for range say:
if step is negative, the last element is the smallest start + i * step greater than stop
So, you need to have start > stop if your step is negative. Otherwise, the for loop does not run at all.

Categories