25 template <
int numDisks>
29 for (
int x = 0; x < 4; x++)
33 for (
int x = 0; x < numDisks; x++)
35 disks[3][x] = numDisks-x;
42 for (
int x = 0; x < 4; x++)
46 for (
int x = 0; x < numDisks; x++)
48 disks[3][x] = numDisks-x;
54 for (
int x = 0; x < 4; x++)
58 for (
int x = 0; x < numDisks; x++)
60 disks[0][x] = numDisks-x;
72 return disks[whichPeg][whichDisk];
92 for (
int x = 0; x < 4; x++)
94 out <<
"(" << x <<
") ";
103 for (
int x = 0; x < 4; x++)
123 out <<
"(" << +m.
source <<
", " << +m.
dest <<
")";
154 std::string
GetName() {
return "TOH("+std::to_string(disks)+
")"; }
165 mutable std::vector<TOHMove>
acts;
176 GetActions(nodeID, acts);
177 for (
auto act : acts)
179 this->GetNextState(nodeID, act, tmp);
180 neighbors.push_back(tmp);
187 bool goalOrdered =
false;
205 actions.push_back(
TOHMove(0, 1));
209 actions.push_back(
TOHMove(1, 0));
214 actions.push_back(
TOHMove(0, 2));
218 actions.push_back(
TOHMove(2, 0));
224 actions.push_back(
TOHMove(0, 3));
228 actions.push_back(
TOHMove(3, 0));
233 actions.push_back(
TOHMove(1, 2));
237 actions.push_back(
TOHMove(2, 1));
242 actions.push_back(
TOHMove(1, 3));
246 actions.push_back(
TOHMove(3, 1));
251 actions.push_back(
TOHMove(2, 3));
255 actions.push_back(
TOHMove(3, 2));
292 return (
node == goal);
301 for (
int x = 0; x < 4; x++)
303 for (
int y = 0; y <
node.GetDiskCountOnPeg(x); y++)
305 hash |= (uint64_t(x)<<(2*(
node.GetDiskOnPeg(x, y)-1)));
314 return 1ull<<(2*disks);
320 for (
int x = 0; x < 4; x++)
322 for (
int x = disks-1; x >= 0; x--)
324 int nextPeg = (hash>>(2*x))&0x3;
339 glColor3f(0.5, 0.5, 0.5);
344 glColor3f(0.6, 0.4, 0.2);
346 glScalef(1.0, 0.05, 0.25);
347 DrawBox(0, 0.4/0.05+1, 0, 1.0);
355 glColor3f(0.0, 0.0, 1.0);
356 double offset[4] = {-0.75, -0.25, 0.25, 0.75};
357 for (
int x = 0; x < 4; x++)
362 glColor3f(0.0, 1.0-
float(which)/
float(disks), 1.0);
363 DrawCylinder(offset[x], 0.4-0.4/(1+
float(disks))-y*0.8/(1+
float(disks)), 0,
364 0.02, 0.04+0.2*which/
float(disks), 0.8/(1+
float(disks)));
373 TOHMove m = this->GetAction(s, s2);
378 glColor3f(0.0, 0.0, 1.0);
379 double offset[4] = {-0.75, -0.25, 0.25, 0.75};
380 for (
int x = 0; x < 4; x++)
385 if (which != animatingDisk)
387 glColor3f(0.0, 1.0-
float(which)/
float(disks), 1.0);
388 DrawCylinder(offset[x], 0.4-0.4/(1+
float(disks))-y*0.8/(1+
float(disks)), 0,
389 0.02, 0.04+0.2*which/
float(disks), 0.8/(1+
float(disks)));
393 glColor3f(0.0, 1.0-
float(animatingDisk)/
float(disks), 1.0);
394 if (interval <= 0.333)
397 DrawCylinder(offset[m.
source], 0.4-0.4/(1+
float(disks))-initialHeight*0.8/(1+
float(disks)) - (interval)*(disks+1-initialHeight)*0.8/(1+
float(disks)), 0,
398 0.02, 0.04+0.2*animatingDisk/
float(disks), 0.8/(1+
float(disks)));
400 else if (interval <= 0.666)
403 DrawCylinder((2-interval)*offset[m.
source]+(interval-1)*offset[m.
dest], 0.4-0.4/(1+
float(disks))-0.8-0.2*sin((interval-1)*
PI), 0,
404 0.02, 0.04+0.2*animatingDisk/
float(disks), 0.8/(1+
float(disks)));
407 DrawCylinder(offset[m.
dest], 0.4-0.4/(1+
float(disks))-finalHeight*0.8/(1+
float(disks)) -
408 ((1.0-interval)/0.334)*(disks+1-finalHeight)*0.8/(1+
float(disks)), 0,
409 0.02, 0.04+0.2*animatingDisk/
float(disks), 0.8/(1+
float(disks)));
419 template <
int patternDisks,
int totalDisks,
int offset=0>
420 class TOHPDB :
public PDBHeuristic<TOHState<patternDisks>, TOHMove, TOH<patternDisks>, TOHState<totalDisks>> {
428 int diff = totalDisks - patternDisks;
431 for (
int x = 0; x < 4; x++)
434 for (
int y = 0; y < tmp.
counts[x]; y++)
436 tmp.
disks[x][y] = start.
disks[x][y]+diff-offset;
451 int diff = totalDisks - patternDisks;
453 for (
int x = 0; x < 4; x++)
459 hash |= (uint64_t(x)<<(2*(s.
GetDiskOnPeg(x, y)-1-diff+offset)));
467 return 1ull<<(2*patternDisks);
478 virtual bool Load(
const char *prefix)
482 virtual void Save(
const char *prefix)
484 FILE *f = fopen(
GetFileName(prefix).c_str(),
"w+");
487 fprintf(stderr,
"Error saving");
496 std::string s = prefix;
497 s +=
"TOH4+"+std::to_string(patternDisks)+
"+"+std::to_string(totalDisks)+
".pdb";