Calculating GCD - how to check every element in list - python

Multiple number inputs
below is just how I chose to start writing my code
def main():
numbers = input()
if numbers == "0":
exit()
else:
number_list = [int(i) for i in numbers.split()]
def calculate_gcd(number_list):
for i in range(1,smallest_number(number_list)+1):
for n in range(0,len(number_list)):
if number_list[n] % i == 0:
check_list += number_list[n]
more code - but not important for the question im asking
my code was hardly complete and only worked for max 3 size lists, sadly.
How I thought of logic
Read input -> split by space, put it in list
sort the list
make a variable (divisor), and set it to 1
while divisor <= sortedlist[0] (which is smallest in list)
5. if every element % divisor == 0, then gcd = divisor, then divisor+=1
loop until it is no longer true
Problem I found
It requires stupid effort, it will actually not run and give runtime error.
I'm having trouble finding a way to check No.5 (in bold)
I know that there is gcd function, but it only deals with two inputs.
and it comes down to same question, how do I make sure 'all' elements divides down to zero?
Any suggestion of making gcd logic and comment on No.5 (bold) ?
Thank you

Instead of tackling the bigger problem, why not tackle a smaller problem. How do you find the gcd of two numbers? Well, there are multiple algorithms for this. Let us use the iterative one:
def gcd_iterative(a, b):
while b:
a, b = b, a % b
return a
Now, one thing to realize is that, if you have multiple numbers, and you want to find the gcd of all numbers, then it is simply:
gcd(gcd(...(a, b), c), ...)
In simpler terms, if you want to find the gcd of three numbers (a, b, c), then you would do the following:
gcd = gcd_iterative(a, b)
gcd = gcd_iterative(gcd, c)
So, now if you have a list of numbers, lst, you can do the following:
>>> gcd = lst[0]
>>> for num in lst[1:]:
gcd = gcd_iterative(gcd, num)
>>> print(gcd)

Related

Finding the product of first Million natural numbers in Python

I have just started with Python programming language. I tried to write a function which takes input either a list or multiple integers to find their product. I am trying to find the product of first million natural numbers but its displaying an MemoryError.
def product(*arg):
answer=1
if type(arg) == tuple:
arg=str(arg)
arg=arg.lstrip('[(')
arg=arg.rstrip('],)')
arg=arg.split(',')
for i in arg:
answer*=int(i)
return answer
else:
for i in arg:
answer*=int(i)
return answer
j=range(1,1000000,1)
j=list(j)
print(product(j))
Steps:
I convert the range object into list object if i am to pass a list as
argument
Now, within the function, i try to split the tuple by converting it
string.
I convert the resultant string into a list and then loop over the
elements to find the product
Q1: How to avoid the memory error as i try to find the product of first Million natural numbers?
Q2 How to improve this code?
You can use a Generator in Python.
def generate_product():
r = 1
for i in range(1,1000000):
r *= i + 1
yield r
list(generate_product())[0]
It is more memory efficient and better in terms of performance.
To calculate the product of all numbers from 1 to 1 million use a simple loop:
r = 1
for l in range(1,1000000):
r*=(i+1)
print(res)
But keep in mind that the result will be a pretty big number.
That means that your calculation might take long and the resulting number will need a lot memory.
EDIT Then i missread your question a little. This is a function that multiplies the elements in a list:
def multiply_list_elements(_list):
result = 1
for element in _list:
result*=element
return result
multiply_list_elements([1,2,3,4])
>>> 24
The memory error probably came from the huge number as #ZabirAlNazi calculated so nicely.
All of the solution is fine, but one point to make - your question is equivalent to find the factorial of 1 million.
The number of digits of n! = log10(1) + log10(2) + ... log10(n)
import math
num_dig = 1
for i in range(1,1000000):
num_dig += math.log10(i)
print(num_dig)
So, the number of digits in your answer is 5565703 (approx.).
That's only the final n, if you also want the intermediate results it will require squared memory O(m^2).
import math
ans = 1
for i in range(2,1000001):
ans *= i
print(ans)
N.B: You can approximate with logarithms and Stirling numbers with faster run-time.
A very simple solution would be:
def prod_of():
p=1
for i in range(1,1000000):
p* = i
print(p)

isPrime test using list of factors

I'm trying to create a python program to check if a given number "n" is prime or not. I've first created a program that lists the divisors of n:
import math
def factors(n):
i = 2
factlist = []
while i <= n:
if n% i == 0:
factlist.append(i)
i = i + 1
return factlist
factors(100)
Next, I'm trying to use the "for i in" function to say that if p1 (the list of factors of n) only includes n itself, then print TRUE, and if else, print FALSE. This seems really easy, but I cannot get it to work. This is what I've done so far:
def isPrime(n):
p1 = factors(n)
for i in p1:
if factors(n) == int(i):
return True
return False
Any help is appreciated! This is a hw assignment, so it's required to use the list of factors in our prime test. Thanks in advance!
p1 will only have n if if has length 1. It may be worthwhile to add if len(p1)==1 as the conditional instead.
What I did (I actually managed to get it in 1 line) was use [number for number in range (2, num // 2) if num % number == 0]. This gets all the numbers that are factors of num. Then you can check if the length of that list is > 0. (Wouldn't be prime).
I usually do something like this:
primes = [2,3]
def is_prime(num):
if num>primes[-1]:
for i in range(primes[-1]+2, num+1,2):
if all(i%p for p in primes):
primes.append(i)
return num in primes
This method generates a global list of prime numbers as it goes. It uses that list to find other prime numbers. The advantage of this method is fewer calculations the program has to make, especially when there are many repeated calls to the is_prime function for possible prime numbers that are less than the largest number you have previously sent to it.
You can adapt some of the concepts in this function for your HW.

Function returning none- Trying to find highest number in a set without using x

Hey so I am just starting out on python. I am trying to find the largest number among 4 numbers using a function with return. For whatever reason the function keeps returning only value d and only if it the highest int. Other set of numbers I put in yeild none. I solved it originally using max, but I cant use max for the assignment. Please let me know what im doing wrong!! Thanks!
a=num1=int(input("Enter 1st number "))
b=num2=int(input("Enter 2nd number "))
c=num3=int(input("Enter 3rd number "))
d=num4=int(input("Enter 4th number "))
def CompareNumbers(a, b , c, d):
if(b > a):
largest=b
return largest
if(c > b):
largest= c
return largest
if(d > c):
largest= d
return largest
largest = a
e= CompareNumbers(a, b, c, d)
print(e)
You may not have encountered for-loops yet, but you will. My suggestion is to try and use one here:
def compare_numbers(a, b, c, d):
# To start out, we'll assume the
# first number is the largest, but
# we'll be double checking that.
largest = a
# We put the rest of the numbers in
# a list that we'll iterate over in
# the for-loop below
my_list = [b, c, d]
for number in my_list:
# see explanation below...
return largest
In the empty for-loop I've written above, you'll want to write a bit of code that checks if largest is actually larger than number. If it is, Great! You don't need to do anything. But if number is the larger of the two, you need to set largest = number. If you do this correctly, when the for-loop ends, largest will be the biggest of the four numbers you put in.

What would be the best answer for this Fibonacci excercise in Python?

What's the best answer for this Fibonacci exercise in Python?
http://www.scipy-lectures.org/intro/language/functions.html#exercises
Exercise: Fibonacci sequence
Write a function that displays the n first terms of the Fibonacci
sequence, defined by:
u0 = 1; u1 = 1
u(n+2) = u(n+1) + un
If this were simply asking a Fibonacci code, I would write like this:
def fibo_R(n):
if n == 1 or n == 2:
return 1
return fibo_R(n-1) + fibo_R(n-2)
print(fibo_R(6))
... However, in this exercise, the initial conditions are both 1 and 1, and the calculation is going towards the positive direction (+). I don't know how to set the end condition. I've searched for an answer, but I couldn't find any. How would you answer this?
Note that u_(n+2) = u_(n+1) + u_n is equivalent to u_n = u_(n-1) + u_(n-2), i.e. your previous code will still apply. Fibonacci numbers are by definition defined in terms of their predecessors, no matter how you phrase the problem.
A good approach to solve this is to define a generator which produces the elements of the Fibonacci sequence on demand:
def fibonacci():
i = 1
j = 1
while True:
yield i
x = i + j
i = j
j = x
You can then take the first N items of the generator via e.g. itertools.islice, or you use enumerate to keep track of how many numbers you saw:
for i, x in enumerate(fibonacci()):
if i > n:
break
print x
Having a generator means that you can use the same code for solving many different problems (and quite efficiently though), such as:
getting the n'th fibonacci number
getting the first n fibonacci numbers
getting all fibonacci numbers satisfying some predicate (e.g. all fibonacci numbers lower than 100)
The best way to calculate a fibonacci sequence is by simply starting at the beginning and looping until you have calculated the n-th number. Recursion produces way too many method calls since you are calculating the same numbers over and over again.
This function calculates the first n fibonacci numbers, stores them in a list and then prints them out:
def fibonacci(n):
array = [1]
a = 1
b = 1
if n == 1:
print array
for i in range(n-1):
fib = a + b
a = b
b = fib
array.append(fib)
print array
If you want a super memory-efficient solution, use a generator that only produces the next number on demand:
def fib_generator():
e1, e2 = 0, 1
while True:
e1,e2 = e2, e1+e2
yield e1
f = fib_generator()
print(next(f))
print(next(f))
print(next(f))
## dump the rest with a for-loop
for i in range(3, 50):
print(next(f))
The recursive solution is the most elegant, but it is slow. Keiwan's loop is the fastest for a large number of elements.
Yes, definitely no globals as correctly observed by DSM. Thanks!
An alternative recursive just to show that things can be done in slightly different ways:
def fib2(n): return n if n < 2 else fib2( n - 1 ) + fib2( n - 2 )

Python: divide elements of a list based on a condition

I am trying to find the LCM of first 20 natural numbers (Project Euler question 5). For that, my algorithm is:
have numbers 1 to 20 in a list
Divide only those elements of the list that are divisible by i where i is in the range (2-20).
Whatever numbers are left in the list, multiply them and that will be the lcm.
This is the naivest algorithm which we actually used to calculate lcm in school for the first time.
Now, I donot know how to divide the elements of the list based on the condition.
I have tried:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
for x in a:
if(x%2==0):
x=x/2
This does not seem to work.
I also tried:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
a1=[if(x%2==0): x/2 for x in a]
the above with both with and without ":" after the if condition. This does not work. I have the following questions:
a. Why isn't the first loop working correctly?
b. Can someone tell me how I can do this?
c. Will my algorithm work correctly?
a. Why isn't the first loop working correctly?
For the same reason as:
Foreach in Python not working as expected
b. Can someone tell me how I can do this?
You can do either:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
for i, x in enumerate(a):
if x%2==0:
a[i]=x/2
Or:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
a1=[x/2 if x%2==0 else x for x in a]
c. Will my algorithm work correctly?
I don't think so. You'll end up dividing everyone by itself and the result will always be 1.
But there are other questions here in SO that have simple answers, like:
find least common multiple of numbers 1-20
a) Why is this loop not working correctly?
As #jose-ricardo-bustos-m indicates, the x is not a reference, is a local copy to each element of the array a, and cannot modify the array in the for loop. You can use, instead:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
for i,x in enumerate(a): #used to provide a value, and an index
if(x%2==0):
a[i]=x/2
b) Can someone tell me how I can do this?
You can try to use the ternary if operator and list comprehension:
a = [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
b = [x/2 if x%2==0 else x for x in a]
c) Will my algorithm work correctly
You have to keep track of the numbers you have already used, and you might need to divide by the same number more than once. But if you do that, and keep dividing by the same number _until the resulting list is equal to the previous one, and then move to the next, you can later multiply all numbers used, times the remainder of the list (but if you go to the max number in the list, the remaining list will contain just 1's).
def f(l,n): # divides items in a which are divisible by n, or leaves them
return [x/n if x%n==0 else x for x in l]
lcm = 1
a=[2,3,4,5,6,7]
# we go from the smallest to the largest number in your list
for i in range(2,max(a)+1):
repeat_next_time = True
while repeat_next_time:
b = f(a,i)
if a != b:
print('Using %s as a factor' % i)
a = b
lcm *= i
# print(a) # to get the status of the a list
else:
repeat_next_time = False
# finally, for numbers which might have not been divided yet,
# multiply the lcm by all of the remaining items
lcm *= reduce(lambda x,y: x*y, a)
It works even if there are common divisors, or repeated numbers in the list. Try, for instance, with a = [2,2,2], or a = [2,3,6], or a = [8,7,4,7].
a) the variable x takes the value of the list a , but not modified, it is not a reference of list, the following code does what you want:
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
for i in range(len(a)):
if(a[i]%2==0):
a[i]=a[i]/2
b) y C)
a=[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
def f(x):
if(x%2==0):
return x/2
return x
a1=[f(x) for x in a]
Whatever numbers are left in the list, multiply them and that will be the lcm.
reduce(lambda x, y: x*y, a1)

Categories

Resources