I created the database of solution sets programatically. I used the code below to enumerate {number of cells, clue} pairs:
typedef std::bitset<9> valueSet_t;
typedef std::list<valueSet_t> result_t;
const unsigned NumToBit[] = {
0, 1, 2, 4, 8, 16, 32, 64, 128, 256,
};
void iterLevel(size_t begin, size_t level, size_t sum, valueSet_t & set, result_t & result)
{
if(sum < begin)
return;
if(--level == 0) {
if(sum <= 9) {
set |= NumToBit[sum];
result.push_back(set);
set &= ~NumToBit[sum];
}
return;
}
for(size_t i = begin; i <= 9; i++) {
set |= NumToBit[i];
iterLevel(i + 1, level, sum - i, set, result);
set &= ~NumToBit[i];
}
}
void kakkuroSums()
{
valueSet_t set;
result_t result;
for(size_t level = 2; level <= 9; level++) {
for(size_t sum = 3; sum <= 45; sum++) {
set.reset();
result.clear();
iterLevel(1, level, sum, set, result);
if(result.size() > 0) {
// generate the database here
}
}
}
typedef std::list<valueSet_t> result_t;
const unsigned NumToBit[] = {
0, 1, 2, 4, 8, 16, 32, 64, 128, 256,
};
void iterLevel(size_t begin, size_t level, size_t sum, valueSet_t & set, result_t & result)
{
if(sum < begin)
return;
if(--level == 0) {
if(sum <= 9) {
set |= NumToBit[sum];
result.push_back(set);
set &= ~NumToBit[sum];
}
return;
}
for(size_t i = begin; i <= 9; i++) {
set |= NumToBit[i];
iterLevel(i + 1, level, sum - i, set, result);
set &= ~NumToBit[i];
}
}
void kakkuroSums()
{
valueSet_t set;
result_t result;
for(size_t level = 2; level <= 9; level++) {
for(size_t sum = 3; sum <= 45; sum++) {
set.reset();
result.clear();
iterLevel(1, level, sum, set, result);
if(result.size() > 0) {
// generate the database here
}
}
}
The idea is, when I calculate solution sets for an entry with 5 white cells, call iterLevel() recursively 5 times. Each call picks up a solution value for a white cell.
For example, assume we want to find solution sets for 13-in-three. The first call of iterLevel() picks up "1" as a solution value. The second call picks up "2". The last call finds a set {1, 2, 10} but this is not a valid set, so just returns. Back to the second call, it picks up "3" next. The last call finds a set {1, 3, 9} and this is valid, so remember the result and returns. And so on.
But after I made the database, I realized that I could find all solution sets by simply finding all combinations of 1 through 9. And it is easy to get all the combinations by checking values from 3 to 511.
For example, 3 - 0b11 in binary. If you interprete the least bit as "1" and the second least bit as "2", 3 is interpreted as a solution set {1, 2} for 3-in-two. 4 has only one bit set, so skip it. 5 is interpreted as {1, 3}. 6 as {2, 3}, 7 as {1, 2, 3}, and so on.
The result is not sorted, so you need to sort it in the order you want but it looks faster than what I actually did.
For example, assume we want to find solution sets for 13-in-three. The first call of iterLevel() picks up "1" as a solution value. The second call picks up "2". The last call finds a set {1, 2, 10} but this is not a valid set, so just returns. Back to the second call, it picks up "3" next. The last call finds a set {1, 3, 9} and this is valid, so remember the result and returns. And so on.
But after I made the database, I realized that I could find all solution sets by simply finding all combinations of 1 through 9. And it is easy to get all the combinations by checking values from 3 to 511.
For example, 3 - 0b11 in binary. If you interprete the least bit as "1" and the second least bit as "2", 3 is interpreted as a solution set {1, 2} for 3-in-two. 4 has only one bit set, so skip it. 5 is interpreted as {1, 3}. 6 as {2, 3}, 7 as {1, 2, 3}, and so on.
The result is not sorted, so you need to sort it in the order you want but it looks faster than what I actually did.
No comments:
Post a Comment