diff --git a/src/Algorithms.rs b/src/Algorithms.rs index 681fa79..112a1bf 100644 --- a/src/Algorithms.rs +++ b/src/Algorithms.rs @@ -1,6 +1,7 @@ extern crate num; +// pub fn getAllFib(goalNumber: u64) -> Vec{ let mut fibNums = Vec::new(); //A list to save the Fibonacci numbers //If the number is <= 0 return an empty list @@ -21,6 +22,7 @@ pub fn getAllFib(goalNumber: u64) -> Vec{ return fibNums; } +// pub fn getAllFibBig(goalNumber: num::BigInt) -> Vec{ let mut fibNums = Vec::new(); //A list to save the Fibonacci numbers in //If the number is <= 0 return an empty list @@ -39,3 +41,169 @@ pub fn getAllFibBig(goalNumber: num::BigInt) -> Vec{ fibNums.remove(fibNums.len() - 1); return fibNums; } + +//Ths function returns all factors of goalNumber +pub fn getFactors(mut goalNumber: i64) -> Vec{ + //You need to get all the primes that could be factors of this number so you can test them + let topPossiblePrime = (goalNumber as f64).sqrt().ceil() as i64; + let primes = getPrimes(topPossiblePrime); + let mut factors = Vec::::new(); + + //You need to step through each prime and see if it is a factor in the number + let mut cnt = 0; + while(cnt < primes.len()){ + //If the prime is a factor you need to add it to the factor list + if((goalNumber % primes[cnt]) == 0){ + factors.push(primes[cnt]); + goalNumber /= primes[cnt]; + } + //Otherwise advance the location in primes you are looking at + //By not advancing if the prime is a factor you allow for multiple of the same prime number as a factor + else{ + cnt += 1; + } + } + + //If you didn't get any factors the number itself must be a prime + if(factors.len() == 0){ + factors.push(goalNumber); + goalNumber /= goalNumber; + } + + //TODO: If for some reason the goalNumber is not 1 throw an error + if(goalNumber != 1){ + } + + //Return the list of factors + return factors; +} +pub fn getFactorsBig(mut goalNumber: num::BigInt) -> Vec{ + //You need to get all the rpimes that could be factors of this number so you can test them + let topPossiblePrime = goalNumber.sqrt(); + let primes = getPrimesBig(topPossiblePrime); + let mut factors = Vec::::new(); + + //You need to step through each prime and see if it is a factor in the number + let mut cnt = 0; + while(cnt < primes.len()){ + //If the prime is a factor you need to add it to the factor list + if((&goalNumber % &primes[cnt]) == num::BigInt::from(0)){ + factors.push(num::BigInt::new(primes[cnt].sign(), primes[cnt].to_u32_digits().1)); + goalNumber /= &primes[cnt]; + } + //Otherwise advance the location in primes you are looking at + //By not advancing if the prime is a factor you allow for multiple of the same prime number as a factor + else{ + cnt += 1; + } + } + + //If you didn't get any factors the number itself must be a prime + if(factors.len() == 0){ + factors.push(goalNumber); + goalNumber = num::BigInt::from(1); + } + + //TODO: If for some reason the goalNumber is not 1 throw an error + if(goalNumber != num::BigInt::from(1)){ + } + + //Return the list of factors + return factors; +} + +//This function returns a list with all the prime numbers <= goalNumber +pub fn getPrimes(goalNumber: i64) -> Vec{ + let mut primes = Vec::::new(); + let mut foundFactor = false; + + //If the number is 1, 0, or negative return an empty list + if(goalNumber <= 1){ + return primes; + } + //Otherwise the number is at least 2, so 2 should be added to the list + else{ + primes.push(2); + } + + //We can now start at 3 and skip all even number, because they cannot be prime + for possiblePrime in (3..=goalNumber).step_by(2){ + //Check all current primes, up to sqrt(possiblePrime), to see if there is a divisor + let topPossibleFactor = (possiblePrime as f64).sqrt().ceil(); + //We can safely assume that there will be at least 1 element in the primes list because of 2 being added before this + let mut primesCnt = 0; + while(primes[primesCnt] <= topPossibleFactor as i64){ + if((possiblePrime % primes[primesCnt]) == 0){ + foundFactor = true; + break; + } + else{ + primesCnt += 1; + } + //Check if the index has gone out of range + if(primesCnt >= primes.len()){ + break; + } + } + + //If you didn't find a factor then the current number must be prime + if(!foundFactor){ + primes.push(possiblePrime); + } + else{ + foundFactor = false; + } + } + + //Sort the list before returning it + primes.sort(); + return primes; +} +pub fn getPrimesBig(goalNumber: num::BigInt) -> Vec{ + let mut primes = Vec::::new(); + let mut foundFactor = false; + + //If the number is 1, 0, or negative return an empty list + if(goalNumber <= num::BigInt::from(0)){ + return primes; + } + //Otherwise the number is at least 2, so 2 should be added to the list + else{ + primes.push(num::BigInt::from(2)); + } + + //We can now start at 3 and skip all even number, because they cannot be prime + let mut possiblePrime = num::BigInt::from(3); + while(possiblePrime <= goalNumber){ + //Check for all currentprimes, up to sqrt(possiblePrime), to see if there is a divisor + let topPossibleFactor = possiblePrime.sqrt() + num::BigInt::from(1); + //We can safely assume that there will be at least 2 element in the primes list because of 2 being added before this + let mut primesCnt = 0; + while(primes[primesCnt] <= topPossibleFactor){ + if((&possiblePrime % &primes[primesCnt]) == num::BigInt::from(0)){ + foundFactor = true; + break; + } + else{ + primesCnt += 1; + } + //Check if the index has gone out of range + if(primesCnt >= primes.len()){ + break; + } + } + + //If you didn't find a factor then the current number must be prime + if(!foundFactor){ + primes.push(num::BigInt::new(possiblePrime.sign(), possiblePrime.to_u32_digits().1)); + } + else{ + foundFactor = false; + } + possiblePrime += num::BigInt::from(2); + } + + //Sort the list before returning it + primes.sort(); + return primes; +} diff --git a/src/lib.rs b/src/lib.rs index 386aed3..6cfdfb7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,4 +68,40 @@ mod AlgorithmsTests{ let answerBig = super::Algorithms::getAllFibBig(highestNumberBig); assert_eq!(correctAnswerBig, answerBig); } + #[test] + fn testGetPrimes(){ + //Test1 + let mut correctAnswer1 = Vec::::new(); + correctAnswer1.extend_from_slice(&[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]); + let topNum1 = 100; + let answer1 = super::Algorithms::getPrimes(topNum1); + assert_eq!(correctAnswer1, answer1); + //Test2 + let mut correctAnswer2 = Vec::::new(); + correctAnswer2.extend_from_slice(&[num::BigInt::from(2), num::BigInt::from(3), num::BigInt::from(5), num::BigInt::from(7), num::BigInt::from(11), num::BigInt::from(13), num::BigInt::from(17), num::BigInt::from(19), num::BigInt::from(23), num::BigInt::from(29), num::BigInt::from(31), num::BigInt::from(37), num::BigInt::from(41), num::BigInt::from(43), num::BigInt::from(47), num::BigInt::from(53), num::BigInt::from(59), num::BigInt::from(61), num::BigInt::from(67), num::BigInt::from(71), num::BigInt::from(73), num::BigInt::from(79), num::BigInt::from(83), num::BigInt::from(89), num::BigInt::from(97)]); + let topNum2 = num::BigInt::from(100); + let answer2 = super::Algorithms::getPrimesBig(topNum2); + assert_eq!(correctAnswer2, answer2); + } + #[test] + fn testGetFactors(){ + //Test1 + let mut correctAnswer1 = Vec::::new(); + correctAnswer1.extend_from_slice(&[2, 2, 5, 5]); + let number1 = 100; + let answer1 = super::Algorithms::getFactors(number1); + assert_eq!(correctAnswer1, answer1); + //Test2 + let mut correctAnswer2 = Vec::::new(); + correctAnswer2.extend_from_slice(&[2, 7, 7]); + let number2 = 98; + let answer2 = super::Algorithms::getFactors(number2); + assert_eq!(correctAnswer2, answer2); + //Test3 + let mut correctAnswer3 = Vec::::new(); + correctAnswer3.extend_from_slice(&[num::BigInt::from(2), num::BigInt::from(2), num::BigInt::from(5), num::BigInt::from(5)]); + let number3 = num::BigInt::from(100); + let answer3 = super::Algorithms::getFactorsBig(number3); + assert_eq!(correctAnswer3, answer3); + } }