Partition an integer x into n primes
You are encouraged to solve this task according to the task description, using any language you may know.
- Task
Partition a positive integer X into N primes.
Or, to put it in another way:
Find N unique primes such that they add up to X.
Show in the output section the (sum) X and the N primes in ascending order and separated by plus (+) signs:
partition 99809 with 1 prime. partition 18 with 2 primes. partition 19 with 3 primes. partition 20 with 4 primes. partition 2017 with 24 primes. partition 22699 with 1, 2, 3, and 4 primes. partition 40355 with 3 primes.
The output could/should be shown in a format such as:
Partitioned 19 with 3 primes: 3+5+11
- Use any spacing that may be appropriate for the display.
- You need not validate the input(s).
- Use the lowest primes possible; use 18 = 5+13, not: 18 = 7+11.
- You only need to show one solution.
This task is similar to factoring an integer.
- Related tasks
- count in factors
- prime decomposition
- factors of an integer
- Sieve of Eratosthenes
- primality by trial division
- factors of a Mersenne number
- trial factoring of a Mersenne number
- sequence of primes by Trial Division
D
<lang D>import std.array : array; import std.range : take; import std.stdio;
bool isPrime(int n) {
if (n < 2) return false; if (n % 2 == 0) return n == 2; if (n % 3 == 0) return n == 3;
int d = 5; while (d*d <= n) { if (n % d == 0) return false; d += 2; if (n % d == 0) return false; d += 4; } return true;
}
auto generatePrimes() {
struct Seq { int p = 2;
bool empty() { return p < 0; }
int front() { return p; }
void popFront() { if (p==2) { p++; } else { p += 2; while (!empty && !p.isPrime) { p += 2; } } } }
return Seq();
}
bool findCombo(int k, int x, int m, int n, int[] combo) {
import std.algorithm : map, sum; auto getPrime = function int(int idx) => primes[idx];
if (k >= m) { if (combo.map!getPrime.sum == x) { auto word = (m > 1) ? "primes" : "prime"; writef("Partitioned %5d with %2d %s ", x, m, word); foreach (i; 0..m) { write(primes[combo[i]]); if (i < m-1) { write('+'); } else { writeln(); } } return true; } } else { foreach (j; 0..n) { if (k==0 || j>combo[k-1]) { combo[k] = j; bool foundCombo = findCombo(k+1, x, m, n, combo); if (foundCombo) { return true; } } } } return false;
}
void partition(int x, int m) {
import std.exception : enforce; import std.algorithm : filter; enforce(x>=2 && m>=1 && m<x);
auto lessThan = delegate int(int a) => a<=x; auto filteredPrimes = primes.filter!lessThan.array; auto n = filteredPrimes.length; enforce(n>=m, "Not enough primes");
int[] combo = new int[m]; if (!findCombo(0, x, m, n, combo)) { auto word = (m > 1) ? "primes" : "prime"; writefln("Partitioned %5d with %2d %s: (not possible)", x, m, word); }
}
int[] primes; void main() {
// generate first 50,000 and call it good primes = generatePrimes().take(50_000).array;
auto a = [ [99809, 1], [ 18, 2], [ 19, 3], [ 20, 4], [ 2017, 24], [22699, 1], [22699, 2], [22699, 3], [22699, 4], [40355, 3] ];
foreach(p; a) { partition(p[0], p[1]); }
}</lang>
- Output:
Partitioned 99809 with 1 prime 99809 Partitioned 18 with 2 primes 5+13 Partitioned 19 with 3 primes 3+5+11 Partitioned 20 with 4 primes: (not possible) Partitioned 2017 with 24 primes 2+3+5+7+11+13+17+19+23+29+31+37+41+43+47+53+59+61+67+71+73+79+97+1129 Partitioned 22699 with 1 prime 22699 Partitioned 22699 with 2 primes 2+22697 Partitioned 22699 with 3 primes 3+5+22691 Partitioned 22699 with 4 primes 2+3+43+22651 Partitioned 40355 with 3 primes 3+139+40213
F#
This task uses Extensible Prime Generator (F#) <lang fsharp> // Partition an integer as the sum of n primes. Nigel Galloway: November 27th., 2017 let rcTask n ng =
let rec fN i g e l = seq{ match i with |1 -> if isPrime g then yield Some (g::e) else yield None |_ -> yield! Seq.mapi (fun n a->fN (i-1) (g-a) (a::e) (Seq.skip (n+1) l)) (l|>Seq.takeWhile(fun n->(g-n)>n))|>Seq.concat} match fN n ng [] primes |> Seq.tryPick id with |Some n->printfn "%d is the sum of %A" ng n |_ ->printfn "No Solution"
</lang>
- Output:
rcTask 1 99089 -> 99089 is the sum of [99089] rcTask 2 18 -> 18 is the sum of [13; 5] rcTask 3 19 -> 19 is the sum of [11; 5; 3] rcTask 4 20 -> No Solution rcTask 24 2017 -> 2017 is the sum of [1129; 97; 79; 73; 71; 67; 61; 59; 53; 47; 43; 41; 37; 31; 29; 23; 19; 17; 13; 11; 7; 5; 3; 2] rcTask 1 2269 -> 2269 is the sum of [2269] rcTask 2 2269 -> 2269 is the sum of [2267; 2] rcTask 3 2269 -> 2269 is the sum of [2243; 23; 3] rcTask 4 2269 -> 2269 is the sum of [2251; 13; 3; 2] rcTask 3 40355 -> 40355 is the sum of [40213; 139; 3]
Haskell
<lang haskell>{-# LANGUAGE TupleSections #-}
import Data.List (delete, intercalate)
-- PRIME PARTITIONS ---------------------------------------------------------- partition :: Int -> Int -> [Int] partition x n
| n <= 1 = [ x | last ps == x ] | otherwise = partition_ ps x n where ps = takeWhile (<= x) primes partition_ ps_ x 1 = [ x | x `elem` ps_ ] partition_ ps_ x n = let found = foldMap partitionsFound ps_ in nullOr found [] (head found) where partitionsFound p = let r = x - p rs = partition_ (delete p (takeWhile (<= r) ps_)) r (n - 1) in nullOr rs [] [p : rs]
-- TEST ---------------------------------------------------------------------- main :: IO () main =
mapM_ putStrLn $ (\(x, n) -> (intercalate " -> " [ justifyLeft 9 ' ' (show (x, n)) , let xs = partition x n in nullOr xs "(no solution)" (intercalate "+" (show <$> xs)) ])) <$> concat [ [(99809, 1), (18, 2), (19, 3), (20, 4), (2017, 24)] , (22699, ) <$> [1 .. 4] , [(40355, 3)] ]
-- GENERIC -------------------------------------------------------------------- justifyLeft :: Int -> Char -> String -> String justifyLeft n c s = take n (s ++ replicate n c)
nullOr
:: Foldable t1 => t1 a -> t -> t -> t
nullOr expression nullValue orValue =
if null expression then nullValue else orValue
primes :: [Int] primes =
2 : pruned [3 ..] (listUnion [ (p *) <$> [p ..] | p <- primes ]) where pruned :: [Int] -> [Int] -> [Int] pruned (x:xs) (y:ys) | x < y = x : pruned xs (y : ys) | x == y = pruned xs ys | x > y = pruned (x : xs) ys listUnion :: Int -> [Int] listUnion = foldr union [] where union (x:xs) ys = x : union_ xs ys union_ (x:xs) (y:ys) | x < y = x : union_ xs (y : ys) | x == y = x : union_ xs ys | x > y = y : union_ (x : xs) ys</lang>
- Output:
(99809,1) -> 99809 (18,2) -> 5+13 (19,3) -> 3+5+11 (20,4) -> (no solution) (2017,24) -> 2+3+5+7+11+13+17+19+23+29+31+37+41+43+47+53+59+61+67+71+73+79+97+1129 (22699,1) -> 22699 (22699,2) -> 2+22697 (22699,3) -> 3+5+22691 (22699,4) -> 2+3+43+22651 (40355,3) -> 3+139+40213
J
<lang j> load 'format/printf'
primes_up_to =: monad : 'p: i. _1 p: 1 + y' terms_as_text =: 3 & }. @: ; @: ((' + ' & , @: ":) each "0)
NB. Simple, short and clean J code naturally yields functional and
NB. parallel solutions. However I don't know of any way to easily
NB. make it lazy. Therefore, when the domain solution is huge, even
NB. though we only want the first solution found, time and space may
NB. become a constraint.
NB. In such a case we can fall back on explicit imperative control strutures,
NB. though this is clearly not where J shines.
as_terms_aux=:dyad define
acc=.x p=.>0{y ns=.>1{y sum=.>2{y
if. p=1 do. for_m. i. #ns do. r=. acc,m{ns if. sum=+/r do. r return. end. end. else. for_m. i. (#ns)-(p-1) do. r=. (acc,m{ns) as_terms_aux (p-1);((m+1)}.ns);sum if. #r do. r return. end. end. end.
0$0 NB. Empty result if nothing found
)
NB. A wrapper with a more pleasant call signature.
as_terms_from=:dyad define
sum=.>0{x p=.>1{x ns=.y (0$0) as_terms_aux p;y;sum
)
NB. Finds a partition of y primes, whose sum equals x NB. Try 19 in 3 for example. in =: dyad define
terms=. (x;y) as_terms_from primes_up_to x if. #terms do. 'As the sum of %d primes, %d = %s' printf y;x; terms_as_text terms else. 'Didnt find a way to express %d as a sum of %d different primes.' printf x;y end.
)
99809 in 1 18 in 2 19 in 3 20 in 4 2017 in 24 22699 in 1 22699 in 2 22699 in 3 22699 in 4 40355 in 3 </lang>
- Output:
As the sum of 1 primes, 99809 = 99809 As the sum of 2 primes, 18 = 5 + 13 As the sum of 3 primes, 19 = 3 + 5 + 11 Didn't find a way to express 20 as a sum of 4 different primes. As the sum of 24 primes, 2017 = 2 + 3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 + 29 + 31 + 37 + 41 + 43 + 47 + 53 + 59 + 61 + 67 + 71 + 73 + 79 + 97 + 1129 As the sum of 1 primes, 22699 = 22699 As the sum of 2 primes, 22699 = 2 + 22697 As the sum of 3 primes, 22699 = 3 + 5 + 22691 As the sum of 4 primes, 22699 = 2 + 3 + 43 + 22651 As the sum of 3 primes, 40355 = 3 + 139 + 40213
Julia
<lang julia> using Primes, Combinatorics
function prime_partition(num, parts)
if parts == 1 return isprime(num) ? [num]: [] else for com in combinations(primes(num), parts) if sum(com) == num return com end end end []
end
tests = [[ 18, 2], [ 19, 3], [ 20, 4], [99807, 1], [99809, 1],
[ 2017, 24],[22699, 1], [22699, 2], [22699, 3], [22699, 4] ,[40355, 3]]
for pair in tests
ans = prime_partition(pair[1], pair[2]) println("Partition of $(pair[1]) into $(pair[2]) prime piece", pair[2] == 1 ? ": " : "s: ", ans == [] ? "impossible." : join(ans, " + "))
end </lang>
- Output:
Partition of 18 into 2 prime pieces: 5 + 13 Partition of 19 into 3 prime pieces: 3 + 5 + 11 Partition of 20 into 4 prime pieces: impossible. Partition of 99807 into 1 prime piece: impossible. Partition of 99809 into 1 prime piece: 99809 Partition of 2017 into 24 prime pieces: 2 + 3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 + 29 + 31 + 37 + 41 + 43 + 47 + 53 + 59 + 61 + 67 + 71 + 73 + 79 + 97 + 1129 Partition of 22699 into 1 prime piece: 22699 Partition of 22699 into 2 prime pieces: 2 + 22697 Partition of 22699 into 3 prime pieces: 3 + 5 + 22691 Partition of 22699 into 4 prime pieces: 2 + 3 + 43 + 22651 Partition of 40355 into 3 prime pieces: 3 + 139 + 40213
Kotlin
<lang scala>// version 1.1.2
// compiled with flag -Xcoroutines=enable to suppress 'experimental' warning
import kotlin.coroutines.experimental.*
val primes = generatePrimes().take(50_000).toList() // generate first 50,000 say var foundCombo = false
fun isPrime(n: Int) : Boolean {
if (n < 2) return false if (n % 2 == 0) return n == 2 if (n % 3 == 0) return n == 3 var d : Int = 5 while (d * d <= n) { if (n % d == 0) return false d += 2 if (n % d == 0) return false d += 4 } return true
}
fun generatePrimes() =
buildSequence { yield(2) var p = 3 while (p <= Int.MAX_VALUE) { if (isPrime(p)) yield(p) p += 2 } }
fun findCombo(k: Int, x: Int, m: Int, n: Int, combo: IntArray) {
if (k >= m) { if (combo.sumBy { primes[it] } == x) { val s = if (m > 1) "s" else " " print("Partitioned ${"%5d".format(x)} with ${"%2d".format(m)} prime$s: ") for (i in 0 until m) { print(primes[combo[i]]) if (i < m - 1) print("+") else println() } foundCombo = true } } else { for (j in 0 until n) { if (k == 0 || j > combo[k - 1]) { combo[k] = j if (!foundCombo) findCombo(k + 1, x, m, n, combo) } } }
}
fun partition(x: Int, m: Int) {
require(x >= 2 && m >= 1 && m < x) val filteredPrimes = primes.filter { it <= x } val n = filteredPrimes.size if (n < m) throw IllegalArgumentException("Not enough primes") val combo = IntArray(m) foundCombo = false findCombo(0, x, m, n, combo) if (!foundCombo) { val s = if (m > 1) "s" else " " println("Partitioned ${"%5d".format(x)} with ${"%2d".format(m)} prime$s: (not possible)") }
}
fun main(args: Array<String>) {
val a = arrayOf( 99809 to 1, 18 to 2, 19 to 3, 20 to 4, 2017 to 24, 22699 to 1, 22699 to 2, 22699 to 3, 22699 to 4, 40355 to 3 ) for (p in a) partition(p.first, p.second)
}</lang>
- Output:
Partitioned 99809 with 1 prime : 99809 Partitioned 18 with 2 primes: 5+13 Partitioned 19 with 3 primes: 3+5+11 Partitioned 20 with 4 primes: (not possible) Partitioned 2017 with 24 primes: 2+3+5+7+11+13+17+19+23+29+31+37+41+43+47+53+59+61+67+71+73+79+97+1129 Partitioned 22699 with 1 prime : 22699 Partitioned 22699 with 2 primes: 2+22697 Partitioned 22699 with 3 primes: 3+5+22691 Partitioned 22699 with 4 primes: 2+3+43+22651 Partitioned 40355 with 3 primes: 3+139+40213
Perl
It is tempting to use the partition iterator which takes a "isprime" flag, but this task calls for unique values. Hence the combination iterator over an array of primes makes more sense.
<lang perl>use ntheory ":all";
sub prime_partition {
my($num, $parts) = @_; return is_prime($num) ? [$num] : undef if $parts == 1; my @p = @{primes($num)}; my $r; forcomb { lastfor, $r = [@p[@_]] if vecsum(@p[@_]) == $num; } @p, $parts; $r;
}
foreach my $test ([18,2], [19,3], [20,4], [99807,1], [99809,1], [2017,24], [22699,1], [22699,2], [22699,3], [22699,4], [40355,3]) {
my $partar = prime_partition(@$test); printf "Partition %5d into %2d prime piece%s %s\n", $test->[0], $test->[1], ($test->[1] == 1) ? ": " : "s:", defined($partar) ? join("+",@$partar) : "not possible";
}</lang>
- Output:
Partition 18 into 2 prime pieces: 5+13 Partition 19 into 3 prime pieces: 3+5+11 Partition 20 into 4 prime pieces: not possible Partition 99807 into 1 prime piece: not possible Partition 99809 into 1 prime piece: 99809 Partition 2017 into 24 prime pieces: 2+3+5+7+11+13+17+19+23+29+31+37+41+43+47+53+59+61+67+71+73+79+97+1129 Partition 22699 into 1 prime piece: 22699 Partition 22699 into 2 prime pieces: 2+22697 Partition 22699 into 3 prime pieces: 3+5+22691 Partition 22699 into 4 prime pieces: 2+3+43+22651 Partition 40355 into 3 prime pieces: 3+139+40213
Perl 6
<lang perl6>my @primes = 2, 3, 5, -> $p { ($p + 2, $p + 4 ... &is-prime).tail } ... *; # lazy infinite list of primes
multi partition ( Int $number, 1 ) { $number.is-prime ?? $number !! [] } # short circuit for '1' partition
multi partition ( Int $number, Int $parts where * > 0 = 2 ) {
my @these = @primes[ ^( @primes.first: * > $number, :k ) ]; for @these.combinations($parts) -> @this { return @this if @this.sum == $number } []
}
- TESTING
for 18,2, 19,3, 20,4, 99807,1, 99809,1, 2017,24, 22699,1, 22699,2, 22699,3, 22699,4, 40355,3
-> $number, $parts { say (sprintf "Partition %5d into %2d prime piece", $number, $parts), $parts == 1 ?? ': ' !! 's: ', (join '+', partition $number, $parts) || 'not possible'
}</lang>
- Output:
Partition 18 into 2 prime pieces: 5+13 Partition 19 into 3 prime pieces: 3+5+11 Partition 20 into 4 prime pieces: not possible Partition 99807 into 1 prime piece: not possible Partition 99809 into 1 prime piece: 99809 Partition 2017 into 24 prime pieces: 2+3+5+7+11+13+17+19+23+29+31+37+41+43+47+53+59+61+67+71+73+79+97+1129 Partition 22699 into 1 prime piece: 22699 Partition 22699 into 2 prime pieces: 2+22697 Partition 22699 into 3 prime pieces: 3+5+22691 Partition 22699 into 4 prime pieces: 2+3+43+22651 Partition 40355 into 3 prime pieces: 3+139+40213
Python
<lang Python> from itertools import combinations as cmb
def isP(n):
if n==2: return True if n%2==0: return False return all(n%x>0 for x in range(3, int(n**0.5)+1, 2))
def genP(n):
p = [2] p.extend([x for x in range(3, n+1, 2) if isP(x)]) return p
data = [(99809, 1), (18, 2), (19, 3), (20, 4), (2017, 24), (22699, 1), (22699, 2), (22699, 3), (22699, 4), (40355, 3)]
for n, cnt in data:
ci = iter(cmb(genP(n), cnt)) while True: try: c = next(ci) if sum(c)==n: print(n, ',', cnt , "->", '+'.join(str(s) for s in c)) break except: print(n, ',', cnt, " -> Not possible") break
</lang>
- Output:
99809 , 1 -> 99809 18 , 2 -> 5+13 19 , 3 -> 3+5+11 20 , 4 -> Not possible 2017 , 24 -> 2+3+5+7+11+13+17+19+23+29+31+37+41+43+47+53+59+61+67+71+73+79+97+1129 22699 , 1 -> 22699 22699 , 2 -> 2+22697 22699 , 3 -> 3+5+22691 22699 , 4 -> 2+3+43+22651 40355 , 3 -> 3+139+40213
Racket
<lang racket>#lang racket (require math/number-theory)
(define memoised-next-prime
(let ((m# (make-hash))) (λ (P) (hash-ref! m# P (λ () (next-prime P))))))
(define (partition-X-into-N-primes X N)
(define (partition-x-into-n-primes-starting-at-P x n P result) (cond ((= n x 0) result) ((or (= n 0) (= x 0) (> P x)) #f) (else (let ((P′ (memoised-next-prime P))) (or (partition-x-into-n-primes-starting-at-P (- x P) (- n 1) P′ (cons P result)) (partition-x-into-n-primes-starting-at-P x n P′ result)))))) (reverse (or (partition-x-into-n-primes-starting-at-P X N 2 null) (list 'no-solution))))
(define (report-partition X N)
(let ((result (partition-X-into-N-primes X N))) (printf "partition ~a\twith ~a\tprimes: ~a~%" X N (string-join (map ~a result) " + "))))
(module+ test
(report-partition 99809 1) (report-partition 18 2) (report-partition 19 3) (report-partition 20 4) (report-partition 2017 24) (report-partition 22699 1) (report-partition 22699 2) (report-partition 22699 3) (report-partition 22699 4) (report-partition 40355 3))</lang>
- Output:
partition 99809 with 1 primes: 99809 partition 18 with 2 primes: 5 + 13 partition 19 with 3 primes: 3 + 5 + 11 partition 20 with 4 primes: no-solution partition 2017 with 24 primes: 2 + 3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 + 29 + 31 + 37 + 41 + 43 + 47 + 53 + 59 + 61 + 67 + 71 + 73 + 79 + 97 + 1129 partition 22699 with 1 primes: 22699 partition 22699 with 2 primes: 2 + 22697 partition 22699 with 3 primes: 3 + 5 + 22691 partition 22699 with 4 primes: 2 + 3 + 43 + 22651 partition 40355 with 3 primes: 3 + 139 + 40213
REXX
Usage note: entering ranges of X and N numbers (arguments) from the command line:
- X-Y N-M ∙∙∙
which means: partition all integers (inclusive) from X ──► Y with N ──► M primes.
The to number (Y or M) can be omitted.
<lang rexx>/*REXX program partitions integer(s) (greater than unity) into N primes. */
parse arg what /*obtain an optional list from the C.L.*/
do until what== /*possibly process a series of integers*/ parse var what x n what; parse var x x '-' y /*get possible range and # partitions.*/ parse var n n '-' m /*get possible range and # partitions.*/ if x== | x=="," then x=19 /*Not specified? Then use the default.*/ if y== | y=="," then y=x /* " " " " " " */ if n== | n=="," then n= 3 /* " " " " " " */ if m== | m=="," then m=n /* " " " " " " */ call genP y /*generate Y number of primes. */ do g=x to y /*partition X ───► Y into partitions.*/ do q=n to m; call part; end /*q*/ /*partition G into Q primes. */ end /*g*/ end /*until*/
exit 0 /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ genP: arg high; @.1=2; @.2=3; #=2 /*get highest prime, assign some vars. */
do j=@.#+2 by 2 until @.#>high /*only find odd primes from here on. */ do k=2 while k*k<=j /*divide by some known low odd primes. */ if j // @.k==0 then iterate j /*Is J divisible by P? Then ¬ prime.*/ end /*k*/ /* [↓] a prime (J) has been found. */ #=#+1; @.#=j /*bump prime count; assign prime to @.*/ end /*j*/ return
/*──────────────────────────────────────────────────────────────────────────────────────*/ getP: procedure expose i. p. @.; parse arg z /*bump the prime in the partition list.*/
if i.z==0 then do; _=z-1; i.z=i._; end i.z=i.z+1; _=i.z; p.z=@._; return 0
/*──────────────────────────────────────────────────────────────────────────────────────*/ list: _=p.1; if $==g then do j=2 to q; _=_ p.j; end; else _= '__(not_possible)'
the= 'primes:'; if q==1 then the= 'prime: '; return the translate(_,"+ ",' _')
/*──────────────────────────────────────────────────────────────────────────────────────*/ part: i.=0; do j=1 for q; call getP j; end /*j*/
do !=0 by 0; $=0 /*!: a DO variable for LEAVE & ITERATE*/ do s=1 for q; $=$+p.s /* [↓] is sum of the primes too large?*/ if $>g then do; if s==1 then leave ! /*perform a quick exit?*/ do k=s to q; i.k=0; end /*k*/ do r=s-1 to q; call getP r; end /*r*/ iterate ! end end /*s*/ if $==g then leave /*is sum of the primes exactly right ? */ if $ <g then do; call getP q; iterate; end end /*!*/ /* [↑] Is sum too low? Bump a prime.*/ say 'partitioned' center(g,9) "into" center(q, 5) list() return</lang>
{{out|output|text= when using the input of: 99809 1 18 2 19 3 20 4 2017 24 22699 1-4 40355
partitioned 99809 into 1 prime: 99809 partitioned 18 into 2 primes: 5+13 partitioned 19 into 3 primes: 3+5+11 partitioned 20 into 4 primes: (not possible) partitioned 2017 into 24 primes: 2+3+5+7+11+13+17+19+23+29+31+37+41+43+47+53+59+61+67+71+73+79+97+1129 partitioned 22699 into 1 prime: 22699 partitioned 22699 into 2 primes: 2+22697 partitioned 22699 into 3 primes: 3+5+22691 partitioned 22699 into 4 primes: 2+3+43+22651 partitioned 40355 into 3 primes: 3+139+40213
Ring
<lang ring>
- Project : Partition an integer X into N primes
- Date : 2018/02/05
- Author : Gal Zsolt [~ CalmoSoft ~]
- Email : <calmosoft@gmail.com>
load "stdlib.ring" nr = 0 num = 0 list = list(10) items = newlist(pow(2,len(list))-1,10) while true
nr = nr + 1 if isprime(nr) num = num + 1 list[num] = nr ok if num = 10 exit ok
end
powerset(list,10) showarray(items,10) see nl
func showarray(items,ind)
for p = 1 to 20 for n = 1 to len(items) flag = 0 for m = 1 to ind if items[n][m] = 0 exit ok flag = flag + items[n][m] next if flag = p str = "" for x = 1 to len(items[n]) if items[n][x] != 0 str = str + items[n][x] + " " ok next str = left(str, len(str) - 1) str = str + "]" if substr(str, " ") > 0 see "" + p + " = [" see str + nl exit else str = "" ok ok next next
func powerset(list,ind)
num = 0 num2 = 0 items = newlist(pow(2,len(list))-1,ind) for i = 2 to (2 << len(list)) - 1 step 2 num2 = 0 num = num + 1 for j = 1 to len(list) if i & (1 << j) num2 = num2 + 1 if list[j] != 0 items[num][num2] = list[j] ok ok next next return items
</lang> Output:
5 = [2 3] 7 = [2 5] 8 = [3 5] 9 = [2 7] 10 = [2 3 5] 12 = [2 3 7] 13 = [2 11] 14 = [2 5 7] 15 = [3 5 7] 16 = [2 3 11] 17 = [2 3 5 7] 18 = [2 5 11] 19 = [3 5 11] 20 = [2 7 11]
Ruby
<lang ruby>require "prime"
def prime_partition(x, n)
Prime.each(x).to_a.combination(n).detect{|primes| primes.sum == x}
end
TESTCASES = [[99809, 1], [18, 2], [19, 3], [20, 4], [2017, 24],
[22699, 1], [22699, 2], [22699, 3], [22699, 4], [40355, 3]]
TESTCASES.each do |prime, num|
res = prime_partition(prime, num) str = res.nil? ? "no solution" : res.join(" + ") puts "Partitioned #{prime} with #{num} primes: #{str}"
end </lang>
- Output:
Partitioned 99809 with 1 primes: 99809 Partitioned 18 with 2 primes: 5 + 13 Partitioned 19 with 3 primes: 3 + 5 + 11 Partitioned 20 with 4 primes: no solution Partitioned 2017 with 24 primes: 2 + 3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 + 29 + 31 + 37 + 41 + 43 + 47 + 53 + 59 + 61 + 67 + 71 + 73 + 79 + 97 + 1129 Partitioned 22699 with 1 primes: 22699 Partitioned 22699 with 2 primes: 2 + 22697 Partitioned 22699 with 3 primes: 3 + 5 + 22691 Partitioned 22699 with 4 primes: 2 + 3 + 43 + 22651 Partitioned 40355 with 3 primes: 3 + 139 + 40213
Sidef
<lang ruby>func prime_partition(num, parts) {
if (parts == 1) { return (num.is_prime ? [num] : []) }
num.primes.combinations(parts, {|*c| return c if (c.sum == num) })
return []
}
var tests = [
[ 18, 2], [ 19, 3], [ 20, 4], [99807, 1], [99809, 1], [ 2017, 24], [22699, 1], [22699, 2], [22699, 3], [22699, 4], [40355, 3],
]
for num,parts (tests) {
say ("Partition %5d into %2d prime piece" % (num, parts), parts == 1 ? ': ' : 's: ', prime_partition(num, parts).join('+') || 'not possible')
}</lang>
- Output:
Partition 18 into 2 prime pieces: 5+13 Partition 19 into 3 prime pieces: 3+5+11 Partition 20 into 4 prime pieces: not possible Partition 99807 into 1 prime piece: not possible Partition 99809 into 1 prime piece: 99809 Partition 2017 into 24 prime pieces: 2+3+5+7+11+13+17+19+23+29+31+37+41+43+47+53+59+61+67+71+73+79+97+1129 Partition 22699 into 1 prime piece: 22699 Partition 22699 into 2 prime pieces: 2+22697 Partition 22699 into 3 prime pieces: 3+5+22691 Partition 22699 into 4 prime pieces: 2+3+43+22651 Partition 40355 into 3 prime pieces: 3+139+40213
VBScript
<lang vb>' Partition an integer X into N primes
dim p(),a(32),b(32),v,g: redim p(64) what="99809 1 18 2 19 3 20 4 2017 24 22699 1-4 40355 3" t1=split(what," ") for j=0 to ubound(t1) t2=split(t1(j)): x=t2(0): n=t2(1) t3=split(x,"-"): x=clng(t3(0)) if ubound(t3)=1 then y=clng(t3(1)) else y=x t3=split(n,"-"): n=clng(t3(0)) if ubound(t3)=1 then m=clng(t3(1)) else m=n genp y 'generate primes in p for g=x to y for q=n to m: part: next 'q next 'g next 'j
sub genp(high)
p(1)=2: p(2)=3: c=2: i=p(c)+2 do 'i k=2: bk=false do while k*k<=i and not bk 'k if i mod p(k)=0 then bk=true k=k+1 loop 'k if not bk then c=c+1: if c>ubound(p) then redim preserve p(ubound(p)+8) p(c)=i end if i=i+2 loop until p(c)>high 'i
end sub 'genp
sub getp(z)
if a(z)=0 then w=z-1: a(z)=a(w) a(z)=a(z)+1: w=a(z): b(z)=p(w)
end sub 'getp
function list()
w=b(1) if v=g then for i=2 to q: w=w&"+"&b(i): next else w="(not possible)" list="primes: "&w
end function 'list
sub part()
for i=lbound(a) to ubound(a): a(i)=0: next 'i for i=1 to q: call getp(i): next 'i do while true: v=0: bu=false for s=1 to q v=v+b(s) if v>g then if s=1 then exit do for k=s to q: a(k)=0: next 'k for r=s-1 to q: call getp(r): next 'r bu=true: exit for end if next 's if not bu then if v=g then exit do if v<g then call getp(q) end if loop wscript.echo "partition "&g&" into "&q&" "&list
end sub 'part </lang>
- Output:
partition 99809 into 1 primes: 99809 partition 18 into 2 primes: 5+13 partition 19 into 3 primes: 3+5+11 partition 20 into 4 primes: (not possible) partition 2017 into 24 primes: 2+3+5+7+11+13+17+19+23+29+31+37+41+43+47+53+59+61+67+71+73+79+97+1129 partition 22699 into 1 primes: 22699 partition 22699 into 2 primes: 2+22697 partition 22699 into 3 primes: 3+5+22691 partition 22699 into 4 primes: 2+3+43+22651 partition 40355 into 3 primes: 3+139+40213
Visual Basic .NET
<lang vbnet>' Partition an integer X into N primes - 29/03/2017 Option Explicit On
Module PartitionIntoPrimes
Dim p(8), a(32), b(32), v, g, q As Long
Sub Main() Dim what, t1(), t2(), t3(), xx, nn As String Dim x, y, n, m As Long what = "99809 1 18 2 19 3 20 4 2017 24 22699 1-4 40355 3" t1 = Split(what, " ") For j = 0 To UBound(t1) t2 = Split(t1(j)) : xx = t2(0) : nn = t2(1) t3 = Split(xx, "-") : x = CLng(t3(0)) If UBound(t3) = 1 Then y = CLng(t3(1)) Else y = x t3 = Split(nn, "-") : n = CLng(t3(0)) If UBound(t3) = 1 Then m = CLng(t3(1)) Else m = n genp(y) 'generate primes in p For g = x To y For q = n To m : part() : Next 'q Next 'g Next 'j End Sub 'Main
Sub genp(high As Long) Dim c, i, k As Long Dim bk As Boolean p(1) = 2 : p(2) = 3 : c = 2 : i = p(c) + 2 Do 'i k = 2 : bk = False Do While k * k <= i And Not bk 'k If i Mod p(k) = 0 Then bk = True k = k + 1 Loop 'k If Not bk Then c = c + 1 : If c > UBound(p) Then ReDim Preserve p(UBound(p) + 8) p(c) = i End If i = i + 2 Loop Until p(c) > high 'i End Sub 'genp
Sub getp(z As Long) Dim w As Long If a(z) = 0 Then w = z - 1 : a(z) = a(w) a(z) = a(z) + 1 : w = a(z) : b(z) = p(w) End Sub 'getp
Function list() Dim w As String w = b(1) If v = g Then For i = 2 To q : w = w & "+" & b(i) : Next Else w = "(not possible)" End If Return "primes: " & w End Function 'list
Sub part() For i = LBound(a) To UBound(a) : a(i) = 0 : Next 'i For i = 1 To q : Call getp(i) : Next 'i Do While True : v = 0 For s = 1 To q v = v + b(s) If v > g Then If s = 1 Then Exit Do For k = s To q : a(k) = 0 : Next 'k For r = s - 1 To q : Call getp(r) : Next 'r Continue Do End If Next 's If v = g Then Exit Do If v < g Then Call getp(q) Loop Console.WriteLine("partition " & g & " into " & q & " " & list()) End Sub 'part
End Module 'PartitionIntoPrimes </lang>
- Output:
partition 99809 into 1 primes: 99809 partition 18 into 2 primes: 5+13 partition 19 into 3 primes: 3+5+11 partition 20 into 4 primes: (not possible) partition 2017 into 24 primes: 2+3+5+7+11+13+17+19+23+29+31+37+41+43+47+53+59+61+67+71+73+79+97+1129 partition 22699 into 1 primes: 22699 partition 22699 into 2 primes: 2+22697 partition 22699 into 3 primes: 3+5+22691 partition 22699 into 4 primes: 2+3+43+22651 partition 40355 into 3 primes: 3+139+40213
zkl
Using the prime generator from task Extensible prime generator#zkl. <lang zkl> // Partition integer N into M unique primes fcn partition(N,M,idx=0,ps=List()){
var [const] sieve=Utils.Generator(Import("sieve").postponed_sieve); var [const] primes=List(); while(sieve.peek()<=N){ primes.append(sieve.next()) } if(M<2){ z:=primes.find(N); return(if(Void!=z and z>=idx) ps.append(N) else Void); } foreach z in ([idx..primes.len()-1]){ p:=primes[z]; if(p<=N and self.fcn(N-p,M-1,z+1,ps)) return(ps.insert(0,p)); if(p>N) break; } Void // no solution
}</lang> <lang zkl>foreach n,m in (T( T(18,2),T(19,3),T(99809,1),T(20,4),T(2017,24),
T(22699,1),T(22699,2),T(22699,3),T(22699,4),T(40355,3), )){ ps:=partition(n,m); if(ps) println("Partition %d with %d prime(s): %s".fmt(n,m,ps.concat("+"))); else println("Can not partition %d with %d prime(s)".fmt(n,m));
}</lang>
- Output:
Partition 18 with 2 prime(s): 5+13 Partition 19 with 3 prime(s): 3+5+11 Partition 99809 with 1 prime(s): 99809 Can not partition 20 with 4 prime(s) Partition 2017 with 24 prime(s): 2+3+5+7+11+13+17+19+23+29+31+37+41+43+47+53+59+61+67+71+73+79+97+1129 Partition 22699 with 1 prime(s): 22699 Partition 22699 with 2 prime(s): 2+22697 Partition 22699 with 3 prime(s): 3+5+22691 Partition 22699 with 4 prime(s): 2+3+43+22651 Partition 40355 with 3 prime(s): 3+139+40213