Enumerate factors of an integer - Page 1
Forum section: electronics / general

author: blueskull
author_rank: Unknown
timestamp: April 17, 2018, 01:01:00 pm
content: I've been thinking on this problem for a while, and I have yet to find a way to do this.The problem is simple: find all factor combination of a number.For instance, given 20, output should be:2*102*2*52*5*210*22*5*25*2*2Or given input 40, I should have:2*202*2*102*2*2*52*2*5*22*10*24*104*2*54*5*28*52*4*510*410*2*22*5*45*2*42*5*2*25*2*2*220*2One way I can think of is to use recursion, first find out all factors, then loop through all factors f, then factorize f and n/f in a recursive manner.Finally, eliminate all duplicate terms. This is how I do this in mind.Is there a better way to achieve this?

author: rstofer
author_rank: Super Contributor
timestamp: April 17, 2018, 01:18:28 pm
content: I have no idea how to solve the problem but I did notice that you have 4 permutations of 5*2*2*2. Do you consider that to be a different set of factors than 2*2*2*5?The number is completely factored when all factors are prime numbers, if that helps. I might start with the lowest usable prime (2) and divide as many times as possible before moving up to 3 then 5 then 7 and so on.Sooner or later, this is going to get to 'number theory' and the math will lead toward crypto since keys are often related to the product of two large prime numbers.https://en.wikipedia.org/wiki/Integer_factorization

author: rstofer
author_rank: Super Contributor
timestamp: April 17, 2018, 01:36:10 pm
content: Repeated successful integer division by ascending primes will get you the factors as a string of prime numbers (a vector) and you can get the repeated factors by scrambling the vector: 2*2*2*5, 2*2*5*2, 2*5*2*2, 5*2*2*2.I just know there is a clever way to do this but I would start with brute force.

author: bd139
author_rank: Super Contributor
timestamp: April 17, 2018, 02:37:48 pm
content: It's easier to factor it into a tree of primes using an off the shelf algorithm then process the resulting tree into intermediate factors.So if you factor 40 for example, this will result in a tree with leaves of 2, 2, 2, 2, 5. You can then visit the tree (visitor pattern or recursive descent) and calculate all permutations by combining two or more leaves.If you combine two "2" leaves you get: 4*2*2*5.If you combine "2" and "5" leaves you get 2*2*2*10etc etc

author: Tom45
author_rank: Frequent Contributor
timestamp: April 17, 2018, 02:45:32 pm
content: For numbers <= 100 you can just brute force it. For very large numbers, brute force might take considerable time.Anyway, take a look at dynamic programming, a technique that takes advantage of what you already know.Starting at n = 2, factor it and store the results in a table. Then n = 3, etc.Once you get up to 4, you have 2 with 2 left over. But you already know the answer for the leftover 2. So just append that to the first 2.For 20, the first factor is 2 plus what you already know about 10. The second factor is 4 plus what you already know about 5, etc.For 40, 2 plus what you know about 20, 4 plus what you know about 10, 5 plus what you know about 8, etc.You missed 5*8 in your example.Tom

author: Brumby
author_rank: Unknown
timestamp: April 17, 2018, 03:01:49 pm
content: I've done an Excel spreadsheet that will give you the prime factors of a number.Let me see if I can find it...

author: rstofer
author_rank: Super Contributor
timestamp: April 17, 2018, 03:13:19 pm
content: Quote from: blueskull on April 17, 2018, 01:54:08 pmYes but it will be found before the '4' is factored. Which may actually occur after all the 2*2*2* factors are obtained.I have no idea how to write the loop but this certainly looks like a Fortran program to me!

author: Brumby
author_rank: Unknown
timestamp: April 17, 2018, 03:20:46 pm
content: Found it.This will give you all the prime factors for any integer from 1 to just over 1 million.Not particularly elegant, but it works. It does depend on having a list of all the primes up to 1,000 though.

author: Ampera
author_rank: Super Contributor
timestamp: April 17, 2018, 03:28:12 pm
content: The way I would do it is to write a dynamic C program (to get the best speed possible) that would do an optimized form of brute forcing. I would first perform a few tests on the number to see what single numbers do NOT go into it. No use testing numbers that are known not to be factors (even factors can't go into odd numbers, the sum of the numbers of a multiple of 3 has to itself sum to a multiple of 3, etc)Next, start with the lowest possible factor. I don't know if you would include 1, but for simplicity's sake, we can assume that it's a bad idea, given that 1xn = 1x1xn = 1x1x1xn. Next, multiply through the full list of possible factors. For 16, we would start with 2x2 (cross off), go onto 2x3 (cross off), and so on until we hit 2x8, which is the target number, or has gone past it, and we finish by writing that down or crossing it off (in the event none of these are factors).Continue on with a third digit. (2x2x2) and keep going with 2x2x3, and then you hit 2x2x4. (Equal or greater, finish this)Keep expanding that list, taking priority to expand the second digit first, and then the third (So you get 2x3x2 before you do 2x3x3) Keep going until you equal or greater the number on all first tries, and all extensions of the number of digits. Keeping in mind to only ever use factors that can be possible. So in this case, we would never use 3, 6, 5, or 9 as a single digit factor, or any multiples of those, because we know as fact that they can't possible be factors.This is still brute forcing (and I hope I made some sense) but with further and further shortcuts and optimizations, in theory we could keep pushing the time limit farther.Eventually we will hit a wall with modern computing, as each next number we calculate the list of factors for will be slower and slower until we cannot go farther with our computing power, but with the brunt of modern computing, I imagine that it would take a little while at least.Keep in mind, factoring takes a lot of time and effort on computing. You could also try other approaches like working backwards, starting with the largest possible factors and working your way back, that way you will eliminate the need to test smaller factors, but it's a game of finding ways to speed it up.Ultimately, if you are looking for a way to do this for a practical problem, you need to figure out how far you need to take this. If you just want to do it for kicks, I'd pick up the C, write something like this, and watch as it fills up a text file with factor tables.

author: Ampera
author_rank: Super Contributor
timestamp: April 17, 2018, 03:55:52 pm
content: nice.

author: rhb
author_rank: Super Contributor
timestamp: April 17, 2018, 04:03:17 pm
content: rhb@Hipster:~/Documents/vref$ cat tst3.c#include <stdio.h>int main(){int i;int n = 100;i = 2;while( n > 1 ){if( !(n % i) ){printf( "factor %d\n" ,i );n /= i;}else{i++;}}}

author: helius
author_rank: Super Contributor
timestamp: April 17, 2018, 04:16:47 pm
content: Prime factorization was one of the first programs I typed in when I bought my Casio fx7000ga in the eighth grade. The program was actually an example in the user manual: I found it very helpful for reducing fractions. It used a speed/space tradeoff because the calc had a pitiful memory size (testing divisibility by 2, then every odd factor will pick up only primes, since composites will never be the smallest remaining factors).

author: alexanderbrevig
author_rank: Frequent Contributor
timestamp: April 17, 2018, 04:35:33 pm
content: Code:function printFactors(factors, prefix, input) {var i = 2;while (i<=input) {if (input%i === 0 && input/i>1) {factors.push(prefix + (i + "*" + (input/i)));if (i>1) {printFactors(factors, prefix + i + "*", input/i);}}i++;}}var factors = [];printFactors(factors, "", 40)console.log(factors);EDIT: if you set i=1, you aslo get 1*40 and the rest such as 1*2*20JavaScript is fun

author: bd139
author_rank: Super Contributor
timestamp: April 17, 2018, 04:38:20 pm
content: Python is more fun:Code:def factor_tree(n):for i in xrange(2, n):if n % i == 0:return (n, factor_tree(n / i), factor_tree(i))return (n, None, None)print(factor_tree(198))Haven't written the tree visitor yet

author: helius
author_rank: Super Contributor
timestamp: April 17, 2018, 04:46:09 pm
content: It seems to me that if you want to enumerate all products ∏(n1, n2, ...)=m where you don't care if n_i is prime and you don't have any regular ordering, then you are in effect collecting all the permutations of all of the partitions of the prime factors of m.For example, the prime factorization of 100 is (2, 2, 5, 5).All of the partitions of this multiset are [(2), (2), (5), (5)], [(2, 2), (5), (5)], [(2, 5), (2), (5)], [(5, 5), (2), (2)], [(2, 5), (2, 5)], [(2, 2), (5, 5)], [(2, 2, 5), (5)], [(2, 5, 5), (2)], and [(2, 2, 5, 5)].Taking the permutations of each of these, we have every possible sequence of multiplicands that produces 100.P([(2), (2), (5), (5)]): (2, 2, 5, 5) (2, 5, 2, 5) (2, 5, 5, 2) (5, 2, 5, 2) (5, 2, 2, 5) (5, 5, 2, 2)P([(2, 2), (5), (5)]): (4, 5, 5) (5, 4, 5) (5, 5, 4)P([(2, 5), (2), (5)]): (10, 2, 5) (10, 5, 2) (5, 10, 2) (5, 2, 10) (2, 10, 5) (2, 5, 10)P([(5, 5), (2), (2)]): (25, 2, 2) (2, 25, 2) (2, 2, 25)P([(2, 5), (2, 5)]): (10, 10)P([(2, 2), (5, 5)]): (4, 25) (25, 4)P([(2, 2, 5), (5)]): (20, 5) (5, 20)P([(2, 5, 5), (2)]): (50, 2) (2, 50)P([(2, 2, 5, 5)]): (100)

author: rhb
author_rank: Super Contributor
timestamp: April 17, 2018, 06:12:37 pm
content: Quote from: blueskull on April 17, 2018, 04:12:50 pmSorry, my sister was agitating to go move some furniture. I should have waited until later to respond.What you are asking for is NP-hard. You probably want to rethink the question. The number of permutations is of order N! and in this case, larger as you are also considering coalescing terms. For 10 prime factors considered individually you have over 3 million choices. If you combine two terms you have N*(N-1)*(N-1)! permutations. I'll leave you to work out the number of permutations. for the general case. Suffice it to say that any program that attempts this with integers of any size will be prone to going into a denumerably infinite loop.You may *think* you want an algorithm that does what you asked, but you *really* don't.If I may ask, what are you trying to do?

author: T3sl4co1l
author_rank: Super Contributor
timestamp: April 17, 2018, 09:05:47 pm
content: This appears to be the sequence in question, and includes code:https://oeis.org/A001055It may not be optimal code for large N.Tim

author: orolo
author_rank: Frequent Contributor
timestamp: April 18, 2018, 04:42:03 pm
content: Well, your problema is divided in two parts. First, you need to factor the number which, while nontrivial, you have already handled for your cases of interest.Second, you need to find all the possible combinations of the multiset of prime factors, for any given number of factors. Let's see an example.You want to find all the factors of 540. First, you factor it: 540 = 2*2*3*3*3*5. These six bricks made up all the divisors of 540. Then you loop from 0 to 6.Take 0 factors: the trivial divisor, 1.Take 1 factor: 2, 3, and 5.Take 2 factors: 2*2, 2*3, 2*5, 3*3, 3*5 -> 4, 6, 10, 9, 15.Take 3 factors: 2*2*3, 2*2*5, 2*3*3, 2*3*5, 3*3*3, 3*3*5 -> 12, 20, 18, 30, 27, 45.Take 4 factors: 2*2*3*3, 2*2*3*5, 2*3*3*3, 2*3*3*5, 3*3*3*5 -> 36, 60, 90, 135.Take 5 factors: 2*2*3*3*3, 2*2*3*3*5, 2*3*3*3*5 -> 108, 180, 270.Take 6 factors: 2*2*3*3*3*5 -> 540.So, the divisors are: 1,2,3,4,5,6,9,10,12,15,18,20,27,30,36,45,60,90,108,135,180,270,540.Therefore, your only problem is to efficiently generate combinations (of a given size) of a multiset. If you want to efficiently do this, see for examplehttp://www.kcats.org/csci/464/doc/knuth/fascicles/fasc3a.pdf. Since Knuth states that combinations of a multiset can be easily reduced to combinations without repetition (with some reomoval of duplicates), you could use one of the many algorithms proposed. Or you can go all the way to Theorems K, M and W, and spend some time with shadows and multidimensional tori.Probably, since you are working with not too big numbers anyway, you can just (ab)use the iteration tools of your choice language. For a quick and dirty python solution:Code:import itertools, functoolsfactors = [2, 2, 3, 3, 3, 5]result = for n in range(1, 1 + len(factors)):combinations = list(itertools.combinations(factors, n))divisors_rep = map(lambda z: functools.reduce(lambda x, y: x*y, z), combinations)divisors = list(set(divisors_rep))result = result + divisorsprint sorted(result)The output being: [1, 2, 3, 4, 5, 6, 9, 10, 12, 15, 18, 20, 27, 30, 36, 45, 54, 60, 90, 108, 135, 180, 270, 540]Note I skipped 54 in the explanation above. I hope this gives some hints about how to implement this.

author: Nominal Animal
author_rank: Super Contributor
timestamp: April 18, 2018, 05:50:20 pm
content: Here's how to obtain all permutations of the product that matches a specific positive integer:First, find out the prime factorsfi? 2, for example in ascending order. Let's say you haveNprime factors,i= 0 toN-1, inclusive.Because the root expression hasN-1 multiplications, we need a loop fromm= 0 to 2N-1-2, inclusive, to construct all possible terms. (Them= 2N-1-1 term corresponds to the original value -- all multiplies applied! --, so we can ignore that one.)Within eachmloop iteration, create a stack of factors. Start with the first prime factor in the accumulator. Do a loopk= 1 toN-1, inclusive. If the binary digitkofmis nonzero, push the accumulator to the stack, and set accumulator equal tok'th prime factor. Otherwise, multiply the accumulator with thek'th prime factor. After thekloop, push the accumulator to the stack.You now have them'th set of factors for the original value.Next, still within themloop iteration, we need to generate all permutations of the stack, and print each permutation. If the stack hasLfactors, then there areLpermutations.Obviously, this approach does produce quite a lot of duplicates, because e.g.2*2*2=2*4=4*2=8, so you still need to eliminate duplicates.Consider an example: 546 =2*3*7*13.Themloop produces the following stacks:2*3*7*13,6*7*13,2*21*13,42*13,2*3*91,6*91,2*273. (Them= 7 that we skip would correspond to stack546, as I already mentioned.)Let's consider just one of those stacks, say the second (form= 1):6*7*13. It has three factors, and therefore 3! = 1*2*3 = 6 permutations. They are6*7*13,6*13*7,7*6*13,7*13*6,13*6*7, and13*7*6.In all, for 546, this approach produces 24+6+6+2+6+2+2 = 48 candidates, which might contain some duplicates. (That number, 48, does not include the number itself, 546; only the products with two or more terms greater than one that multiply to 546.)(Actually, I believe, but have no proof, that this generates duplicates only if the prime factors are not unique.)

author: Brumby
author_rank: Unknown
timestamp: April 19, 2018, 12:03:14 am
content: I'll step back from the permutation Olympics - since there's enough discussion on that already, but I just wanted to point out that to find out all the factors, you only have to apply your recursive process with primes up to the square root of the value maximum.For example, with a limit of 100, you only need to analyse using the primes up to 10, namely {2, 3, 5, 7}. In fact, using only these primes, you can work out the factors for any integer up to the value of thenextprime {11} squared minus 1. That is to say, a recursive process using {2, 3, 5, 7} can identify the prime factors of every integer up to and including 120.All that is required is a simple statement, the proof of which is trivial. (This statement has been implemented in the spreadsheet I posted above.)