-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtriple_step.cpp
More file actions
141 lines (128 loc) · 3.54 KB
/
triple_step.cpp
File metadata and controls
141 lines (128 loc) · 3.54 KB
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* A child is running up a staircase with n steps and can hop either 1 step, 2 steps, or 3 steps
at a time. Implement a method to count how many possible ways the child can run up the stairs */
#include <iostream>
#include <array>
#include <memory>
#include <deque>
#include <vector>
#include <cmath>
template <size_t N>
struct Node
{
static const size_t C = N;
size_t hops;
std::array<std::shared_ptr<Node>, _C> children;
Node() : hops(0) {}
Node(size_t hops) : hops(hops) {}
};
template <size_t C>
void makeDecisionTree(std::shared_ptr<Node<C>> &node, size_t hops, size_t missingSteps, std::vector<std::array<std::shared_ptr<Node<C>>, C>> &missingStepsSubtrees)
{
node = std::make_shared<Node<C>>(hops);
for (size_t i = 0; i < std::min(missingSteps, C); ++i)
{
auto newHops = i + 1;
auto &child = missingStepsSubtrees[missingSteps][i];
if (child == nullptr)
{
makeDecisionTree(child, newHops, missingSteps - newHops, missingStepsSubtrees);
}
node->children[i] = child;
}
}
template <size_t C>
void makeDecisionTree(std::shared_ptr<Node<C>> &root, size_t step)
{
std::vector<std::array<std::shared_ptr<Node<C>>, C>> missingStepsSubtrees;
missingStepsSubtrees.resize(step + 1);
makeDecisionTree(root, 0, step, missingStepsSubtrees);
}
template <size_t C>
struct Visit
{
const Node<C> *node;
size_t depth;
};
template <size_t C, typename Visitor>
bool inOrderDfs(const std::shared_ptr<Node<C>> &node, Visitor visitor, size_t depth = 0)
{
if (visitor(node, depth))
{
return true;
}
for (size_t i = 0; i < C; ++i)
{
auto &child = node->children[i];
if (child != nullptr)
{
if (inOrderDfs(child, visitor, depth + 1))
{
return true;
}
}
}
return false;
}
template <size_t C>
size_t getMaxDepth(const std::shared_ptr<Node<C>> &root)
{
size_t maxDepth = 0;
inOrderDfs(root, [&maxDepth](const std::shared_ptr<Node<C>> &child, size_t depth) -> bool {
if (depth > maxDepth)
{
maxDepth = depth;
}
return false;
});
return maxDepth;
}
template <size_t C>
void printTree(const std::shared_ptr<Node<C>> &root)
{
std::deque<Visit<C>> bfs;
bfs.push_back({root.get(), 0});
auto maxDepth = getMaxDepth(root);
size_t currDepth = 0;
size_t prevIndent = 0;
std::string spacing = "";
while (!bfs.empty())
{
auto visit = bfs.front();
bfs.pop_front();
auto *node = visit.node;
if (visit.depth > currDepth || currDepth == 0)
{
std::cout << std::endl;
currDepth = visit.depth;
auto currIndent = std::pow(C, maxDepth - currDepth) - 1;
std::cout << std::string(currIndent, ' ');
if (prevIndent > 0)
spacing = std::string(prevIndent - currIndent - 1, ' ');
prevIndent = currIndent;
}
std::cout << node->hops << spacing;
for (size_t i = 0; i < C; ++i)
{
auto &child = node->children[i];
if (child != nullptr)
{
bfs.push_back({child.get(), visit.depth + 1});
}
}
}
}
using TernaryNode = Node<3>;
void test(size_t steps)
{
std::cout << "steps: " << steps << std::endl;
std::cout << "tree: " << std::endl;
std::shared_ptr<TernaryNode> root;
makeDecisionTree(root, steps);
printTree(root);
std::cout << std::endl;
}
int main()
{
test(6);
return 0;
}