A
Alf P. Steinbach
* Branimir Maksimovic:
#include <algorithm>
#include <list>
#include "nac_puzzle.h"
using namespace std;
using namespace nac_puzzle;
struct print_list{
void operator()(const State& s)const
{
printf("Nuns left:%u Cannibals left:%u"
"\tNuns right:%u Cannibals right%u"
"\tBoat position:%s\n",
s.n(nun,nac_puzzle::left),s.n(cannibal,nac_puzzle::left),
s.n(nun,nac_puzzle::right),s.n(cannibal,nac_puzzle::right),
s.boatPosition() == nac_puzzle::left?"left":"right"
);
fflush(stdout);
}
};
int main(int argc, char *argv[])
{
assert(maxPerTransfer>nPersonsOfAKind/2);
// no solution for such cases at least for me
unsigned max =
maxPerTransfer>=nPersonsOfAKind?nPersonsOfAKind-1:maxPerTransfer;
// this is just to simplify algo
list<State> l;
l.push_back(State());
while(!l.back().isSolution())
{
l.push_back(l.back());
unsigned nc = l.back().n(cannibal,l.back().boatPosition());
unsigned nn = l.back().n(nun,l.back().boatPosition());
if(l.back().boatPosition() == nac_puzzle::left)
{
if(nn==nc)
{
if(l.back().n(nun,nac_puzzle::right)>max-1)
l.back().transfer(0,nn);
else
l.back().transfer(1,1);
}
else
l.back().transfer(nc>max?nc-max:1,0);
}
else
{
if((nn>nc && nn-nc >= max) ||
(nn==nc && nn <= max))
{
l.back().transfer(0,nn<max?nn:max);
}
else
{
if(nn==nc && nn+nc <= max)
{
l.back().transfer(nc,nn);
}
else
l.back().transfer(nc>max?max:nc,0);
}
}
}
printf("Solution:\n");
for_each(l.begin(),l.end(),print_list());
return 0;
}
Well, yes, but how does it work? As far as I can see the list is only used to
record the sequence of moves for the final display? I.e., except for the
final display the list could be removed from the code, and one would have a
while-loop that generated only a correct move in each iteration?
So, is the difference from hard-coding the moves that this can handle other
puzzle parameters (number of nuns & cannibals, max per transfer)?
Anyway, good job, and I have a suggestion for the code. Namely, the
print_list 'struct'. You can make that simply a function. ;-)
Cheers,
- Alf
#include <cstdio>
#include <algorithm>
#include <list>
#include "nac_puzzle.h"
using namespace std;
using namespace nac_puzzle;
struct print_list{
void operator()(const State& s)const
{
printf("Nuns left:%u Cannibals left:%u"
"\tNuns right:%u Cannibals right%u"
"\tBoat position:%s\n",
s.n(nun,nac_puzzle::left),s.n(cannibal,nac_puzzle::left),
s.n(nun,nac_puzzle::right),s.n(cannibal,nac_puzzle::right),
s.boatPosition() == nac_puzzle::left?"left":"right"
);
fflush(stdout);
}
};
int main(int argc, char *argv[])
{
assert(maxPerTransfer>nPersonsOfAKind/2);
// no solution for such cases at least for me
unsigned max =
maxPerTransfer>=nPersonsOfAKind?nPersonsOfAKind-1:maxPerTransfer;
// this is just to simplify algo
list<State> l;
l.push_back(State());
while(!l.back().isSolution())
{
l.push_back(l.back());
unsigned nc = l.back().n(cannibal,l.back().boatPosition());
unsigned nn = l.back().n(nun,l.back().boatPosition());
if(l.back().boatPosition() == nac_puzzle::left)
{
if(nn==nc)
{
if(l.back().n(nun,nac_puzzle::right)>max-1)
l.back().transfer(0,nn);
else
l.back().transfer(1,1);
}
else
l.back().transfer(nc>max?nc-max:1,0);
}
else
{
if((nn>nc && nn-nc >= max) ||
(nn==nc && nn <= max))
{
l.back().transfer(0,nn<max?nn:max);
}
else
{
if(nn==nc && nn+nc <= max)
{
l.back().transfer(nc,nn);
}
else
l.back().transfer(nc>max?max:nc,0);
}
}
}
printf("Solution:\n");
for_each(l.begin(),l.end(),print_list());
return 0;
}
Well, yes, but how does it work? As far as I can see the list is only used to
record the sequence of moves for the final display? I.e., except for the
final display the list could be removed from the code, and one would have a
while-loop that generated only a correct move in each iteration?
So, is the difference from hard-coding the moves that this can handle other
puzzle parameters (number of nuns & cannibals, max per transfer)?
Anyway, good job, and I have a suggestion for the code. Namely, the
print_list 'struct'. You can make that simply a function. ;-)
Cheers,
- Alf