Is there a know algorithm to factor an integer into as few factors as possible (not necessarily prime) where every factor is less than some given constant N?
I don't care about numbers with a prime factor greater than N. Also, I'm not dealing with numbers greater than a few million and the factoring is part of the processing initialization, so I'm not especially worried about computational complexity.
EDIT: Just to be clear. I already have code find the prime factors. I'm looking for a way to combine those factors into as few composite factors as possible while keeping each factor less than N.
You can solve your problem by dividing it into two parts:
Factorize your number into primes using any of the standard techniques. For a number of only a few million, trial division would be perfectly fine.
Take the logarithm of each factor, and pack them into bins of size log N.
Now, bin packing is NP-hard but in practice it is possible to find good approximate solutions using simple techniques: the first-fit algorithm packs no more than 11/9 times the optimal number of bins (plus one bin).
Here's an implementation in Python:
from math import exp, log, sqrt
import operator
def factorize(n):
"""
Factorize n by trial division and yield the prime factors.
>>> list(factorize(24))
[2, 2, 2, 3]
>>> list(factorize(91))
[7, 13]
>>> list(factorize(999983))
[999983]
"""
for p in xrange(2, int(sqrt(n)) + 1):
while n % p == 0:
yield p
n //= p
if n == 1:
return
yield n
def product(s):
"""
Return the product of the items in the sequence `s`.
>>> from math import factorial
>>> product(xrange(1,10)) == factorial(9)
True
"""
return reduce(operator.mul, s, 1)
def pack(objects, bin_size, cost=sum):
"""
Pack the numbers in `objects` into a small number of bins of size
`bin_size` using the first-fit decreasing algorithm. The optional
argument `cost` is a function that computes the cost of a bin.
>>> pack([2, 5, 4, 7, 1, 3, 8], 10)
[[8, 2], [7, 3], [5, 4, 1]]
>>> len(pack([6,6,5,5,5,4,4,4,4,2,2,2,2,3,3,7,7,5,5,8,8,4,4,5], 10))
11
"""
bins = []
for o in sorted(objects, reverse=True):
if o > bin_size:
raise ValueError("Object {0} is bigger than bin {1}"
.format(o, bin_size))
for b in bins:
new_cost = cost([b[0], o])
if new_cost <= bin_size:
b[0] = new_cost
b[1].append(o)
break
else:
b = [o]
bins.append([cost(b), b])
return [b[1] for b in bins]
def small_factorization(n, m):
"""
Factorize `n` into a small number of factors, subject to the
constraint that each factor is less than or equal to `m`.
>>> small_factorization(2400, 40)
[25, 24, 4]
>>> small_factorization(2400, 50)
[50, 48]
"""
return [product(b) for b in pack(factorize(n), m, cost=product)]
I don't know if there is an established algorithm, but I would try the following
public static List<Integer> getFactors(int myNumber, int N) {
int temp=N;
int origNumber=myNumber;
List<Integer> results=new ArrayList<Integer>();
System.out.println("Factors of "+myNumber+" not greater than "+N);
while (temp>1) {
if (myNumber % temp == 0) {
results.add(temp);
myNumber/=temp;
} else {
if (myNumber<temp) {
temp= myNumber;
} else {
temp--;
}
}
}
for (int div : results) {
origNumber/=div;
}
if (origNumber>1) {
results.clear();
}
return(results);
}
I hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With