I'm working on this:
Write a function, persistence, that takes in a positive parameter num
and returns its multiplicative persistence, which is the number of
times you must multiply the digits in num until you reach a single
digit.
For example:
persistence(39) == 3 // because 3*9 = 27, 2*7 = 14, 1*4=4
// and 4 has only one digit
persistence(999) == 4 // because 9*9*9 = 729, 7*2*9 = 126,
// 1*2*6 = 12, and finally 1*2 = 2
persistence(4) == 0 // because 4 is already a one-digit number
This is what I tried:
public static int Persistence(long n)
{
List<long> listofints = new List<long>();
while (n > 0)
{
listofints.Add(n % 10);
n /= 10;
}
listofints.Reverse();
// list of a splited number
int[] arr = new int[listofints.Count];
for (int i = 0; i < listofints.Count; i++)
{
arr[i] = (int)listofints[i];
}
//list to array
int pro = 1;
for (int i = 0; i < arr.Length; i++)
{
pro *= arr[i];
}
// multiply each number
return pro;
}
I have a problem with understanding recursion - probably there is a place to use it. Can some1 give me advice not a solution, how to deal with that?
It looks like you've got the complete function to process one iteration. Now all you need to do is add the recursion. At the end of the function call Persistence again with the result of the first iteration as the parameter.
Persistence(pro);
This will recursively call your function passing the result of each iteration as the parameter to the next iteration.
Finally, you need to add some code to determine when you should stop the recursion, so you only want to call Persistence(pro) if your condition is true. This way, when your condition becomes false you'll stop the recursion.
if (some stop condition is true)
{
Persistence(pro);
}
Let me take a stab at explaining when you should consider using a recursive method.
Example of Factorial: Factorial of n is found by multiplying 1*2*3*4*..*n.
Suppose you want to find out what the factorial of a number is. For finding the answer, you can write a foreach loop that keeys multiplying a number with the next number and the next number until it reaches 0. Once you reach 0, you are done, you'll return your result.
Instead of using loops, you can use Recursion because the process at "each" step is the same. Multiply the first number with the result of the next, result of the next is found by multiplying that next number with the result of the next and so on.
5 * (result of rest)
4 * (result of rest )
3 * (result of rest)
...
1 (factorial of 0 is 1).---> Last Statement.
In this case, if we are doing recursion, we have a terminator of the sequence, the last statement where we know for a fact that factorial of 0 = 1. So, we can write this like,
FactorialOf(5) = return 5 * FactorialOf(4) = 120 (5 * 24)
FactorialOf(4) = return 4 * FactorialOf(3) = 24 (4 * 6)
FactorialOf(3) = return 3 * FactorialOf(2) = 6 (3 * 2)
FactorialOf(2) = return 2 * FactorialOf(1) = 2 (2 * 1)
FactorialOf(1) = return 1 * FactorialOf(0) = 1 (1 * 1)
FactorialOf(0) = Known -> 1.
So, it would make sense to use the same method over and over and once we get to our terminator, we stop and start going back up the tree. Each statement that called the FactorialOf would start returning numbers until it reaches all the way to the top. At the top, we will have our answer.
Your case of Persistence
It calls for recursive method as well as you are taking the result and doing the same process on it each time.
Persistence(39) (not single) = return 1 + Persistence(3 * 9 = 27) = 3
Persistence(27) (not single) = return 1 + Persistence(2 * 7 = 14) = 2
Persistence(14) (not single) = return 1 + Persistence(1 * 4 = 4) = 1
Persistence(4) (single digit) = Known -> 0 // Terminator.
At the end of the day, if you have same process performed after each calculation / processing with a termination, you can most likely find a way to use recursion for that process.
You definitely can invoke your multiplication call recursively.
You will need initial sate (0 multiplications) and keep calling your method until you reach your stop condition. Then you return the last iteration you've got up to as your result and pass it through all the way up:
int persistence(int input, int count = 0) {} // this is how I would define the method
// and this is how I see the control flowing
var result = persistence(input: 39, count: 0) {
//write a code that derives 27 out of 39
//then keep calling persistence() again, incrementing the iteration count with each invocation
return persistence(input: 27, count: 1) {
return persistence(input: 14, count: 2) {
return persistence(input: 4, count: 3) {
return 3
}
}
}
}
the above is obviously not a real code, but I'm hoping that illustrates the point well enough for you to explore it further
Designing a simple recursive solution usually involves two steps:
- Identify the trivial base case to which you can calculate the answer easily.
- Figure out how to turn a complex case to a simpler one, in a way that quickly approaches the base case.
In your problem:
- Any single-digit number has a simple solution, which is persistence = 1.
- Multiplying all digits of a number produces a smaller number, and we know that the persistence of the bigger number is greater than the persistence of the smaller number by exactly one.
That should bring you to your solution. All you need to do is understand the above and write that in C#. There are only a few modifications that you need to make in your existing code. I won't give you a ready solution as that kinda defeats the purpose of the exercise, doesn't it. If you encounter technical problems with codifying your solution into C#, you're welcome to ask another question.
public int PerRec(int n)
{
string numS = n.ToString();
if(numS.Length == 1)
return 0;
var number = numS.ToArray().Select(x => int.Parse(x.ToString())).Aggregate((a,b) => a*b);
return PerRec(number) + 1;
}
For every recursion, you should have a stop condition(a single digit in this case).
The idea here is taking your input and convert it to string to calculate that length. If it is 1 then you return 0
Then you need to do your transformation. Take all the digits from the string representation(in this case from the char array, parse all of them, after getting the IEnumerable<int>, multiply each digit to calculate the next parameter for your recursion call.
The final result is the new recursion call + 1 (which represents the previous transformation)
You can do this step in different ways:
var number = numS.ToArray().Select(x => int.Parse(x.ToString())).Aggregate((a,b) => a*b);
convert numS into an array of char calling ToArray()
iterate over the collection and convert each char into its integer representation and save it into an array or a list
iterate over the int list multiplying all the digits to have the next number for your recursion
Hope this helps
public static int Persistence(long n)
{
if (n < 10) // handle the trivial cases - stop condition
{
return 0;
}
long pro = 1; // int may not be big enough, use long instead
while (n > 0) // simplify the problem by one level
{
pro *= n % 10;
n /= 10;
}
return 1 + Persistence(pro); // 1 = one level solved, call the same function for the rest
}
It is the classic recursion usage. You handle the basic cases, simplify the problem by one level and then use the same function again - that is the recursion.
You can rewrite the recursion into loops if you wish, you always can.
Related
I'm working on a project for which I need a very fast algorithm for checking whether a supplied number is pandigital. Though the logic seems sound, I'm not particularly happy with performance of the methods described below.
I can check up to one million 9-digit numbers in about 520ms, 600ms and 1600ms respectively. I'm working on a low-latency application and in production I'll have a dataset of about 9 or 9.5 billion 7- to 9-digit numbers that I'll need to check.
I have three candidiates right now (well, really two) that use the following logic:
Method 1: I take an input N, split into into a byte array of its constituent digits, sort it using an Array.Sort function and iterate over the array using a for loop checking for element vs counter consistency:
byte[] Digits = SplitDigits(N);
int len = NumberLength(N);
Array.Sort(Digits);
for (int i = 0; i <= len - 1; i++)
{
if (i + 1 != Digits[i])
return false;
}
Method 2: This method is based on a bit of dubious logic, but I split the input N into a byte array of constituent digits and then make the following test:
if (N * (N + 1) * 0.5 == DigitSum(N) && Factorial(len) == DigitProduct(N))
return true;
Method 3: I dislike this method, so not a real candidate but I cast the int to a string and then use String.Contains to determine if the required string is pandigital.
The second and third method have fairly stable runtimes, though the first method bounces around a lot - it can go as high as 620ms at times.
So ideally I really like to reduce the runtime for the million 9-digit mark to under 10ms. Any thoughts?
I'm running this on a Pentium 6100 laptop at 2GHz.
PS - is the mathematical logic of the second method sound?
Method 1
Pre-compute a sorted list of the 362880 9-digit pandigital numbers. This will take only a few milliseconds. Then for each request, first check if the number is divisible by 9: It must be to be pandigital. If it is, then use a binary search to check if it is in your pre-computed list.
Method 2
Again, check if the number is divisible by 9. Then use a bit vector to track the presence of digits. Also use modular multiplication to replace the division by a multiplication.
static bool IsPandigital(int n)
{
if (n != 9 * (int)((0x1c71c71dL * n) >> 32))
return false;
int flags = 0;
while (n > 0) {
int q = (int)((0x1999999aL * n) >> 32);
flags |= 1 << (n - q * 10);
n = q;
}
return flags == 0x3fe;
}
Method 1 comes in at 15ms/1M. Method 2 comes in at 5.5ms/1M on my machine. This is C# compiled to x64 on an i7 950.
just a thought: (after the definitition of pandigital from wikipedia)
int n = 1234567890;
int Flags = 0;
int Base = 10;
while(n != 0)
{
Flags |= 1<<(n % Base); n /= Base;
}
bool bPanDigital = Flags == ((1 << Base) - 1);
I need to find the n-th term of this infinite series: 1,2,2,3,3,3,4,4,4,4...
Can you give me a constant time function for this task?
int i = 1;
while(true)
{
if(i = n)
//do things and exit the loop
i++;
}
I think this isn`t going to be a constant time function...
Edit
After reading more comments, it appears I misunderstood the question.
If you want to find the item at nth position an array in constant time, then the answer is trivial: x[n], because array access is constant time. However, if for some reason you were using some container where access time is not constant (e.g. linked list), or did not want to look up value in the array, you'd have to use the arithmetic series formulas to find the answer.
Arithmetic series tells us that the position n of the ith unique item would be
n = i * (i - 1) / 2
So we just need to solve for i. Using quadratic formula, and discarding the nonsensical negative option, we get:
i = Math.Floor( (1 + Math.Sqrt(1 + 8 * n)) / 2)
Original Response
I'm assuming you're looking for the position of the nth unique term, because otherwise the problem is trivial.
Sounds like the first occurrence of the nth unique term should follow arithmetic series. I.e. the position of nth unique term would be:
n * (n - 1) / 2
Given my understanding of the problem, this is more of a math problem than a programming one.
If the problem is:
Given an infinite series that consists of 1 copy of 1, 2 copies of 2, 3 copies of 3... n copies of n, what is the kth value in this series?
Now the first clue when approaching this problem is that there are 1 + 2 + 3... + n values before the first occurance of n + 1. Specifically there are (sum of the first n numbers) values before n+1, or (n)(n-1)/2.
Now set (n)(n-1)/2 = k. Multiply out and rationalize to n^2 - n - 2k = 0. Solve using quadratic equation, you get n = (1 + sqrt(1+8k))/2. The floor of this gives you how many full copies of n there are before, and happily, given zero based indexing, the floor gives you the value at the kth point in the array.
That means your final answer in c# is
return (int) Math.Floor((1 + Math.Sqrt(1 + 8 * k)) / 2);
Given non zero based indexing,
return (int) Math.Floor((1 + Math.Sqrt(-7 + 8 * k)) / 2);
public static long Foo(long index)
{
if (index < 0)
{
throw new IndexOutOfRangeException();
}
long nowNum = 0;
long nowIndex = 0;
do
{
nowIndex += nowNum;
nowNum++;
} while (nowIndex < index);
return nowNum;
}
This is the problem I'm solving (it's a sample problem, not a real problem):
Given N numbers , [N<=10^5] we need to count the total pairs of
numbers that have a difference of K. [K>0 and K<1e9]
Input Format: 1st line contains N & K (integers). 2nd line contains N
numbers of the set. All the N numbers are assured to be distinct.
Output Format: One integer saying the no of pairs of numbers that have
a diff K.
Sample Input #00:
5 2
1 5 3 4 2
Sample Output #00:
3
Sample Input #01:
10 1
363374326 364147530 61825163 1073065718 1281246024 1399469912 428047635 491595254 879792181 1069262793
Sample Output #01:
0
I already have a solution (and I haven't been able to optimize it as well as I had hoped). Currently my solution gets a score of 12/15 when it is run, and I'm wondering why I can't get 15/15 (my solution to another problem wasn't nearly as efficient, but got all of the points). Apparently, the code is run using "Mono 2.10.1, C# 4".
So can anyone think of a better way to optimize this further? The VS profiler says to avoid calling String.Split and Int32.Parse. The calls to Int32.Parse can't be avoided, although I guess I could optimize tokenizing the array.
My current solution:
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
namespace KDifference
{
class Solution
{
static void Main(string[] args)
{
char[] space = { ' ' };
string[] NK = Console.ReadLine().Split(space);
int N = Int32.Parse(NK[0]), K = Int32.Parse(NK[1]);
int[] nums = Console.ReadLine().Split(space, N).Select(x => Int32.Parse(x)).OrderBy(x => x).ToArray();
int KHits = 0;
for (int i = nums.Length - 1, j, k; i >= 1; i--)
{
for (j = 0; j < i; j++)
{
k = nums[i] - nums[j];
if (k == K)
{
KHits++;
}
else if (k < K)
{
break;
}
}
}
Console.Write(KHits);
}
}
}
Your algorithm is still O(n^2), even with the sorting and the early-out. And even if you eliminated the O(n^2) bit, the sort is still O(n lg n). You can use an O(n) algorithm to solve this problem. Here's one way to do it:
Suppose the set you have is S1 = { 1, 7, 4, 6, 3 } and the difference is 2.
Construct the set S2 = { 1 + 2, 7 + 2, 4 + 2, 6 + 2, 3 + 2 } = { 3, 9, 6, 8, 5 }.
The answer you seek is the cardinality of the intersection of S1 and S2. The intersection is {6, 3}, which has two elements, so the answer is 2.
You can implement this solution in a single line of code, provided that you have sequence of integers sequence, and integer difference:
int result = sequence.Intersect(from item in sequence select item + difference).Count();
The Intersect method will build an efficient hash table for you that is O(n) to determine the intersection.
Try this (note, untested):
Sort the array
Start two indexes at 0
If difference between the numbers at those two positions is equal to K, increase count, and increase one of the two indexes (if numbers aren't duplicated, increase both)
If difference is larger than K, increase index #1
If difference is less than K, increase index #2, if that would place it outside the array, you're done
Otherwise, go back to 3 and keep going
Basically, try to keep the two indexes apart by K value difference.
You should write up a series of unit-tests for your algorithm, and try to come up with edge cases.
This would allow you to do it in a single pass. Using hash sets is beneficial if there are many values to parse/check. You might also want to use a bloom filter in combination with hash sets to reduce lookups.
Initialize. Let A and B be two empty hash sets. Let c be zero.
Parse loop. Parse the next value v. If there are no more values the algorithm is done and the result is in c.
Back check. If v exists in A then increment c and jump back to 2.
Low match. If v - K > 0 then:
insert v - K into A
if v - K exists in B then increment c (and optionally remove v - K from B).
High match. If v + K < 1e9 then:
insert v + K into A
if v + K exists in B then increment c (and optionally remove v + K from B).
Remember. Insert v into B.
Jump back to 2.
// php solution for this k difference
function getEqualSumSubstring($l,$s) {
$s = str_replace(' ','',$s);
$l = str_replace(' ','',$l);
for($i=0;$i<strlen($s);$i++)
{
$array1[] = $s[$i];
}
for($i=0;$i<strlen($s);$i++)
{
$array2[] = $s[$i] + $l[1];
}
return count(array_intersect($array1,$array2));
}
echo getEqualSumSubstring("5 2","1 3 5 4 2");
Actually that's trivially to solve with a hashmap:
First put each number into a hashmap: dict((x, x) for x in numbers) in "pythony" pseudo code ;)
Now you just iterate through every number in the hashmap and check if number + K is in the hashmap. If yes, increase count by one.
The obvious improvement to the naive solution is to ONLY check for the higher (or lower) bound, otherwise you get the double results and have to divide by 2 afterwards - useless.
This is O(N) for creating the hashmap when reading the values in and O(N) when iterating through, i.e. O(N) and about 8loc in python (and it is correct, I just solved it ;-) )
Following Eric's answer, paste the implementation of Interscet method below, it is O(n):
private static IEnumerable<TSource> IntersectIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
Set<TSource> set = new Set<TSource>(comparer);
foreach (TSource current in second)
{
set.Add(current);
}
foreach (TSource current2 in first)
{
if (set.Remove(current2))
{
yield return current2;
}
}
yield break;
}
Can someone please explain it to me? I wrote a function to calculate the factorial of a number like this in C#:
public int factorial(int input)
{
if (input == 0 || input == 1)
return 1;
else
{
int temp = 1;
for (int i = 1; i <= input; i++)
temp = temp * i;
return temp;
}
}
But I found some C++ code (I don't really know any C++ btw) which finds a factorial using a recursive loop:
int factorial(int number) {
int temp;
if(number <= 1) return 1;
temp = number * factorial(number - 1);
return temp;
}
Can someone explain to me how it works? Thanks.
Well, it uses the fact that factorial(n) is n * factorial(n - 1) with a base case of n = 1.
So for example:
factorial(5) = 5 * factorial(4)
= 5 * 4 * factorial(3)
= 5 * 4 * 3 * factorial(2)
= 5 * 4 * 3 * 2 * factorial(1)
= 5 * 4 * 3 * 2 * 1
The implementation just uses this recursive definition.
Syntactically, the C++ code is identical to the same code written in C#. Don't let the language discrepancy catch you off guard! It actually looks like C to me, given that the variable is declared at the top of the function; that's not strictly necessary in either C++ or C#. I prefer to declare variables the first time I use them, combining the declaration and initialization in one single statement, but that's merely a stylistic preference that doesn't change the function of the code.
I'll try to explain this by adding comments to each line of the code snippet:
// Declare a function named "Factorial" that accepts a single integer parameter,
// and returns an integer value.
int Factorial(int number)
{
// Declare a temporary variable of type integer
int temp;
// This is a guard clause that returns from the function immediately
// if the value of the argument is less than or equal to 1.
// In that case, it simply returns a value of 1.
// (This is important to prevent the function from recursively calling itself
// forever, producing an infinite loop!)
if(number <= 1) return 1;
// Set the value of the temp variable equal to the value of the argument
// multiplied by a recursive call to the Factorial function
temp = number * Factorial(number - 1);
// Return the value of the temporary variable
return temp;
}
Recursive calls simply mean that the function calls itself from within the same function. This works because the factorial of n is equivalent to the following statement:
n! = n * (n-1)!
One great way to understand how code works is to add it to a test project, then single-step through the code using the debugger. Visual Studio has very rich support for this in C# applications. You can watch how the function recursively calls itself, watching each line execute in sequence, and even seeing the values of the variables change as operations are performed on them.
Lets analyze this line by line:
if(number <= 1) return 1;
temp = number * factorial(number - 1);
return temp;
Line 1: If the number is less than or equal to zero, we return 1. This is saying that 0! = 1 and 1! = 1
Lines 2 + 3: Otherwise we return number * factorial(number - 1). Lets look at this for 5! (here i use n! as a synonym for factorial(n) for brevity)
5!
5 * 4!
5 * 4 * 3!
5 * 4 * 3 * 2!
5 * 4 * 3 * 2 * 1!
5 * 4 * 3 * 3 * 1 // Here we don't have to expand 1! in the same way because of the condition
So the whole thing expands out. Its just using the property that
n! = n * (n - 1) * ... * 2 * 1 = n * (n - 1)!
Warning: The recursive code, as always, will suffer from a stack overflow and increased memory usage as compared to an iterative (or tail-recursive-optimized) version, so use at your own risk.
A recursive function is a function that calls itself in its body. For it be bounded, and eventually return a value, two things must happen:
It has to have a base case where it doesn't call itself again, returning a known value. This base case stops the recursion. For the factorial function, this value is 1 when the input is 0.
Its recursive applications must converge to the base case. For factorial, the recursive application calls the function with the input subtracted by 1, which will eventually converge to the base case.
A simpler way to look at this function is this (only valid for positive input):
int factorial(int input) {
return input == 0 ? 1 : input * factorial(input - 1);
}
Recursive function are function calling from the same function
eg:
Test()
{
i++;
Test();
cout<<i;
}
look at the code it will call the function again and again
Problem with recursion it will work infinitely so want to stop it by a particular condition
some change in above code now look
int i=0;
Test()
{
if(i==10) return;
i++;
Test();
cout<<i;
}
output will be 10 printed 10 times, here this line cout<<i; will execute after return
I'm trying to refactor this algorithm to make it faster. What would be the first refactoring here for speed?
public int GetHowManyFactors(int numberToCheck)
{
// we know 1 is a factor and the numberToCheck
int factorCount = 2;
// start from 2 as we know 1 is a factor, and less than as numberToCheck is a factor
for (int i = 2; i < numberToCheck; i++)
{
if (numberToCheck % i == 0)
factorCount++;
}
return factorCount;
}
The first optimization you could make is that you only need to check up to the square root of the number. This is because factors come in pairs where one is less than the square root and the other is greater.
One exception to this is if n is an exact square then its square root is a factor of n but not part of a pair.
For example if your number is 30 the factors are in these pairs:
1 x 30
2 x 15
3 x 10
5 x 6
So you don't need to check any numbers higher than 5 because all the other factors can already be deduced to exist once you find the corresponding small factor in the pair.
Here is one way to do it in C#:
public int GetFactorCount(int numberToCheck)
{
int factorCount = 0;
int sqrt = (int)Math.Ceiling(Math.Sqrt(numberToCheck));
// Start from 1 as we want our method to also work when numberToCheck is 0 or 1.
for (int i = 1; i < sqrt; i++)
{
if (numberToCheck % i == 0)
{
factorCount += 2; // We found a pair of factors.
}
}
// Check if our number is an exact square.
if (sqrt * sqrt == numberToCheck)
{
factorCount++;
}
return factorCount;
}
There are other approaches you could use that are faster but you might find that this is already fast enough for your needs, especially if you only need it to work with 32-bit integers.
Reducing the bound of how high you have to go as you could knowingly stop at the square root of the number, though this does carry the caution of picking out squares that would have the odd number of factors, but it does help reduce how often the loop has to be executed.
Looks like there is a lengthy discussion about this exact topic here: Algorithm to calculate the number of divisors of a given number
Hope this helps
The first thing to notice is that it suffices to find all of the prime factors. Once you have these it's easy to find the number of total divisors: for each prime, add 1 to the number of times it appears and multiply these together. So for 12 = 2 * 2 * 3 you have (2 + 1) * (1 + 1) = 3 * 2 = 6 factors.
The next thing follows from the first: when you find a factor, divide it out so that the resulting number is smaller. When you combine this with the fact that you need only check to the square root of the current number this is a huge improvement. For example, consider N = 10714293844487412. Naively it would take N steps. Checking up to its square root takes sqrt(N) or about 100 million steps. But since the factors 2, 2, 3, and 953 are discovered early on you actually only need to check to one million -- a 100x improvement!
Another improvement: you don't need to check every number to see if it divides your number, just the primes. If it's more convenient you can use 2 and the odd numbers, or 2, 3, and the numbers 6n-1 and 6n+1 (a basic wheel sieve).
Here's another nice improvement. If you can quickly determine whether a number is prime, you can reduce the need for division even further. Suppose, after removing small factors, you have 120528291333090808192969. Even checking up to its square root will take a long time -- 300 billion steps. But a Miller-Rabin test (very fast -- maybe 10 to 20 nanoseconds) will show that this number is composite. How does this help? It means that if you check up to its cube root and find no factors, then there are exactly two primes left. If the number is a square, its factors are prime; if the number is not a square, the numbers are distinct primes. This means you can multiply your 'running total' by 3 or 4, respectively, to get the final answer -- even without knowing the factors! This can make more of a difference than you'd guess: the number of steps needed drops from 300 billion to just 50 million, a 6000-fold improvement!
The only trouble with the above is that Miller-Rabin can only prove that numbers are composite; if it's given a prime it can't prove that the number is prime. In that case you may wish to write a primality-proving function to spare yourself the effort of factoring to the square root of the number. (Alternately, you could just do a few more Miller-Rabin tests, if you would be satisfied with high confidence that your answer is correct rather than a proof that it is. If a number passes 15 tests then it's composite with probability less than 1 in a billion.)
You can limit the upper limit of your FOR loop to numberToCheck / 2
Start your loop counter at 2 (if your number is even) or 3 (for odd values). This should allow you to check every other number dropping your loop count by another 50%.
public int GetHowManyFactors(int numberToCheck)
{
// we know 1 is a factor and the numberToCheck
int factorCount = 2;
int i = 2 + ( numberToCheck % 2 ); //start at 2 (or 3 if numberToCheck is odd)
for( ; i < numberToCheck / 2; i+=2)
{
if (numberToCheck % i == 0)
factorCount++;
}
return factorCount;
}
Well if you are going to use this function a lot you can use modified algorithm of Eratosthenes http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes and store answars for a interval 1 to Max in array. It will run IntializeArray() once and after it will return answers in 0(1).
const int Max =1000000;
int arr [] = new int [Max+1];
public void InitializeArray()
{
for(int i=1;i<=Max;++i)
arr[i]=1;//1 is factor for everyone
for(int i=2;i<=Max;++i)
for(int j=i;i<=Max;i+=j)
++arr[j];
}
public int GetHowManyFactors(int numberToCheck)
{
return arr[numberToCheck];
}
But if you are not going to use this function a lot I think best solution is to check unitll square root.
Note: I have corrected my code!
An easy to implement algorithm that will bring you much farther than trial division is Pollard Rho
Here is a Java implementation, that should be easy to adapt to C#: http://www.cs.princeton.edu/introcs/78crypto/PollardRho.java.html
https://codility.com/demo/results/demoAAW2WH-MGF/
public int solution(int n) {
var counter = 0;
if (n == 1) return 1;
counter = 2; //1 and itself
int sqrtPoint = (Int32)(Math.Truncate(Math.Sqrt(n)));
for (int i = 2; i <= sqrtPoint; i++)
{
if (n % i == 0)
{
counter += 2; // We found a pair of factors.
}
}
// Check if our number is an exact square.
if (sqrtPoint * sqrtPoint == n)
{
counter -=1;
}
return counter;
}
Codility Python 100 %
Here is solution in python with little explanation-
def solution(N):
"""
Problem Statement can be found here-
https://app.codility.com/demo/results/trainingJNNRF6-VG4/
Codility 100%
Idea is count decedent factor in single travers. ie. if 24 is divisible by 4 then it is also divisible by 8
Traverse only up to square root of number ie. in case of 24, 4*4 < 24 but 5*5!<24 so loop through only i*i<N
"""
print(N)
count = 0
i = 1
while i * i <= N:
if N % i == 0:
print()
print("Divisible by " + str(i))
if i * i == N:
count += 1
print("Count increase by one " + str(count))
else:
count += 2
print("Also divisible by " + str(int(N / i)))
print("Count increase by two count " + str(count))
i += 1
return count
Example by run-
if __name__ == '__main__':
# result = solution(24)
# result = solution(35)
result = solution(1)
print("")
print("Solution " + str(result))
"""
Example1-
24
Divisible by 1
Also divisible by 24
Count increase by two count 2
Divisible by 2
Also divisible by 12
Count increase by two count 4
Divisible by 3
Also divisible by 8
Count increase by two count 6
Divisible by 4
Also divisible by 6
Count increase by two count 8
Solution 8
Example2-
35
Divisible by 1
Also divisible by 35
Count increase by two count 2
Divisible by 5
Also divisible by 7
Count increase by two count 4
Solution 4
Example3-
1
Divisible by 1
Count increase by one 1
Solution 1
"""
Github link
I got pretty good results with complexity of O(sqrt(N)).
if (N == 1) return 1;
int divisors = 0;
int max = N;
for (int div = 1; div < max; div++) {
if (N % div == 0) {
divisors++;
if (div != N/div) {
divisors++;
}
}
if (N/div < max) {
max = N/div;
}
}
return divisors;
Python Implementation
Score 100% https://app.codility.com/demo/results/trainingJ78AK2-DZ5/
import math;
def solution(N):
# write your code in Python 3.6
NumberFactor=2; #one and the number itself
if(N==1):
return 1;
if(N==2):
return 2;
squareN=int(math.sqrt(N)) +1;
#print(squareN)
for elem in range (2,squareN):
if(N%elem==0):
NumberFactor+=2;
if( (squareN-1) * (squareN-1) ==N):
NumberFactor-=1;
return NumberFactor