This commit is contained in:
Lily Tsuru 2024-10-21 12:27:40 -04:00
parent af49206a16
commit f8285f9e4c
5 changed files with 111 additions and 114 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
__pycache__/
*.o
/vxorg
/tree_test
/testdata

View file

@ -2,37 +2,29 @@
#include <vector> #include <vector>
/// Port of tree.py to C++ /// Port of tree.py to C++
template<class T> template <class T>
struct Tree { struct Tree {
// FIXME make T not require default constructability // FIXME make T not require default constructability
struct Node { struct Node {
protected: protected:
friend Tree; friend Tree;
Node* parent = nullptr; Node* parent = nullptr;
std::vector<Node*> children{}; std::vector<Node*> children {};
T item{}; T item {};
public: public:
~Node() { ~Node() {
for(auto& child: children) for(auto& child : children)
delete child; delete child;
} }
T& data() { T& data() { return item; }
return item;
}
const T& data() const { const T& data() const { return item; }
return item;
}
bool is_leaf() const { bool is_leaf() const { return children.size() == 0; }
return children.size() == 0;
}
Node* parent_node() { Node* parent_node() { return parent; }
return parent;
}
Node* create_leaf(const T& item) { Node* create_leaf(const T& item) {
auto* node = new Node; auto* node = new Node;
@ -42,21 +34,21 @@ struct Tree {
return node; return node;
} }
template<class Fn> template <class Fn>
void walk(Fn&& fn) { void walk(Fn&& fn) {
fn(this); fn(this);
if(!is_leaf()) { if(!is_leaf()) {
for(auto& child: children) for(auto& child : children)
child->walk(fn); child->walk(fn);
} }
} }
template<class Pred> template <class Pred>
Node* find_child(Pred&& predicate) { Node* find_child(Pred&& predicate) {
if(predicate(this) == true) if(predicate(this) == true)
return this; return this;
for(auto& child: children) for(auto& child : children)
if(predicate(child) == true) if(predicate(child) == true)
return child; return child;
@ -67,40 +59,30 @@ struct Tree {
auto* parent = this->parent; auto* parent = this->parent;
auto parent_count = 0z; auto parent_count = 0z;
while(parent) { while(parent) {
parent_count ++; parent_count++;
parent = parent->parent; parent = parent->parent;
} }
return parent_count; return parent_count;
} }
}; };
Tree() { Tree() { root = new Node; }
root = new Node;
}
~Tree() { ~Tree() { delete root; }
delete root;
}
// Trees are not copyable but they can move // Trees are not copyable but they can move
Tree(const Tree&) = delete; Tree(const Tree&) = delete;
Tree(Tree&&) = default; Tree(Tree&&) = default;
template<class Fn> template <class Fn>
void walk(Fn&& fn) { void walk(Fn&& fn) {
root->walk(fn); root->walk(fn);
} }
Node* create_leaf(const T& item) { return root->create_leaf(item); }
Node* create_leaf(const T& item) { Node* root_node() { return root; }
return root->create_leaf(item);
}
Node* root_node() { private:
return root;
}
private:
Node* root; Node* root;
}; };

View file

@ -21,6 +21,34 @@ namespace vxorg {
return res; return res;
} }
std::string get_sample_name(VxHeavenTree::Node* node) {
if(node == nullptr)
return "";
if(!node->data().is_sample)
return node->data().name;
std::string sample_name {};
std::vector<vxorg::VxHeavenItem*> parent_list {};
vxorg::VxHeavenTree::Node* parent = node->parent_node();
while(parent) {
if(parent->data().name.empty())
break;
parent_list.push_back(&parent->data());
parent = parent->parent_node();
}
for(auto& item : std::views::reverse(parent_list)) {
sample_name += std::format("{}.", item->name);
}
sample_name += node->data().name;
return sample_name;
}
void parse_into_tree(VxHeavenTree& tree, std::istream& is) { void parse_into_tree(VxHeavenTree& tree, std::istream& is) {
std::string line {}; std::string line {};
while(std::getline(is, line)) { while(std::getline(is, line)) {

View file

@ -1,7 +1,8 @@
#pragma once #pragma once
#include "tree.hpp"
#include <string> #include <string>
#include "tree.hpp"
namespace vxorg { namespace vxorg {
struct VxHeavenItem { struct VxHeavenItem {
@ -12,5 +13,7 @@ namespace vxorg {
using VxHeavenTree = Tree<VxHeavenItem>; using VxHeavenTree = Tree<VxHeavenItem>;
std::string get_sample_name(VxHeavenTree::Node* node);
void parse_into_tree(VxHeavenTree& tree, std::istream& is); void parse_into_tree(VxHeavenTree& tree, std::istream& is);
} } // namespace vxorg

View file

@ -1,15 +1,12 @@
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <ranges>
#include <string> #include <string>
#include <string_view>
#include <vector>
#include "tree.hpp" #include "tree.hpp"
#include "vxheaven_parse.hpp" #include "vxheaven_parse.hpp"
int main() { int main() {
std::ifstream ifs("./samples.sort"); std::ifstream ifs("./testdata/samples.sort");
vxorg::VxHeavenTree tree; vxorg::VxHeavenTree tree;
vxorg::parse_into_tree(tree, ifs); vxorg::parse_into_tree(tree, ifs);
@ -26,26 +23,8 @@ int main() {
std::printf("(root)\n"); std::printf("(root)\n");
} else { } else {
if(data.is_sample) { if(data.is_sample) {
std::string sample_name {}; std::string sample_name = vxorg::get_sample_name(node);
std::vector<vxorg::VxHeavenItem*> parent_list {};
vxorg::VxHeavenTree::Node* parent = node->parent_node();
while(parent) {
if(parent->data().name.empty())
break;
parent_list.push_back(&parent->data());
parent = parent->parent_node();
}
for(auto& item : std::views::reverse(parent_list)) {
sample_name += std::format("{}.", item->name);
}
sample_name += data.name;
std::printf("%s (sample %s)\n", data.name.c_str(), sample_name.c_str()); std::printf("%s (sample %s)\n", data.name.c_str(), sample_name.c_str());
} else { } else {
std::printf("%s\n", data.name.c_str()); std::printf("%s\n", data.name.c_str());
} }