-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHanoiTowerAStar.cpp
99 lines (93 loc) · 3.25 KB
/
HanoiTowerAStar.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include "HanoiTowerAStar.hpp"
#include <algorithm>
#include <numeric>
#include <set>
#include <cassert>
#include <iostream>
HanoiTowerAStar::HanoiTowerAStar(const unsigned int towerHeight, const unsigned int numberOfPoles)
{
HanoiState::HanoiPole properPole;
properPole.resize(towerHeight);
std::iota(properPole.rbegin(), properPole.rend(), 1);
root.state.push_back(properPole);
for (int i = 1; i < numberOfPoles; ++i) {
root.state.push_back(HanoiState::HanoiPole());
solution.state.push_back(HanoiState::HanoiPole());
}
solution.state.push_back(properPole);
root.distance = countStateHeuristic(root) + moveWeight;
// this is terrible hack cause i haven't used pointers and vector
// reallocation invalidated my references to parents
visitedStates.reserve(30000);
}
HanoiState HanoiTowerAStar::solve() {
int baseHeuristic = 100;
int baseHeuristicStep = 100;
std::set<HanoiState> statesToCheck;
statesToCheck.insert(root);
while(!statesToCheck.empty())
{
auto beg = statesToCheck.begin();
HanoiState stateToCheck(*beg);
statesToCheck.erase(beg);
if (isSolution(stateToCheck))
{
return stateToCheck;
}
std::vector<HanoiState> nextStates = generateNextValidStates(stateToCheck);
visitedStates.push_back(std::move(stateToCheck));
for (auto& nextState: nextStates)
{
if (isStateAlreadyChecked(nextState))
{
continue;
}
nextState.distance+=baseHeuristic;
auto sameStateAs = std::find_if(
statesToCheck.cbegin(),
statesToCheck.cend(),
[&nextState](HanoiState const& visitedState) -> bool {
return visitedState == nextState;
}
);
if (sameStateAs == statesToCheck.end())
{
nextState.parent = &visitedStates.back();
statesToCheck.insert(std::move(nextState));
}
else
{
int nextStateDistance = countStateHeuristic(nextState) + moveWeight + baseHeuristic;
if (sameStateAs->distance > nextStateDistance)
{
// std::cout << "i am here" << std::endl;
// printState(*sameStateAs,0);
// printState(nextState,0);
// printState(visitedStates.back(),0);
// printState(*sameStateAs->parent, 0);
sameStateAs->distance = nextStateDistance;
}
}
}
baseHeuristic+=baseHeuristicStep;
}
assert(1==2);
}
bool HanoiTowerAStar::isStateAlreadyChecked(const HanoiState &state) const
{
auto it = std::find_if(visitedStates.cbegin(),
visitedStates.cend(),
[&state](HanoiState const& visitedState) -> bool {
return visitedState == state;
}
);
return it != visitedStates.end();
}
bool HanoiTowerAStar::isSolution(HanoiState const& state) const
{
return solution == state;
}
int const HanoiTowerAStar::getVisitedStatesNumber() const
{
return visitedStates.size();
}