Partition an integer x into n primes: Difference between revisions

Content added Content deleted
m (added this task to prime numbers category.)
No edit summary
Line 41: Line 41:
:*   [[Sequence of primes by trial division]]
:*   [[Sequence of primes by trial division]]
<br><br>
<br><br>

=={{header|C++}}==
{{trans|D}}
<lang cpp>#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

std::vector<int> primes;

struct Seq {
public:
bool empty() {
return p < 0;
}

int front() {
return p;
}

void popFront() {
if (p == 2) {
p++;
} else {
p += 2;
while (!empty() && !isPrime(p)) {
p += 2;
}
}
}

private:
int p = 2;

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;
}
};

// generate the first 50,000 primes and call it good
void init() {
Seq seq;

while (!seq.empty() && primes.size() < 50000) {
primes.push_back(seq.front());
seq.popFront();
}
}

bool findCombo(int k, int x, int m, int n, std::vector<int>& combo) {
if (k >= m) {
int sum = 0;
for (int idx : combo) {
sum += primes[idx];
}

if (sum == x) {
auto word = (m > 1) ? "primes" : "prime";
printf("Partitioned %5d with %2d %s ", x, m, word);
for (int idx = 0; idx < m; ++idx) {
std::cout << primes[combo[idx]];
if (idx < m - 1) {
std::cout << '+';
} else {
std::cout << '\n';
}
}
return true;
}
} else {
for (int j = 0; j < n; j++) {
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) {
if (x < 2 || m < 1 || m >= x) {
throw std::runtime_error("Invalid parameters");
}

std::vector<int> filteredPrimes;
std::copy_if(
primes.cbegin(), primes.cend(),
std::back_inserter(filteredPrimes),
[x](int a) { return a <= x; }
);

int n = filteredPrimes.size();
if (n < m) {
throw std::runtime_error("Not enough primes");
}

std::vector<int> combo;
combo.resize(m);
if (!findCombo(0, x, m, n, combo)) {
auto word = (m > 1) ? "primes" : "prime";
printf("Partitioned %5d with %2d %s: (not possible)\n", x, m, word);
}
}

int main() {
init();

std::vector<std::pair<int, int>> a{
{99809, 1},
{ 18, 2},
{ 19, 3},
{ 20, 4},
{ 2017, 24},
{22699, 1},
{22699, 2},
{22699, 3},
{22699, 4},
{40355, 3}
};

for (auto& p : a) {
partition(p.first, p.second);
}

return 0;
}</lang>
{{out}}
<pre>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</pre>


=={{header|C sharp}}==
=={{header|C sharp}}==