Пример #1
0
// Given a list of lists of possible cage values:
//     [[1,2,3], [3,4,5]]
// Recursively generates tuples of combinations from each of the lists as
// follows:
//   [1,3]
//   [1,4]
//   [1,5]
//   [2,3]
//   [2,4]
// ... etc
// Each of these is checked against the target sum, and pushed into a result
// vector if they match.
// Note: The algorithm assumes that the list of possibles/candidates are
// ordered. This allows it to bail out early if it detects there's no point
// going further.
static void subsetSum(const std::vector<IntList> &possible_lists,
                      const std::size_t p_size, IntList &tuple,
                      unsigned tuple_sum, std::vector<IntList> &subsets,
                      const unsigned target_sum, unsigned list_idx) {
  for (unsigned p = list_idx; p < p_size; ++p) {
    for (auto &poss : possible_lists[p]) {
      // Optimization for small target sums: if the candidate is bigger than
      // the target itself then it can't be valid, neither can any candidate
      // after it (ordered).
      if (target_sum < static_cast<unsigned>(poss)) {
        break;
      }

      // Can't repeat a value inside a cage
      if (std::find(tuple.begin(), tuple.end(), poss) != tuple.end()) {
        continue;
      }

      // Pre-calculate the new tuple values to avoid spurious
      // insertions/deletions to the vector.
      const auto new_tuple_sum = tuple_sum + poss;
      const auto new_tuple_size = tuple.size() + 1;

      // If we've added too much then we can bail out (ordered).
      if (new_tuple_sum > target_sum) {
        break;
      }

      // If there are fewer spots left in the tuple than there are options for
      // the sum to reach the target, bail.
      // TODO: This could be more sophisticated (can't have more than one 1, so
      // it's more like the N-1 sum that it should be greater than.
      if ((p_size - new_tuple_size) > (target_sum - new_tuple_sum)) {
        break;
      }

      if (new_tuple_size == p_size) {
        // If we've reached our target size then we can stop searching other
        // possiblities from this list (ordered).
        if (new_tuple_sum == target_sum) {
          tuple.push_back(poss);
          subsets.push_back(tuple);
          tuple.pop_back();
          break;
        }

        // Else, move on to the next candidate in the list.
        continue;
      }

      tuple_sum += poss;
      tuple.push_back(poss);

      subsetSum(possible_lists, p_size, tuple, tuple_sum, subsets, target_sum,
                p + 1);

      tuple.pop_back();
      tuple_sum -= poss;
    }
  }
}
Пример #2
0
	TestList()
	{
		typedef List<char, DebugAllocator<int> > IntList;

		IntList a;
		a.push_back('1');
		a.push_back('2');
		a.push_back('3');
		LIST_ASSERT(*a.begin() == '1');
		LIST_ASSERT(*++a.begin() == '2');
		LIST_ASSERT(*++++a.begin() == '3');
		LIST_ASSERT(++++++a.begin() == a.end());

		IntList b;
		b.push_back('a');
		b.push_back('b');
		b.push_back('c');
		LIST_ASSERT(*b.begin() == 'a');
		LIST_ASSERT(*++b.begin() == 'b');
		LIST_ASSERT(*++++b.begin() == 'c');
		LIST_ASSERT(++++++b.begin() == b.end());

		// swap full lists
		a.swap(b);
		LIST_ASSERT(*a.begin() == 'a');
		LIST_ASSERT(*++a.begin() == 'b');
		LIST_ASSERT(*++++a.begin() == 'c');
		LIST_ASSERT(++++++a.begin() == a.end());
		LIST_ASSERT(*b.begin() == '1');
		LIST_ASSERT(*++b.begin() == '2');
		LIST_ASSERT(*++++b.begin() == '3');
		LIST_ASSERT(++++++b.begin() == b.end());

		// swap to/from empty list
		IntList c;
		c.swap(b);
		LIST_ASSERT(b.empty());
		LIST_ASSERT(*c.begin() == '1');
		LIST_ASSERT(*++c.begin() == '2');
		LIST_ASSERT(*++++c.begin() == '3');
		LIST_ASSERT(++++++c.begin() == c.end());

		c.swap(b);
		LIST_ASSERT(c.empty());
		LIST_ASSERT(*b.begin() == '1');
		LIST_ASSERT(*++b.begin() == '2');
		LIST_ASSERT(*++++b.begin() == '3');
		LIST_ASSERT(++++++b.begin() == b.end());

		IntList d;
		c.swap(d);
		LIST_ASSERT(c.empty());
		LIST_ASSERT(d.empty());

		c.splice(c.end(), d);
		LIST_ASSERT(c.empty());
		LIST_ASSERT(d.empty());

		// splice full with empty
		b.splice(b.end(), c);
		LIST_ASSERT(c.empty());
		LIST_ASSERT(*b.begin() == '1');
		LIST_ASSERT(*++b.begin() == '2');
		LIST_ASSERT(*++++b.begin() == '3');
		LIST_ASSERT(++++++b.begin() == b.end());

		// splice empty with full
		c.splice(c.end(), b);
		LIST_ASSERT(b.empty());
		LIST_ASSERT(*c.begin() == '1');
		LIST_ASSERT(*++c.begin() == '2');
		LIST_ASSERT(*++++c.begin() == '3');
		LIST_ASSERT(++++++c.begin() == c.end());

		// splice full with full
		c.splice(c.end(), a);
		LIST_ASSERT(a.empty());
		LIST_ASSERT(*c.begin() == '1');
		LIST_ASSERT(*++c.begin() == '2');
		LIST_ASSERT(*++++c.begin() == '3');
		LIST_ASSERT(*++++++c.begin() == 'a');
		LIST_ASSERT(*++++++++c.begin() == 'b');
		LIST_ASSERT(*++++++++++c.begin() == 'c');
		LIST_ASSERT(++++++++++++c.begin() == c.end());


		c.pop_back();
		LIST_ASSERT(!c.empty());
		c.pop_back();
		LIST_ASSERT(!c.empty());
		c.pop_back();
		LIST_ASSERT(!c.empty());
		c.pop_back();
		LIST_ASSERT(!c.empty());
		c.pop_back();
		LIST_ASSERT(!c.empty());
		c.pop_back();
		LIST_ASSERT(c.empty());
	}