Equal Partition
:::note PROBLEM Given a set of positive numbers, find if we can partition it into two subsets such that the sum of elements in both subsets is equal. :::
#include <iostream>#include <vector>#include <format>#include <algorithm>#include <ranges>#include <numeric>#include <any>
class EqualPartitionSolver {private: class DpEntry { public: bool isPossible = false; std::vector<int> indices = {}; };public: std::optional<std::vector<int>> solve(std::vector<int> const& values) { if (values.empty()) { return std::vector<int> {}; }
auto sum = std::reduce(values.cbegin(), values.cend());
if (sum % 2 == 1) { return {}; }
int halfSum = sum / 2;
std::vector<DpEntry> dp(halfSum + 1); dp[0].isPossible = true;
std::ranges::for_each( values | std::views::enumerate, [&, maxSumYet = 0] (auto const& indexValueTuple) mutable { auto [index, value] = indexValueTuple;
maxSumYet += value; maxSumYet = std::min(maxSumYet, halfSum);
for (int c = maxSumYet; c >= value; --c) { if (dp[c].isPossible) { continue; }
if (!dp[c - value].isPossible) { continue; }
dp[c].isPossible = true; dp[c].indices = dp[c - value].indices; dp[c].indices.push_back(index); } } );
if (!dp[halfSum].isPossible) { return {}; }
return dp[halfSum].indices; }};
int main() { EqualPartitionSolver equalPartitionSolver;
auto solution = equalPartitionSolver.solve({1, 1, 3, 4, 7});
std::cout << std::format("isPossible: {}", solution.has_value()) << std::endl;
solution.and_then([](auto const& indices) -> std::optional<std::any> { std::cout << "indices: "; std::ranges::for_each(indices, [](auto const& index) { std::cout << std::format("{} ", index); }); std::cout << std::endl; return {}; });}
/* * isPossible: true * indices: 0 2 3 */