Prime decomposition
From Rosetta Code
Programming Task
This is a programming task. It lays out a problem which Rosetta Code users are encouraged to solve, using languages they know.
Write a function which returns an array or collection which contains the prime decomposition of a given number, n, greater than 1. If your language does not have an isPrime-like function available, you may assume that you have a function which determines whether a number is prime (note its name before your code).
If you would like to test code from this task, you may use code from trial division or the Sieve of Eratosthenes.
Note: The program must not be limited by the word size of your computer or some other artificial limit; it should work for any number regardless of size (ignoring the physical limits of RAM etc).
Contents |
[edit] Ada
with Ada.Text_IO; use Ada.Text_IO; procedure Test_Prime is generic type Number is private; Zero : Number; One : Number; Two : Number; with function Image (X : Number) return String is <>; with function "+" (X, Y : Number) return Number is <>; with function "/" (X, Y : Number) return Number is <>; with function "mod" (X, Y : Number) return Number is <>; with function ">=" (X, Y : Number) return Boolean is <>; package Prime_Numbers is type Number_List is array (Positive range <>) of Number; function Decompose (N : Number) return Number_List; procedure Put (List : Number_List); end Prime_Numbers; package body Prime_Numbers is function Decompose (N : Number) return Number_List is Size : Natural := 0; M : Number := N; K : Number := Two; begin -- Estimation of the result length from above while M >= Two loop M := (M + One) / Two; Size := Size + 1; end loop; M := N; -- Filling the result with prime numbers declare Result : Number_List (1..Size); Index : Positive := 1; begin while N >= K loop -- Divisors loop while Zero = (M mod K) loop -- While divides Result (Index) := K; Index := Index + 1; M := M / K; end loop; K := K + One; end loop; return Result (1..Index - 1); end; end Decompose; procedure Put (List : Number_List) is begin for Index in List'Range loop Put (Image (List (Index))); end loop; end Put; end Prime_Numbers; package Integer_Numbers is new Prime_Numbers (Natural, 0, 1, 2, Positive'Image); use Integer_Numbers; begin Put (Decompose (12)); end Test_Prime;
The solution is generic. The package is instantiated by a type that supports necessary operations +, /, mod, >=. The constants 0, 1, 2 are parameters too, because the type might have no literals. The package also provides a procedure to output an array of prime numbers and a function to convert a number to string (as a parameter). The function Decompose first estimates the maximal result length as log2 of the argument. Then it allocates the result and starts to enumerate divisors. It does not care to check if the divisors are prime, because non-prime divisors will be automatically excluded. In the example provided, the package is instantiated with plain integer type. Sample output:
2 2 3
[edit] C
Library: GMP
#include <stdio.h>
#include <stdlib.h>
#include <GMP/gmp.h>
void decompose(mpz_t n) {
int i;
mpz_t tmp, d;
i = 0;
mpz_init(tmp);
mpz_init(d);
while(mpz_cmp_si(n, 1)) {
mpz_set_ui(d, 1);
do {
mpz_add_ui(tmp, d, 1);
mpz_swap(tmp, d);
} while(!mpz_divisible_p(n, d));
mpz_divexact(tmp, n, d);
mpz_swap(tmp, n);
gmp_printf("%s%Zd", i++?" * ":"", d);
}
gmp_printf("\n");
}
int main(int argc, char ** argv) {
mpz_t n;
if(argc != 2) {
puts("Pass a parameter");
return EXIT_SUCCESS;
}
mpz_init_set_str(n, argv[1], 10);
decompose(n);
mpz_clear(n);
return EXIT_SUCCESS;
}
[edit] C++
Works with: g++ version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
Library: GMP
#include <iostream> #include <gmpxx.h> // This function template works for any type representing integers or // nonnegative integers, and has the standard operator overloads for // arithmetic and comparison operators, as well as explicit conversion // from int. // // OutputIterator must be an output iterator with value_type Integer. // It receives the prime factors. template<typename Integer, typename OutputIterator> void decompose(Integer n, OutputIterator out) { Integer i(2); while (n != 1) { while (n % i == Integer(0)) { *out++ = i; n /= i; } ++i; } } // this is an output iterator similar to std::ostream_iterator, except // that it outputs the separation string *before* the value, but not // before the first value (i.e. it produces an infix notation). template<typename T> class infix_ostream_iterator: public std::iterator<T, std::output_iterator_tag> { class Proxy; friend class Proxy; class Proxy { public: Proxy(infix_ostream_iterator& iter): iterator(iter) {} Proxy& operator=(T const& value) { if (!iterator.first) { iterator.stream << iterator.infix; } iterator.stream << value; } private: infix_ostream_iterator& iterator; }; public: infix_ostream_iterator(std::ostream& os, char const* inf): stream(os), first(true), infix(inf) { } infix_ostream_iterator& operator++() { first = false; return *this; } infix_ostream_iterator operator++(int) { infix_ostream_iterator prev(*this); ++*this; return prev; } Proxy operator*() { return Proxy(*this); } private: std::ostream& stream; bool first; char const* infix; }; int main() { std::cout << "please enter a positive number: "; mpz_class number; std::cin >> number; if (number <= 0) std::cout << "this number is not positive!\n;"; else { std::cout << "decomposition: "; decompose(number, infix_ostream_iterator<mpz_class>(std::cout, " * ")); std::cout << "\n"; } }
[edit] Common Lisp
(defun prime-decomposition (n)
(when (> n 1)
(loop for d from 2 upto n
until (zerop (mod n d))
finally (return (cons d (prime-decomposition (truncate n d)))))))
[edit] Forth
: decomp ( n -- )
2
begin 2dup dup * >=
while 2dup /mod swap
if drop 1+ 1 or \ next odd number
else -rot nip dup .
then
repeat
drop . ;
[edit] Haskell
primes = sieve [2..]
where
sieve (p:xs) = p : sieve [x|x <- xs, x `mod` p > 0]
factorize n pps@(p:ps) = case n `divMod` p of
(0,1) -> []
(remainder,0) -> p : factorize remainder pps
_ -> factorize n ps
[edit] J
q:
Example use:
q: 3684 2 2 3 307 _1+2^128x 340282366920938463463374607431768211455 q: _1+2^128x 3 5 17 257 641 65537 274177 6700417 67280421310721 */ q: _1+2^128x 340282366920938463463374607431768211455
[edit] Java
Works with: Java version 1.5+
This is a version for arbitrary-precision integers which assumes the existence of a function with the signature:
public boolean prime(BigInteger i);
You will need to import java.util.List, java.util.LinkedList, and java.math.BigInteger.
public static List<BigInteger> primeFactorBig(BigInteger a){ List<BigInteger> ans = new LinkedList<BigInteger>(); //loop until we test the number itself or the number is 1 for (BigInteger i = BigInteger.valueOf(2); i.compareTo(a) <= 0 && !a.equals(BigInteger.ONE); i = i.add(BigInteger.ONE)){ while (a.remainder(i).equals(BigInteger.ZERO) && prime(i)) { //if we have a prime factor ans.add(i); //put it in the list a = a.divide(i); //factor it out of the number } } return ans; }
[edit] JavaScript
This code uses the BigInteger Library jsbn and jsbn2
http://xenon.stanford.edu/~tjw/jsbn/jsbn.js
http://xenon.stanford.edu/~tjw/jsbn/jsbn2.js
function run_factorize(input, output) {
var n = new BigInteger(input.value, 10);
var prod = false;
var two = new BigInteger("2", 10);
var divisor = new BigInteger("3", 10);
if(n.compareTo(two) < 0) { return; }
output.value = "";
while(true) {
var qr = n.divideAndRemainder(two);
if(qr[1].compareTo(BigInteger.ZERO) == 0) {
if(prod) { output.value += "*"; } else { prod = true; }
output.value += "2";
n = qr[0];
}
else { break; }
}
while(n.compareTo(BigInteger.ONE) != 0) {
var qr = n.divideAndRemainder(divisor);
if(qr[1].compareTo(BigInteger.ZERO) == 0) {
if(prod) { output.value += "*"; } else { prod = true; }
output.value += divisor;
n = qr[0];
}
else { divisor = divisor.add(two); }
}
}
[edit] Logo
to decomp :p :n if :p*:p > :n [output (list :n)] if less? 0 modulo :n :p [output decomp :p+1 :n] output fput :p decomp :p :n/:p end to decompose :n output decomp 2 :n end
[edit] OCaml
open Big_int;; let prime_decomposition x = let rec inner c p = if lt_big_int p (square_big_int c) then [p] else if eq_big_int (mod_big_int p c) zero_big_int then c :: inner c (div_big_int p c) else inner (succ_big_int c) p in inner (succ_big_int (succ_big_int zero_big_int)) x;;
[edit] Python
import sys, time def primes(): yield 2 n = 3 while n < sys.maxint - 2: yield n n += 2 while n < sys.maxint - 2 and len(zip(range(2),decompose(n))) > 1: n += 2 def decompose(n): for p in primes(): if p*p > n: break while n % p == 0: yield p n /=p if n > 1: yield n # Example: calculate factors of Mersenne numbers to M59 # for m in xrange(1,60): if len(list(decompose(m))) != 1: continue p = 2 ** m - 1 print "2**%d-1 = %d, with factors:"%(m, p), start = time.time() for factor in decompose(p): print factor, sys.stdout.flush() print "=> %.2fs"%(time.time()-start)
Output:
2**2-1 = 3, with factors: 3 => 0.00s 2**3-1 = 7, with factors: 7 => 0.00s 2**5-1 = 31, with factors: 31 => 0.00s 2**7-1 = 127, with factors: 127 => 0.00s 2**11-1 = 2047, with factors: 23 89 => 0.00s 2**13-1 = 8191, with factors: 8191 => 0.00s 2**17-1 = 131071, with factors: 131071 => 0.02s 2**19-1 = 524287, with factors: 524287 => 0.05s 2**23-1 = 8388607, with factors: 47 178481 => 0.02s 2**29-1 = 536870911, with factors: 233 1103 2089 => 0.09s 2**31-1 = 2147483647, with factors: 2147483647 => 33.57s 2**37-1 = 137438953471, with factors: 223 616318177 => 12.12s 2**41-1 = 2199023255551, with factors: 13367 164511353 => 4.50s 2**43-1 = 8796093022207, with factors: 431 9719 2099863 => 2.71s 2**47-1 = 140737488355327, with factors: 2351 4513 13264529 => 0.79s 2**53-1 = 9007199254740991, with factors: 6361 69431 20394401 => 65.28s 2**59-1 = 576460752303423487, with factors: 179951 3203431780337 => 14324.83s
[edit] Smalltalk
Integer extend [
primesDo: aBlock [
| div next rest |
div := 2. next := 3.
rest := self.
[ [ rest \\ div == 0 ]
whileTrue: [
aBlock value: div.
rest := rest // div ].
rest = 1] whileFalse: [
div := next. next := next + 2 ]
]
]
123456 primesDo: [ :each | each printNl ]
[edit] Scheme
(define (prime-decomposition x)
(let inner ((c 2) (p x))
(if (> (* c c) p)
(list p)
(if (zero? (remainder p c))
(cons c (inner c (quotient p c)))
(inner (+ c 1) p)))))
[edit] V
like in scheme (using variables)
[prime-decomposition
[inner [c p] let
[c c * p >]
[p unit]
[ [p c % zero?]
[c c p c / inner cons]
[c 1 + p inner]
ifte]
ifte].
2 swap inner].
(mostly) the same thing using stack (with out variables)
[prime-decomposition
[inner
[dup * <]
[pop unit]
[ [% zero?]
[ [p c : [c p c / c]] view i inner cons]
[succ inner]
ifte]
ifte].
2 inner].
Using it
|1221 prime-decomposition puts =[3 11 37]
Categories: Programming Tasks | Prime Numbers | Arbitrary precision | Ada | C | GMP | C++ | Common Lisp | Forth | Haskell | J | Java | JavaScript | Logo | OCaml | Python | Smalltalk | Scheme | V

