From 3d5e1529c4a59b860270e80fcf0a0351d4b4b81d Mon Sep 17 00:00:00 2001 From: Matuush Date: Tue, 18 Mar 2025 14:14:20 +0100 Subject: [PATCH 01/17] Created treap implementation file --- file.hpp | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 file.hpp diff --git a/file.hpp b/file.hpp new file mode 100644 index 0000000..4c9a05c --- /dev/null +++ b/file.hpp @@ -0,0 +1,6 @@ + + +// Treap file representation +class file { + +} From 386de7a8ed140667fe1b3b92a40fa903457efd4c Mon Sep 17 00:00:00 2001 From: Matuush Date: Tue, 18 Mar 2025 14:50:38 +0100 Subject: [PATCH 02/17] Treap interface definition --- file.hpp | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/file.hpp b/file.hpp index 4c9a05c..3343a9b 100644 --- a/file.hpp +++ b/file.hpp @@ -1,6 +1,49 @@ +#include +#include +#include +using std::string; +typedef unsigned long long priority_type; +#define RAND_MAX (1 << 62) +class line; +typedef std::pair two_lines; + +class line { + priority_type priority; + string text; + line *left, *right; + +public: + line(priority_type _p, string _t) : priority(_p), text(_t) {} + + two_lines split(string s) { return two_lines(nullptr, nullptr); } + void join(line *l) {} + + void insert(line *l) {} + void remove(string s) {} + line* find(string s) { return nullptr; } +}; // Treap file representation -class file { +struct file { + line* root; -} + file() { + srand(120); + root = nullptr; + } + void insert(string s) { + line *l = new line(rand(), s); + auto two = root->split(s); + two.first->join(l); + two.first->join(two.second); + } + void remove(string s) { + auto two = root->split(s); + two.first = two.first->split(s).first; // TODO sharp split + two.first->join(two.second); + } + line* find(string s) { + return root->find(s); + } +}; From 9525d3763a215dad24eac1aeff7743cbc91063a0 Mon Sep 17 00:00:00 2001 From: Matuush Date: Tue, 18 Mar 2025 15:17:59 +0100 Subject: [PATCH 03/17] Line is represented by line number as key in treap --- file.hpp | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/file.hpp b/file.hpp index 3343a9b..5832190 100644 --- a/file.hpp +++ b/file.hpp @@ -4,12 +4,15 @@ using std::string; typedef unsigned long long priority_type; +typedef unsigned long long key_type; #define RAND_MAX (1 << 62) class line; typedef std::pair two_lines; +// Treap node representation of a line class line { priority_type priority; + key_type key; string text; line *left, *right; @@ -17,14 +20,30 @@ public: line(priority_type _p, string _t) : priority(_p), text(_t) {} two_lines split(string s) { return two_lines(nullptr, nullptr); } - void join(line *l) {} + void join(line *l) { + // Take minimum of priorities of roots + // Join subtrees + } - void insert(line *l) {} - void remove(string s) {} - line* find(string s) { return nullptr; } + line* find(key_type k) { + if(k < key) { + if(left != nullptr) + return left->find(k); + else + return nullptr; + } + else if(k > key) { + if(right != nullptr) + return right->find(k); + else + return nullptr; + } + else + return this; + } }; -// Treap file representation +// Treap representation of a file struct file { line* root; @@ -34,6 +53,12 @@ struct file { } void insert(string s) { line *l = new line(rand(), s); + + if(root == nullptr) { + root = l; + return; + } + auto two = root->split(s); two.first->join(l); two.first->join(two.second); @@ -43,7 +68,7 @@ struct file { two.first = two.first->split(s).first; // TODO sharp split two.first->join(two.second); } - line* find(string s) { - return root->find(s); + line* find(key_type k) { + return root->find(k); } }; From c1ee3d1930fb11a6c9fb0a2d864af23410fd3840 Mon Sep 17 00:00:00 2001 From: Matuush Date: Tue, 18 Mar 2025 16:26:54 +0100 Subject: [PATCH 04/17] Implemented treap operations without subtree-sizes --- file.hpp | 100 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 42 deletions(-) diff --git a/file.hpp b/file.hpp index 5832190..0c90cdd 100644 --- a/file.hpp +++ b/file.hpp @@ -3,55 +3,74 @@ #include using std::string; -typedef unsigned long long priority_type; -typedef unsigned long long key_type; +typedef unsigned long long count_type; #define RAND_MAX (1 << 62) class line; typedef std::pair two_lines; // Treap node representation of a line -class line { - priority_type priority; - key_type key; +struct line { + count_type priority, size; string text; line *left, *right; -public: - line(priority_type _p, string _t) : priority(_p), text(_t) {} - - two_lines split(string s) { return two_lines(nullptr, nullptr); } - void join(line *l) { - // Take minimum of priorities of roots - // Join subtrees - } - - line* find(key_type k) { - if(k < key) { - if(left != nullptr) - return left->find(k); - else - return nullptr; - } - else if(k > key) { - if(right != nullptr) - return right->find(k); - else - return nullptr; - } - else - return this; - } + line(count_type _p, string _t) : priority(_p), text(_t), size(-1), left(nullptr), right(nullptr) {} }; // Treap representation of a file -struct file { +class file { line* root; file() { srand(120); root = nullptr; } - void insert(string s) { + + // Split treap by k-th element + // TODO with sizes + two_lines split(line *l, count_type k) { + if(l == nullptr) return {nullptr, nullptr}; + + if(l->size <= k) { + auto two = split(l->right, k); + l->right = two.first; + return {l, two.second}; + } + else { + auto two = split(l->left, k - 1 - (l->left == nullptr ? 0 : l->left->size)); + l->left = two.second; + return {two.first, l}; + } + } + // Join two treaps + // TODO with sizes + line* join(line *a, line *b) { + if(a == nullptr) return b; + if(b == nullptr) return a; + + if(a->priority < b->priority) { + a->right = join(a->right, b); + return a; + } + else { + b->left = join(a, b->left); + return b; + } + } + line* join(two_lines two) { return join(two.first, two.second); } + +public: + line* find(line* l, count_type k) { + if(l == nullptr) return nullptr; + + if(k < l->size) + return find(l->left, k); + else if(k > l->size) + return find(l->right, k - 1 - (l->left == nullptr ? 0 : l->left->size) ); + else + return l; + } + void insert(int k, string s) { line *l = new line(rand(), s); if(root == nullptr) { @@ -59,16 +78,13 @@ struct file { return; } - auto two = root->split(s); - two.first->join(l); - two.first->join(two.second); + auto two = split(root, k); + join(two.first, l); + join(two); } - void remove(string s) { - auto two = root->split(s); - two.first = two.first->split(s).first; // TODO sharp split - two.first->join(two.second); - } - line* find(key_type k) { - return root->find(k); + void remove(count_type k) { + auto two = split(root, k); + two.first = split(two.first, k-1).first; + join(two); } }; From 7f528796c06b7fcff85523f246c9e9364606d093 Mon Sep 17 00:00:00 2001 From: Matuush Date: Fri, 28 Mar 2025 15:58:34 +0100 Subject: [PATCH 05/17] Add subtree size updating during treap join --- file.hpp | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/file.hpp b/file.hpp index 0c90cdd..d6058f7 100644 --- a/file.hpp +++ b/file.hpp @@ -14,16 +14,17 @@ struct line { string text; line *left, *right; - line(count_type _p, string _t) : priority(_p), text(_t), size(-1), left(nullptr), right(nullptr) {} + line(count_type _p, string _t) : priority(_p), text(_t), size(1), left(nullptr), right(nullptr) {} }; // Treap representation of a file class file { line* root; - file() { - srand(120); - root = nullptr; + // Get size uf a subtreap + int get_size(line* l) { + if(l == nullptr) return 0; + return l->size; } // Split treap by k-th element @@ -31,45 +32,56 @@ class file { two_lines split(line *l, count_type k) { if(l == nullptr) return {nullptr, nullptr}; - if(l->size <= k) { + if(l->size < k) { auto two = split(l->right, k); l->right = two.first; return {l, two.second}; } else { - auto two = split(l->left, k - 1 - (l->left == nullptr ? 0 : l->left->size)); + auto two = split(l->left, k - 1 - get_size(l->left)); l->left = two.second; return {two.first, l}; } } // Join two treaps - // TODO with sizes + // Hopefully with working sizes line* join(line *a, line *b) { if(a == nullptr) return b; if(b == nullptr) return a; if(a->priority < b->priority) { + a->size += b->size; a->right = join(a->right, b); return a; } else { + b->size += a->size; b->left = join(a, b->left); return b; } } line* join(two_lines two) { return join(two.first, two.second); } - -public: + // Find k-th line of file line* find(line* l, count_type k) { if(l == nullptr) return nullptr; - if(k < l->size) + if(k >= get_size(l->left)) return find(l->left, k); - else if(k > l->size) - return find(l->right, k - 1 - (l->left == nullptr ? 0 : l->left->size) ); + else if(k > l->size+1) + return find(l->right, k - 1 - get_size(l->left)); else return l; } + +public: + file() { + srand(120); + root = nullptr; + } + // Don't find index k, but k-th line -> +1 + line* find(count_type k) {return find(root, k+1);} + + // File access void insert(int k, string s) { line *l = new line(rand(), s); @@ -82,6 +94,7 @@ public: join(two.first, l); join(two); } + // Line removal void remove(count_type k) { auto two = split(root, k); two.first = split(two.first, k-1).first; From 02bdb353a4a2ca52946b86da45f03e5009df08c9 Mon Sep 17 00:00:00 2001 From: Matuush Date: Fri, 28 Mar 2025 16:16:47 +0100 Subject: [PATCH 06/17] Add subtree size updating during treap split --- file.hpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/file.hpp b/file.hpp index d6058f7..b1bd35b 100644 --- a/file.hpp +++ b/file.hpp @@ -28,19 +28,21 @@ class file { } // Split treap by k-th element - // TODO with sizes + // Hopefully with sizes two_lines split(line *l, count_type k) { if(l == nullptr) return {nullptr, nullptr}; - if(l->size < k) { - auto two = split(l->right, k); - l->right = two.first; - return {l, two.second}; + if(get_size(l->left) > k) { + // In the left subtree + auto two = split(l->left, k); + l->size -= two.first->size; + return {two.first, l}; } else { - auto two = split(l->left, k - 1 - get_size(l->left)); - l->left = two.second; - return {two.first, l}; + // In the right subtree + auto two = split(l->right, k - (1+get_size(l->left))); + l->size -= two.second->size; + return {l, two.second}; } } // Join two treaps @@ -68,7 +70,7 @@ class file { if(k >= get_size(l->left)) return find(l->left, k); else if(k > l->size+1) - return find(l->right, k - 1 - get_size(l->left)); + return find(l->right, k - (1+get_size(l->left)) ); else return l; } @@ -79,7 +81,11 @@ public: root = nullptr; } // Don't find index k, but k-th line -> +1 - line* find(count_type k) {return find(root, k+1);} + line* find(count_type k) { + if(k >= root->size) + return nullptr; + return find(root, k+1); + } // File access void insert(int k, string s) { From 32fecc75ecf504ea4febca5d0aaa2ea5c42baf69 Mon Sep 17 00:00:00 2001 From: Matuush Date: Fri, 28 Mar 2025 16:23:40 +0100 Subject: [PATCH 07/17] Fix subtree size accessing --- file.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/file.hpp b/file.hpp index b1bd35b..ae34101 100644 --- a/file.hpp +++ b/file.hpp @@ -4,7 +4,6 @@ using std::string; typedef unsigned long long count_type; -#define RAND_MAX (1 << 62) class line; typedef std::pair two_lines; @@ -35,13 +34,13 @@ class file { if(get_size(l->left) > k) { // In the left subtree auto two = split(l->left, k); - l->size -= two.first->size; + l->size -= get_size(two.first); return {two.first, l}; } else { // In the right subtree auto two = split(l->right, k - (1+get_size(l->left))); - l->size -= two.second->size; + l->size -= get_size(two.second); return {l, two.second}; } } @@ -80,6 +79,7 @@ public: srand(120); root = nullptr; } + // File access // Don't find index k, but k-th line -> +1 line* find(count_type k) { if(k >= root->size) @@ -87,7 +87,7 @@ public: return find(root, k+1); } - // File access + // Line insert void insert(int k, string s) { line *l = new line(rand(), s); From 1e1a147116d77f1b0eea98da45533316eef3cb27 Mon Sep 17 00:00:00 2001 From: Matuush Date: Fri, 28 Mar 2025 16:37:45 +0100 Subject: [PATCH 08/17] Fix line finding --- file.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/file.hpp b/file.hpp index ae34101..0eaac96 100644 --- a/file.hpp +++ b/file.hpp @@ -18,6 +18,7 @@ struct line { // Treap representation of a file class file { +public: line* root; // Get size uf a subtreap @@ -66,12 +67,12 @@ class file { line* find(line* l, count_type k) { if(l == nullptr) return nullptr; - if(k >= get_size(l->left)) + if(k <= get_size(l->left)) return find(l->left, k); - else if(k > l->size+1) - return find(l->right, k - (1+get_size(l->left)) ); - else + else if(k == get_size(l->left)+1) return l; + else + return find(l->right, k - (1+get_size(l->left)) ); } public: @@ -97,7 +98,7 @@ public: } auto two = split(root, k); - join(two.first, l); + two.first = join(two.first, l); join(two); } // Line removal From d6e22b641b93d3611d7709e1ca64b6f4d8c48568 Mon Sep 17 00:00:00 2001 From: Matuush Date: Fri, 28 Mar 2025 16:52:19 +0100 Subject: [PATCH 09/17] Made treap size comparisons inclusive --- file.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/file.hpp b/file.hpp index 0eaac96..dd44f23 100644 --- a/file.hpp +++ b/file.hpp @@ -32,7 +32,7 @@ public: two_lines split(line *l, count_type k) { if(l == nullptr) return {nullptr, nullptr}; - if(get_size(l->left) > k) { + if(get_size(l->left) >= k) { // In the left subtree auto two = split(l->left, k); l->size -= get_size(two.first); @@ -45,6 +45,7 @@ public: return {l, two.second}; } } + // Join two treaps // Hopefully with working sizes line* join(line *a, line *b) { @@ -63,6 +64,7 @@ public: } } line* join(two_lines two) { return join(two.first, two.second); } + // Find k-th line of file line* find(line* l, count_type k) { if(l == nullptr) return nullptr; From ec1d64e9ba9048dc12b71a84ac9835024b4e2c2d Mon Sep 17 00:00:00 2001 From: Matuush Date: Fri, 28 Mar 2025 17:00:26 +0100 Subject: [PATCH 10/17] Use defined function for getting subtree size --- file.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/file.hpp b/file.hpp index dd44f23..755aa8b 100644 --- a/file.hpp +++ b/file.hpp @@ -53,12 +53,12 @@ public: if(b == nullptr) return a; if(a->priority < b->priority) { - a->size += b->size; + a->size += get_size(b); a->right = join(a->right, b); return a; } else { - b->size += a->size; + b->size += get_size(a); b->left = join(a, b->left); return b; } From 734588316db662772c2878f37ab8cf567c248a2d Mon Sep 17 00:00:00 2001 From: Matuush Date: Fri, 28 Mar 2025 18:17:13 +0100 Subject: [PATCH 11/17] Refactor comments and typedef --- file.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/file.hpp b/file.hpp index 755aa8b..1128ac1 100644 --- a/file.hpp +++ b/file.hpp @@ -4,8 +4,6 @@ using std::string; typedef unsigned long long count_type; -class line; -typedef std::pair two_lines; // Treap node representation of a line struct line { @@ -15,6 +13,7 @@ struct line { line(count_type _p, string _t) : priority(_p), text(_t), size(1), left(nullptr), right(nullptr) {} }; +typedef std::pair two_lines; // Treap representation of a file class file { @@ -83,10 +82,10 @@ public: root = nullptr; } // File access - // Don't find index k, but k-th line -> +1 line* find(count_type k) { if(k >= root->size) return nullptr; + // Don't find index k, but k-th line -> +1 return find(root, k+1); } From e5bed9f8fe174893deba7d6c4fffc234762c16d5 Mon Sep 17 00:00:00 2001 From: Matuush Date: Fri, 28 Mar 2025 18:17:43 +0100 Subject: [PATCH 12/17] Correct some mistakes in treap functions --- file.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/file.hpp b/file.hpp index 1128ac1..060908c 100644 --- a/file.hpp +++ b/file.hpp @@ -30,16 +30,19 @@ public: // Hopefully with sizes two_lines split(line *l, count_type k) { if(l == nullptr) return {nullptr, nullptr}; + // TODO ??????? sizes dont add up if(get_size(l->left) >= k) { // In the left subtree auto two = split(l->left, k); + l->left = two.second; l->size -= get_size(two.first); return {two.first, l}; } else { // In the right subtree auto two = split(l->right, k - (1+get_size(l->left))); + l->right = two.first; l->size -= get_size(two.second); return {l, two.second}; } @@ -104,8 +107,8 @@ public: } // Line removal void remove(count_type k) { - auto two = split(root, k); - two.first = split(two.first, k-1).first; + auto two = split(root, k+1); + two.first = split(two.first, k).first; join(two); } }; From 1582e7e7cb9a63629fd9747fa0e4873d4a0459c0 Mon Sep 17 00:00:00 2001 From: Matuush Date: Sun, 30 Mar 2025 17:01:40 +0200 Subject: [PATCH 13/17] Update treap root on insert --- file.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/file.hpp b/file.hpp index 060908c..e7c2381 100644 --- a/file.hpp +++ b/file.hpp @@ -30,7 +30,6 @@ public: // Hopefully with sizes two_lines split(line *l, count_type k) { if(l == nullptr) return {nullptr, nullptr}; - // TODO ??????? sizes dont add up if(get_size(l->left) >= k) { // In the left subtree @@ -103,12 +102,12 @@ public: auto two = split(root, k); two.first = join(two.first, l); - join(two); + root = join(two); } // Line removal void remove(count_type k) { auto two = split(root, k+1); two.first = split(two.first, k).first; - join(two); + root = join(two); } }; From 17237e1cb39fdc095e83237733317a6ae8c4e6ee Mon Sep 17 00:00:00 2001 From: Matuush Date: Sun, 30 Mar 2025 17:05:01 +0200 Subject: [PATCH 14/17] Rename file representation to treap for better readability --- file.hpp => treap.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename file.hpp => treap.hpp (98%) diff --git a/file.hpp b/treap.hpp similarity index 98% rename from file.hpp rename to treap.hpp index e7c2381..bbc5ec5 100644 --- a/file.hpp +++ b/treap.hpp @@ -16,7 +16,7 @@ struct line { typedef std::pair two_lines; // Treap representation of a file -class file { +class treap { public: line* root; @@ -79,7 +79,7 @@ public: } public: - file() { + treap() { srand(120); root = nullptr; } From 875a0761c90a52d074aba038f7810a254c65f80e Mon Sep 17 00:00:00 2001 From: Matuush Date: Sun, 30 Mar 2025 17:06:49 +0200 Subject: [PATCH 15/17] Encapsulate treap properties --- treap.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/treap.hpp b/treap.hpp index bbc5ec5..98c287a 100644 --- a/treap.hpp +++ b/treap.hpp @@ -17,7 +17,6 @@ typedef std::pair two_lines; // Treap representation of a file class treap { -public: line* root; // Get size uf a subtreap From ef426253caef0a20b751f6668cc240698ebbf6cb Mon Sep 17 00:00:00 2001 From: Matuush Date: Mon, 31 Mar 2025 19:55:16 +0200 Subject: [PATCH 16/17] Provide heap size outside --- treap.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/treap.hpp b/treap.hpp index 98c287a..2f14e46 100644 --- a/treap.hpp +++ b/treap.hpp @@ -109,4 +109,7 @@ public: two.first = split(two.first, k).first; root = join(two); } + count_type size() { + return get_size(root); + } }; From 179c7ce9bdee67af95cd2db1d057ca680513208b Mon Sep 17 00:00:00 2001 From: Matuush Date: Mon, 31 Mar 2025 20:13:26 +0200 Subject: [PATCH 17/17] Integrate treap into the code --- main.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/main.cpp b/main.cpp index 45e3e41..1f06cd5 100644 --- a/main.cpp +++ b/main.cpp @@ -4,6 +4,8 @@ #include #include +#include "treap.hpp" + using std::string; using std::vector; @@ -12,15 +14,16 @@ enum mode_type { insert, normal }; // Global variables -vector file(0); +treap file; int row = 0, col = 0; // Accessing the file -char get(int r, int s) { return file[r][s]; } -void set(int r, int s, char ch) { file[r][s] = ch; } -string get_line(int r) { return file[r]; } -void add_line(int r) { file.insert(file.begin() + r, ""); } -void remove_line(int r) { file.erase(file.begin() + r); } +string get_line(int r) { return file.find(r)->text; } +char get(int r, int s) { return get_line(r)[s]; } +void set(int r, int s, char ch) { file.find(r)->text[s] = ch; } +void add_line(int r, string text = "") { file.insert(r, text); } +void remove_line(int r) { file.remove(r); } + // For normal mode not to write to terminal void step_back() { @@ -36,9 +39,10 @@ bool load(string filename) { std::ifstream infile(filename); if(!infile.good()) return 1; + string line; while (std::getline(infile, line)) - file.push_back(line); + file.insert(file.size(), line); return 0; } @@ -47,8 +51,8 @@ bool save(string filename) { std::ofstream outfile(filename); if(!outfile.good()) return 1; - for(string line : file) - outfile << line << std::endl; + for(int i = 0; i < file.size(); ++i) + outfile << get_line(i) << std::endl; return 0; } @@ -57,7 +61,7 @@ void print_file() { clear(); for(int i = 0; i < file.size(); i++) { move(i, 0); - adds(file[i]); + adds(get_line(i)); } move(row, col); } @@ -102,7 +106,7 @@ void move_cursor(char ch) { break; case 'l': - if(col < file[row].size()) + if(col < get_line(row).size()) move(row, ++col); break; }