Another way of asking this question, using your example values, is: How many ways can you draw 6 numbers, with replacement, from the set {0,2,3,4,5,6,7,9,11,14,17,21} such that the sum is 44.
Once you have those answers you can select one uniformly, shuffle them into your attributes and add 7 to each one.
Some example answers:
{21, 21, 2, 0, 0, 0} {21, 17, 6, 0, 0, 0} {21, 17, 4, 2, 0, 0}
{21, 17, 3, 3, 0, 0} {21, 17, 2, 2, 2, 0}
etc.
So you select one of these, say {21, 21, 2, 0, 0, 0}. Shuffle it into your 6 attributes (A to F) for example {21, 0, 0, 2, 21, 0}. Map it back to your values {18, 7, 7, 8, 18, 7}.
Note, shuffling is not as easy as it sounds, there are discussions here on stackoverflow about it, and there is this interesting article: http://www.cigital.com/papers/download/developer_gambling.php
Here is correct (I believe), but not necessarily efficient (or pretty), C++ to calculate your sets:
#include <vector>
#include <iterator>
#include <iostream>
typedef std::vector<int> Costs;
typedef std::vector<int> Attrs;
typedef std::vector<Attrs> Choices;
void gen(Choices& c, Attrs a, int sum, Costs costs, int attrs) {
if (sum < 0) { return; }
if (attrs < 1) {
if (sum == 0) {
c.push_back(a);
}
return;
}
auto cc = costs;
for (auto cost : costs) {
a.push_back(cost);
gen(c, a, sum - cost, cc, attrs - 1);
a.pop_back();
cc.erase(cc.begin());
}
}
Choices genChoices(int sum, const Costs& costs, int attrs) {
Choices allChoices;
gen(allChoices, Attrs(), sum, costs, attrs);
return allChoices;
}
int main(int, char*[]) {
const Costs costs { 21, 17, 14, 11, 9, 7, 6, 5, 4, 3, 2, 0 };
const int sum = 44;
const int attrs = 6;
auto choices = genChoices(sum, costs, attrs);
std::cout << choices.size() << "\n";
for (auto c : choices) {
std::copy(std::begin(c), std::end(c), std::ostream_iterator<Attrs::value_type>(std::cout, " "));
std::cout << "\n";
}
return 0;
}
Compile with g++ 4.7.3: g++ -std=c++0x -Wall -Wextra attrs.cpp
There are 280 of them for the example you give.