3

It's hard to explain in just the title, but basically I have created a system that inputs some number N and outputs two numbers (excluding 1 and N) that can be multiplied together to be as close to N as possible (going over instead of under).

Here's a few examples:

  • 25 → 5 & 5.
  • 40 → 5 & 8.
  • 53 → 6 & 9.
  • 13 → 2 & 7.

I have a method Factor that returns a list of all factors of X sans 1 and X. This code also doesn't need to work with big numbers, so I test for primality by checking if it's in a list of prime numbers.

The code that does it is here:

if (primes.Contains(N))
        N++;
List<int> facts = Factor(N);
double root = Math.Sqrt(N);
int cl1;
int cl2;
if (root == (int)root)
{
    cl1 = (int)root;
    cl2 = (int)root;
}
else if (N == 2)
{
    cl1 = 1;
    cl2 = 2;
}
else
{
    cl1 = facts.Aggregate((x, y) => Math.Abs(x - root) < Math.Abs(y - root) ? x : y);
    facts.Remove(cl1);
    cl2 = facts.Aggregate((x, y) => Math.Abs(x - root) < Math.Abs(y - root) ? x : y);
}

What would be a good way to generalize this so it could give three outputs, or four or five or nine? (Obviously I would swap out cl1 and cl2 with an array, but I mean code-wise)

theB
  • 6,450
  • 1
  • 28
  • 38
tryashtar
  • 278
  • 3
  • 13
  • Since you don't need to handle large numbers simply getting all factors of non-prime numbers starting with target and checking if number of factors is greater or equal to target may be an easier approach... – Alexei Levenkov Aug 26 '15 at 01:00
  • @AlexeiLevenkov: With memoization, that might even work reasonably well with moderately large inputs too. – Ben Voigt Aug 26 '15 at 01:08
  • to improve your search you could use the https://en.wikipedia.org/wiki/Dichotomy method – Mickael Thumerel Aug 26 '15 at 09:25
  • If you treat two as a special case, then an algorithm that can solve this problem efficiently (for any bit length) would also be able to decompose large semiprimes. So you should not expect to be able to identify an efficient algorithm to do this. – Leo Oct 08 '15 at 03:13

1 Answers1

1

Getting all the factors of N is a pretty expensive operation. It will actually be faster to do it like this (pseudocode):

For p = floor(sqrt(N)); p>1; --p:    
  q = ceil(N/p);
  error = p*q-N; //always positive
  record=make_tuple(p,q,error);
  //... remember the records with the smallest error

The best way to maintain the list of records depends on how many you want. Call that number M.

If it's just a few, then you can just put them in a list and whenever the list size gets to 2M, sort it by error and truncate to size M.

If it's a lot, then put them in a priority queue with max error first, and whenever the size is >M, remove the one with the highest error. At the end you can pull them out in reverse order and fill your output array backwards

Matt Timmermans
  • 53,709
  • 3
  • 46
  • 87