List all factors of number - python

I am trying to list all the factors of a number called count. Whenever I run it, it returns 1. For example: if 6 = count, then what should be returned when calling findFactor(6) is 1 2 3 6. What is returned is 1
divisors = ""
def findFactor(count):
divisors = ""
valueD = 0
for i in range(1, count+1):
valueD = count/i
if isinstance(valueD,int) == True:
divisors = str(valueD)+" "
print divisors

This can be done on one line using list comprehension.
def factorize(num):
return [n for n in range(1, num + 1) if num % n == 0]

You can refer this code:
def find_factor(n):
factor_values = []
for i in range(1, n + 1):
if n % i == 0:
factor_values.append(i)
values = ""
for v in factor_values:
values += str(v) + " "
return values
The function will return 1 2 3 6

First of all, you have an indentation error. print divisors need to be tabbed to inside the for-loop.
divisors = ""
def findFactor(count):
divisors = ""
valueD = 0
for i in range(1, count+1):
valueD = count/i
if isinstance(valueD,int) == True:
divisors = str(valueD)+" "
print divisors
Furthermore like #juanpa.arrivillaga mentioned, your results will vary between Python 2 and Python 3.
However, if you want your divisors to print in the order you want, i.e. start with 1 you need to change your range to for i in range(count,0, -1). You will get multiple 1's , but that's something I'll leave for you to figure out. A little challenge, if you will. ;)

This is the total code I have come up with. Thank you for all the help.
def findFactor(n):
factorValues = []
for i in range(1, n + 1):
if n % i == 0:
factorValues.append(i)
values = ""
for v in factorValues:
values += str(v) + " "
print values.count(" ")
# prints the number of factors
print values
findFactor(21)
It will print the number of factors, and then the factors on the next line.

The answers given so far are all brute force methods.
For n=10000, they will have to iterate ten thousand times.
The following will iterate only 100 times:
def find_factors(n):
factors = []
i = 1
j = n
while True:
if i*j == n:
factors.append(i)
if i == j:
break
factors.append(j)
i += 1
j = n // i
if i > j:
break
return factors
If there were a list of prime numbers available, it could be made even faster.

Related

How to get the amount of factors in a number

I have code so far which gets me the factors of a number, however I need the amount of factors in any number inputted. How can I do that?
def factor(n):
factor_values = []
for i in range(1, n + 1):
if n % i == 0:
factor_values.append(i)
values = ""
for v in factor_values:
values += str(v) + " "
return values
I have tried to find how many factors does a value have using python, I think because your code using list to save all the factors, you can count all the item using print(factor_values.len()) which will return the length of a list.
Does it solve your problem?
def factor(n):
factor_values = []
for i in range(1, n + 1):
if n % i == 0:
factor_values.append(i)
return len(factor_values)
If you want to find the factors of numbers without 1 and the number itself, then:
def factor(n):
factor_values = []
for i in range(2, n):
if n % i == 0:
factor_values.append(i)
return len(factor_values)
Or in another way you can just count the factors:
def factor(n):
count = 0
for i in range(2, n):
if the_num % i == 0:
count += 1
return count

Can't get out of While loop(Python 3.9)

I'm a new at programming, I like solving this euler questions and I know there are solutions for this problem but it's not about the problem at all actually.
So, i managed to create a working function for finding example: 33. triangular number. It works but i couldn't manage to properly desing my while loop. I wanted to make it like, it starts from first triangular checks it's divisors make list of it's divisors, checks the length of the divisors, because problem wants "What is the value of the first triangle number to have over five hundred divisors?" . But i never managed to work the while loop. Thank you for reading.
nums = [1]
triangles = [1]
divisors = []
def triangularcreator(x):
if x == 1:
return 1
n = 1
sum = 0
while n!=0:
n += 1
nums.append(n)
for i in range(len(nums)):
sum += nums[i]
triangles.append(sum)
sum = 0
if x == len(triangles):
n = 0
return triangles[-1]
counter = 1
while True:
for i in range(1, triangularcreator(counter) + 1):
if triangularcreator(counter) % i == 0:
divisors.append(i)
if len(divisors) == 500:
print(triangularcreator(counter))
break
counter +=1
divisors.clear()
You should try to change a few things, starting with calculating just once the value of triangularcreator(counter) and assigning this value to a variable that you can use in different points of your code.
Second, you create a loop which will be calculate always triangularcreator(1). At the end of each iteration you increase the value of counter+=1, but then at the beginign of the new iteration you assignt it again value 1, so it will not progress as you expect. Try this few things:
counter = 1
while True:
triangle = triangularcreator(counter)
for i in range(1, triangle + 1):
if triangle % i == 0:
divisors.append(i)
if len(divisors) == 500:
print(triangle )
break
counter +=1
Also these two arrays nums = [1], triangles = [1] should be declared and initialized inside the def triangularcreator. Otherwise you would be appending elements in each iteration
Edit: I believe it is better to give you my own answer to the problem, since you are doing some expensive operations which will make code to run for a long time. Try this solution:
import numpy as np
factor_num = 0
n = 0
def factors(n):
cnt = 0
# You dont need to iterate through all the numbers from 1 to n
# Just to the sqrt, and multiply by two.
for i in range(1,int(np.sqrt(n)+1)):
if n % i == 0:
cnt += 1
# If n is perfect square, it will exist a middle number
if (np.sqrt(n)).is_integer():
return (cnt*2)-1
else:
return (cnt*2)-1
while factor_num < 500:
# Here you generate the triangle, by summing all elements from 1 to n
triangle = sum(list(range(n)))
# Here you calculate the number of factors of the triangle
factor_num = factors(triangle)
n += 1
print(triangle)
Turns out that both of your while loop are infinite either in triangularcreatorin the other while loop:
nums = [1]
triangles = [1]
divisors = []
def triangularcreator(x):
if x == 1:
return 1
n = 1
sum = 0
while n:
n += 1
nums.append(n)
for i in range(len(nums)):
sum += nums[i]
triangles.append(sum)
sum = 0
if len(triangles) >= x:
return triangles[-1]
return triangles[-1]
counter = 1
while True:
check = triangularcreator(counter)
for i in range(1, check + 1):
if check % i == 0:
divisors.append(i)
if len(divisors) >= 500:
tr = triangularcreator(counter)
print(tr)
break
counter +=1
Solution
Disclaimer: This is not my solution but is #TamoghnaChowdhury, as it seems the most clean one in the web. I wanted to solve it my self but really run out of time today!
import math
def count_factors(num):
# One and itself are included now
count = 2
for i in range(2, int(math.sqrt(num)) + 1):
if num % i == 0:
count += 2
return count
def triangle_number(num):
return (num * (num + 1) // 2)
def divisors_of_triangle_number(num):
if num % 2 == 0:
return count_factors(num // 2) * count_factors(num + 1)
else:
return count_factors((num + 1) // 2) * count_factors(num)
def factors_greater_than_triangular_number(n):
x = n
while divisors_of_triangle_number(x) <= n:
x += 1
return triangle_number(x)
print('The answer is', factors_greater_than_triangular_number(500))

Palindromic numbers divisible by any given number

I have the following problem to solve:
The numbers 545, 5995 and 15151 are the three smallest palindromes divisible by 109. There are nine palindromes less than 100000 which are divisible by 109.
How many palindromes less than 10**32 are divisible by 10000019 ?
So my code is shown below.
In theory my code will work, but to count all the way from 0 to 10**32 would take my computer literally YEARS.
Is there anyway to improve this code?
Python code:
listPalindroms=[]
for i in range (0,10**32):
strI = str(i)
printTrue = 1
if len(strI) == 1:
listPalindroms.append(i)
else:
if len(strI)%2 ==0:
FinalVal = int(len(strI)/2)
for count in range (0,FinalVal):
if strI[count]!=strI[-count-1]:
printTrue = 0
if printTrue==1: listPalindroms.append(i)
else:
FinalVal = int(round(len(strI)/2))-1
for count in range (0,FinalVal):
if strI[count]!=strI[-count-1]:
printTrue = 0
if printTrue ==1: listPalindroms.append(i)
i=0
for item in listPalindroms:
if item%10000019 ==0:
i = i + 1
print (i)
The problem is presented as Project Euler 655
You are getting all palindromes between 0 and 10**32 then filtering using divisibility. But you can do it the other way around also. Just find the multiples of 10000019 that are less than 10**32 then check if each multiple is a palindrome.
This way you can avoid checking palindromes for numbers that are not required.
i = 1
number = 10000019
list_palindromes = []
element = number * i
while element < (10**32):
e = str(element)
for j in range(len(e)):
if e[j] != e[len(e)-j-1]:
break
if len(e)-1 == j:
list_palindromes.append(e)
print(e)
i += 1
element = number * i
Given that MathJax doesn't work here it's gonna be tough to present my solution.
When you look at a number, eg. 1991, you can write this as 1000*1+100*9+10*9+1*1.
If you look at the remainder when dividing by 19 we have that:
(1000*1+100*9+10*9+1*1)%19 = ((1000%19)*1+(100%19)*9+(10%19)*9+(1%19)*1)%19 = (12*1+5*9+10*9+1*1)%19 = 10.
Therefore 19 doesn't divide 1991
For a palindrome, abcba, we can use this property of modular arithmetic to see that 19 divides abcba if and only if:
(7*a + 3*b + 5*c)%19 = 0
Because
(10000*a+1000*b+100*c+10*b+a)%19 = (10001*a+1010*b+100*c)%19 = (10001*a%19+1010*b%19+100*c%19)%19 = (7*a + 3*b + 5*c)%19
By using this method we can cut the number of iterations down to the square root of the max value. A routine for calculating the sum of ever palindrome less than 10**10 that is divisible by 109 will look some thing like this.
maxValue = 10**5
divisor = 109
moduli = []
for i in range(0,33):
moduli.append((10**i)%divisor)
def test(n,div):
n = str(n)
sum_odd = 0
sum_even = 0
for i in range(len(n)):
sum_even = sum_even + int(n[i])*(moduli[i]+moduli[2*len(n)-i-1])
if i != len(n)-1:
sum_odd = sum_odd + int(n[i])*(moduli[i]+moduli[2*len(n)-i-2])
else:
sum_odd = sum_odd + int(n[i])*(moduli[i])
if sum_odd%div==0 and sum_even%div==0:
return 2
if sum_odd%div==0 or sum_even%div==0:
return 1
else:
return 0
# The sum starts at -1 because 0 is counted twice
sum = -1
for a in range(maxValue):
sum = sum + test(a,divisor)
print(sum)
Running the calculation for every palindrome less than 10**32, still requires 10**16 iterations, so it's not efficient enough for your problem, it's however better than previous answers (requiring about 10**24 iterations).
Well, you just need to check for numbers divisible by your divisor, so why check numbers before that, and while incrementing, why not just increment the divisor amount?
def is_palin(num):
num_str = str(num)
for index in range(len(num_str)/2):
if num_str[index]==num_str[len(num_str)-1-index]:
continue
return False
return True
def multiple(divisor, end):
count=0
index = divisor*2
while index<end:
if is_palin(index):
count+=1
index+=divisor
return count
if __name__=="__main__":
print(multiple(109, 100000))
# print(multiple(10000019, 10**32))
This approach still takes a lot of time, and I'd recommend finding a better method.

Using a loop to describe multiple conditions

In the following code, I am trying to extract numbers from a list in which all digits are divisible by 2. The following code works.
l = range(100,401)
n=[]
for i in l:
s =str(i)
if all([int(s[0])%2==0,int(s[1])%2==0,int(s[2])%2==0]):
n.append(s)
print(",".join(n))
I was trying to insert a for loop to avoid writing all three conditions explicitly.
l = range(100,401)
n=[]
ss=[]
for i in l:
s =str(i)
ss.append(s)
for element in ss:
for j in range(3):
if int(element[j])%2==0:
n.append(element)
print(n)
I can't get the desired output. Not only that, the elements of output list 'n' at even index are printed twice. I am unable to figure out WHY?
Thanks.
Generator expression checking if all() elements evaluate to True comes to your rescue:
l = range(100,401)
n=[]
for i in l:
s = str(i)
if all(int(ch) % 2 == 0 for ch in s):
n.append(s)
print(",".join(n))
Now it also works even if you work with more digits.
Thanks for #jpp's advice on generator expression!
And here a faster alternative where you evaluate if any() is not divisable with 2.
l = range(100,401)
n=[]
for i in l:
s = str(i)
if any(int(ch) % 2 != 0 for ch in s):
continue
else:
n.append(s)
print(",".join(n))
You can do this:
l = range(100, 401)
n = []
for i in l:
v = 0
for j in str(i):
if int(j) % 2 == 0:
v += 1
if v == len(str(i)):
n.append(str(i))
print(",".join(n))
Or with some list comprehension:
l = range(100, 401)
n = []
for i in l:
if all(int(j) % 2 == 0 for j in str(i)):
n.append(str(i))
print(",".join(n))
Or with even more list comprehension:
l = range(100, 401)
n = [str(i) for i in l if all(int(j) % 2 == 0 for j in str(i))]
print(",".join(n))
Or with a ridiculous minimizing:
print(",".join([str(i) for i in range(100, 401) if all(int(j) % 2 == 0 for j in str(i))]))
Explaining
OP asked me to explain why his code doesn't work. I'll make it in some steps, also optimizing it:
l = range(100,401)
n = []
ss = []
for i in l: # You don't need this loop, you are just making a new list with string values instead of integers. You could make that on the fly.
s = str(i)
ss.append(s)
for element in ss:
for j in range(3):
if int(element[j]) % 2 == 0: # This only check if the current digit is pair and it append the whole number to the list. You have to check if the 3 numbers are pair AND then append it.
n.append(element)
print(n)
Your code check each digit and if that is true, the number is appended to the result list (n). But you don't want that, you want to check if the 3 digits that make the number are pair, so you have to check the whole group.
For example you could do this:
for element in l:
pairs = 0
for j in range(3):
if int(str(element)[j]) % 2 == 0:
pairs += 1 # Each time a digit of the number is pair, `pairs` variable increase in one
if pairs == 3: # If the 3 digits are true it append your number
n.append(str(element))
That is my first idea of how to improve your code, but instead of element and pairs I use j and v, (also I don't use range(3), I just iterate over the stringed number).
If you are looking for something "better" you could try to use a list comprehension like all(int(j) % 2 == 0 for j in str(i)). That iterate over all the digits to check if the are pair, if all the checks are true (like 222, or 284) it returns true.
Let me know if I should explain something more.
Try this method. You don't need to check all the numbers.
You just need to change the range statement from range(100, 401) to range (100, 401, 2) and add some checks as the Numbers which have first digit as Odd you can skip all the 100 numbers and then in next 10 series you can skip 10 if the tenth digit is odd. It reduces the complexity and decreases your processing time.
l = range(100, 401, 2)
n = []
for i in l:
s = str(i)
if int(s[0]) % 2 == 1:
remainder = i % 100
i = i - remainder + 100 - 1
continue
elif int(s[1])%2 == 1:
remainder = i % 10
i = i - remainder + 10 - 1
continue
n.append(s)
print(",".join(n))

Python: Create a list of all four digits numbers with all different digits within it

I was wondering if there is any easier way to achieve what this code is achieving. Now the code creates all 4-digits number in a list (if the number starts with a 0 is doesn't count as a 4-digit, for example 0123) and no digit is repeated within the number. So for example 1231 is not in the list. Preferable I want a code that does what this one is doing but a depending on what argument N is given to the function upon calling it creates this kind of list with all numbers with N digits. I hope this wasn't impossible to understand since Im new to programing.
def guessables():
'''creates a list of all 4 digit numbers wherest every
element has no repeating digits inside of that number+
it doesn't count as a 4 digit number if it starts with a 0'''
guesses=[]
for a in range(1,10):
for b in range(0,10):
if a!=b:
for c in range(0,10):
if b!=c and a!=c:
for d in range(0,10):
if c!=d and d!=b and d!=a:
guesses.append(str(a)+str(b)+str(c)+str(d))
return guesses
This can be expressed more easily.
def all_digits_unique(number):
# `set` will only record unique elements.
# We convert to a string and check if the unique
# elements are the same number as the original elements.
return len(str(number)) == len(set(str(number)))
Edit:
def guesses(N):
return filter(all_digits_unique, range(10**(N-1), 10**N))
print guesses(4)
I'd use itertools for this which is in my opinion the simplest generic answer:
import itertools
def guessables(num):
guesses = []
for p in itertools.permutations(xrange(10),num):
if p[0] != 0:
guesses.append(''.join(map(str, p)))
return guesses
Simply call this function with guessables(4) and get a list with all the numbers you want.
You can do in one line:
print([str(a)+str(b)+str(c)+str(d) for a in range(1,10) for b in range(0,10) if a!=b for c in range(0,10) if b!=c and a!=c for d in range(0,10) if c!=d and d!=b and d!=a])
Try the following:
def guessables(n):
''' Returns an array with the combination of different digits of size "n" '''
if n > 10:
raise ValueError("The maximum number of different digits is 10.")
elif n < 1:
raise ValueError("The minimum number of digits is 1.")
else:
results = []
for i in range(1, 10):
_recursiveDigit([i], n, results)
return results
def _formatDigit(l):
''' Return a formated number from a list of its digits. '''
return "".join(map(str, l))
def _recursiveDigit(l, n, results):
''' Recursive function to calculate the following digit. '''
if len(l) < n:
for i in range(0, 10):
if i not in l:
_recursiveDigit(l + [i], n, results)
else:
results.append(_formatDigit(l))
The functions that are prefixed with an underscore(_) should not be called from outside of this script. If you prefer to have the result as something different than an array of strings, such as an array of ints for example, you can change the _formatDigit() function as follows:
def _formatDigit(l):
''' Return a formated number from a list of its digits. '''
return int("".join(map(str, l)))
c=list(range(10))
print c
def fun(n,k,i,getnum): # function , result in getnum
if n==0:
if k not in getnum and len(set(list(k)))==len(k) and k[0]!='0':
getnum.append(k)
return
if i>=len(c):
return
fun(n-1,k+str(c[i]),0,getnum)
fun(n,k,i+1,getnum)
getnum=[]
d=fun(4,"",0,getnum)
print getnum
These types of problems are easily solved with recursion.
def gen(num, n, saveto):
if len(num) == 1 and num[0] == '0':
return
if len(num) == n:
saveto.append(int(''.join(num)))
return
for i in range(0, 10):
i= str(i)
if i not in num:
gen(num+[i], n, saveto)
saveto= []
# generate 4 digit numbers
gen([], 4, saveto)
print(saveto)
Here I'm using the list num to construct the numbers by placing one digit at each call. When there are four digits added, it stores the number to the saveto list.
Edit: Here's a version of the above function that returns the list of numbers instead of appending them to a list.
def gen(num, n):
if len(num) == 1 and num[0] == '0':
return []
if len(num) == n:
return [int(''.join(num))]
ans = []
for i in range(0, 10):
i= str(i)
if i not in num:
ans.extend(gen(num+[i], n))
return ans
saveto= gen([], 4)
print(saveto)
numPool = []
for i in range(0, 10):
for j in range(0, 10):
for k in range(0,10):
for l in range(0,10):
if i != j and i != k and i != l and j != k and j != l and k != l :
numPool.append(str(i) + str(j) + str(k) + str(l))
This works, but keep in mind that this will also add "0123" or "0234" to the list as well. If you do not want the numbers that are starting with zero, you might want to add "i != 0" to the if query. Hope it helps.
I try to write it clear for absolute beginers ^^ Ofcourse it is possible to make it faster and shorter if you use combianations and advance array methods.
def f(n)
s = list(range(10**(n-1), 10**n))
number_list = []
for ss in s:
test_list = []
a = ss
while ss:
if ss % 10 in test_list:
break
test_list.append(ss % 10)
ss = ss // 10
if len(test_list) == n:
number_list.append(a)
return number_list
print(f(4))
This would sovlve the problem, without repeating digits:
from itertools import permutations
myperm = permutations([0,1,2,3,4,5,6,7,8,9],4)
for digits in list(myperm):
print(digits)
How about this?
def check_count(num):
if isinstance(num, str) == False:
num = str(num) # Convert to str
if len(num) == 1: # If total length number is single, return False
return False
return any(num.count(x) > 1 for x in num) # Check here
Return False if numbers all different, else return True
Usage:
# Get all numbers has all different. (1000-9999)
[x for x in range(1000, 10000) if check_count(x) == False]

Categories

Resources