diff --git a/02-splay_operation/cpp/Makefile b/02-splay_operation/cpp/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4ca82749b82280d73f3eb750ae3167fa1fbafd4f --- /dev/null +++ b/02-splay_operation/cpp/Makefile @@ -0,0 +1,12 @@ +test: splay_operation_test + ./$< + +CXXFLAGS=-std=c++11 -O2 -Wall -Wextra -g -Wno-sign-compare + +splay_operation_test: splay_operation.h splay_operation_test.cpp test_main.cpp + $(CXX) $(CXXFLAGS) $^ -o $@ + +clean:: + rm -f splay_operation_test + +.PHONY: clean test diff --git a/02-splay_operation/cpp/splay_operation.h b/02-splay_operation/cpp/splay_operation.h new file mode 100644 index 0000000000000000000000000000000000000000..249f3dd7222ad3e3ce3870f478f91a9bf85bcab4 --- /dev/null +++ b/02-splay_operation/cpp/splay_operation.h @@ -0,0 +1,158 @@ +// A node of the tree +class Node { + public: + int key; + Node* left; + Node* right; + Node* parent; + + // Constructor + Node(int key, Node* parent=nullptr, Node* left=nullptr, Node* right=nullptr) { + this->key = key; + this->parent = parent; + this->left = left; + this->right = right; + if (left) left->parent = this; + if (right) right->parent = this; + } +}; + +// Binary tree +class Tree { + public: + // Pointer to root of the tree; nullptr if the tree is empty. + Node* root; + + Tree(Node* root=nullptr) { + this->root = root; + } + + // Rotate the given `node` up. Perform a single rotation of the edge + // between the node and its parent, choosing left or right rotation + // appropriately. + virtual void rotate(Node* node) { + if (node->parent) { + if (node->parent->left == node) { + if (node->right) node->right->parent = node->parent; + node->parent->left = node->right; + node->right = node->parent; + } else { + if (node->left) node->left->parent = node->parent; + node->parent->right = node->left; + node->left = node->parent; + } + if (node->parent->parent) { + if (node->parent->parent->left == node->parent) + node->parent->parent->left = node; + else + node->parent->parent->right = node; + } else { + root = node; + } + + Node* original_parent = node->parent; + node->parent = node->parent->parent; + original_parent->parent = node; + } + } + + // Look up the given key in the tree, returning the + // the node with the requested key or nullptr. + Node* lookup(int key) { + // TODO: Utilize splay suitably. + Node* node = root; + while (node) { + if (node->key == key) { + return node; + } + if (key < node->key) + node = node->left; + else + node = node->right; + } + return nullptr; + } + + // Insert a key into the tree. + // If the key is already present, nothing happens. + void insert(int key) { + // TODO: Utilize splay suitably. + if (!root) { + root = new Node(key); + return; + } + + Node* node = root; + while (node->key != key) { + if (key < node->key) { + if (!node->left) + node->left = new Node(key, node); + node = node->left; + } else { + if (!node->right) + node->right = new Node(key, node); + node = node->right; + } + } + } + + // Delete given key from the tree. + // It the key is not present, nothing happens. + void remove(int key) { + // TODO: Utilize splay suitably. + Node* node = root; + while (node && node->key != key) { + if (key < node->key) + node = node->left; + else + node = node->right; + } + + if (node) { + if (node->left && node->right) { + Node* replacement = node->right; + while (replacement->left) + replacement = replacement->left; + node->key = replacement->key; + node = replacement; + } + + Node* replacement = node->left ? node->left : node->right; + if (node->parent) { + if (node->parent->left == node) node->parent->left = replacement; + else node->parent->right = replacement; + } else { + root = replacement; + } + if (replacement) + replacement->parent = node->parent; + delete node; + } + } + + // Splay the given node. + // If a single rotation needs to be performed, perform it as the last rotation + // (i.e., to move the splayed node to the root of the tree). + virtual void splay(Node* node) { + // TODO: Implement + } + + // Destructor to free all allocated memory. + ~Tree() { + Node* node = root; + while (node) { + Node* next; + if (node->left) { + next = node->left; + node->left = nullptr; + } else if (node->right) { + next = node->right; + node->right = nullptr; + } else { + next = node->parent; + delete node; + } + node = next; + } + } +}; diff --git a/02-splay_operation/cpp/splay_operation_test.cpp b/02-splay_operation/cpp/splay_operation_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d1e6c996b56b28dd37db3d85ddd7d817c82269b9 --- /dev/null +++ b/02-splay_operation/cpp/splay_operation_test.cpp @@ -0,0 +1,192 @@ +#include <algorithm> +#include <cassert> +#include <fstream> +#include <functional> +#include <string> +#include <utility> +#include <vector> + +#include "splay_operation.h" + +using namespace std; + +// If the condition is not true, report an error and halt. +#define EXPECT(condition, message) do { if (!(condition)) expect_failed(message); } while (0) +void expect_failed(const string& message); + +// Flatten the tree: return a sorted list of all keys in the tree. +vector<int> flatten(const Tree& tree) { + constexpr int L = 0, R = 1, F = 2; + + Node* node = tree.root; + vector<int> flattened, stack = {L}; + while (!stack.empty()) { + if (stack.back() == L) { + stack.back() = R; + if (node->left) { + node = node->left; + stack.push_back(L); + } + } else if (stack.back() == R) { + flattened.push_back(node->key); + stack.back() = F; + if (node->right) { + node = node->right; + stack.push_back(L); + } + } else { + node = node->parent; + stack.pop_back(); + } + } + return flattened; +} + +// Test for splay operation with required helpers +class TestSplay { + public: + static Node* deserialize_node(const string& text, int& index) { + EXPECT(text[index++] == '(', "Internal error during example deserialization"); + if (text[index] == ')') { + index++; + return nullptr; + } else { + int comma = text.find(',', index); + int key = stoi(text.substr(index, comma - index)); + Node* left = deserialize_node(text, (index=comma + 1)); + Node* right = deserialize_node(text, ++index); + EXPECT(text[index++] == ')', "Internal error during example deserialization"); + return new Node(key, nullptr, left, right); + } + } + + static Node* deserialize_root(const string& text) { + int index = 0; + Node* root = deserialize_node(text, index); + assert(index == text.size()); + return root; + } + + static string compare(Node* system, Node* gold) { + if (!system && gold) { + return "expected node with key " + to_string(gold->key) + ", found None"; + } else if (system && !gold) { + return "expected None, found node with key " + to_string(system->key); + } else if (system && gold) { + if (system->key != gold->key) + return "expected node with key " + to_string(gold->key) + ", found " + to_string(system->key); + auto result = compare(system->left, gold->left); + if (!result.empty()) return result; + return compare(system->right, gold->right); + } + return string(); + } + + static void test() { + ifstream splay_tests_file("splay_tests.txt"); + EXPECT(splay_tests_file.is_open(), "Cannot open splay_tests.txt file with the tests"); + + string original, splayed; + int target; + while (splay_tests_file >> original >> target >> splayed) { + Tree original_tree(deserialize_root(original)); + Tree splayed_tree(deserialize_root(splayed)); + + Node* target_node = original_tree.root; + while (target_node && target_node->key != target) + if (target < target_node->key) + target_node = target_node->left; + else + target_node = target_node->right; + EXPECT(target_node, "Internal error during finding the target node in the tree to splay"); + + original_tree.splay(target_node); + auto error = compare(original_tree.root, splayed_tree.root); + EXPECT(error.empty(), "Error running splay on key " + to_string(target) + " of " + original + ": " + error); + } + } +}; + +void test_lookup() { + // Insert even numbers + Tree tree; + for (int i = 0; i < 5000000; i += 2) + tree.insert(i); + + // Find non-existing + for (int i = 1; i < 5000000; i += 2) + for (int j = 0; j < 10; j++) + EXPECT(!tree.lookup(i), "Non-existing element was found"); + + // Find existing + for (int i = 0; i < 5000000; i += 2) + for (int j = 0; j < 10; j++) + EXPECT(tree.lookup(i), "Existing element was not found"); +} + +void test_insert() { + // Test validity first + { + Tree tree; + vector<int> sequence = {997}; + for (int i = 2; i < 1999; i++) + sequence.push_back((sequence.back() * sequence.front()) % 1999); + for (const auto& i : sequence) + tree.insert(i); + + vector<int> flattened = flatten(tree); + sort(sequence.begin(), sequence.end()); + EXPECT(flattened == sequence, "Incorrect tree after a sequence of inserts"); + } + + // Test speed + { + Tree tree; + for (int i = 0; i < 5000000; i++) + for (int j = 0; j < 10; j++) + tree.insert(i); + } +} + +void test_remove() { + // Test validity first + { + Tree tree; + for (int i = 2; i < 1999 * 2; i++) + tree.insert(i); + + vector<int> sequence = {2 * 997}; + for (int i = 2; i < 1999; i++) + sequence.push_back(2 * ((sequence.back() * sequence.front() / 4) % 1999)); + for (const auto& i : sequence) + tree.remove(i + 1); + + vector<int> flattened = flatten(tree); + sort(sequence.begin(), sequence.end()); + EXPECT(flattened == sequence, "Correct tree after a sequence of removes"); + } + + // Test speed + { + Tree tree; + for (int i = 0; i < 5000000; i++) + tree.insert(i); + + // Non-existing elements + for (int i = 1; i < 5000000; i += 2) + for (int j = 0; j < 10; j++) + tree.remove(i); + + // Existing elements + for (int i = 2; i < 5000000; i += 2) + for (int j = 0; j < 10; j++) + tree.remove(i); + } +} + +vector<pair<string, function<void()>>> tests = { + { "splay", TestSplay::test }, + { "lookup", test_lookup }, + { "insert", test_insert }, + { "remove", test_remove }, +}; diff --git a/02-splay_operation/cpp/splay_tests.txt b/02-splay_operation/cpp/splay_tests.txt new file mode 100644 index 0000000000000000000000000000000000000000..7f3259e5d6a4689f8e7cc608e450905b82647b7b --- /dev/null +++ b/02-splay_operation/cpp/splay_tests.txt @@ -0,0 +1,62 @@ +(3,(1,(0,(),()),(2,(),())),(4,(),())) 4 (4,(3,(1,(0,(),()),(2,(),())),()),()) +(6,(5,(),()),(8,(7,(),()),(9,(),()))) 5 (5,(),(6,(),(8,(7,(),()),(9,(),())))) +(3,(1,(0,(),()),(2,(),())),(7,(5,(4,(),()),(6,(),())),(8,(),()))) 8 (8,(7,(3,(1,(0,(),()),(2,(),())),(5,(4,(),()),(6,(),()))),()),()) +(11,(9,(7,(6,(),()),(8,(),())),(10,(),())),(13,(12,(),()),(14,(),()))) 10 (10,(9,(7,(6,(),()),(8,(),())),()),(11,(),(13,(12,(),()),(14,(),())))) +(8,(6,(5,(),()),(7,(),())),(10,(9,(),()),(12,(11,(),()),(13,(),())))) 9 (9,(8,(6,(5,(),()),(7,(),())),()),(10,(),(12,(11,(),()),(13,(),())))) +(16,(12,(11,(),()),(14,(13,(),()),(15,(),()))),(18,(17,(),()),(19,(),()))) 11 (11,(),(12,(),(16,(14,(13,(),()),(15,(),())),(18,(17,(),()),(19,(),()))))) +(3,(1,(0,(),()),(2,(),())),(7,(5,(4,(),()),(6,(),())),(11,(9,(8,(),()),(10,(),())),(12,(),())))) 12 (12,(3,(1,(0,(),()),(2,(),())),(11,(7,(5,(4,(),()),(6,(),())),(9,(8,(),()),(10,(),()))),())),()) +(17,(11,(9,(8,(),()),(10,(),())),(15,(13,(12,(),()),(14,(),())),(16,(),()))),(19,(18,(),()),(20,(),()))) 16 (16,(15,(11,(9,(8,(),()),(10,(),())),(13,(12,(),()),(14,(),()))),()),(17,(),(19,(18,(),()),(20,(),())))) +(9,(7,(6,(),()),(8,(),())),(15,(13,(11,(10,(),()),(12,(),())),(14,(),())),(17,(16,(),()),(18,(),())))) 14 (14,(9,(7,(6,(),()),(8,(),())),(13,(11,(10,(),()),(12,(),())),())),(15,(),(17,(16,(),()),(18,(),())))) +(23,(19,(17,(15,(14,(),()),(16,(),())),(18,(),())),(21,(20,(),()),(22,(),()))),(25,(24,(),()),(26,(),()))) 18 (18,(17,(15,(14,(),()),(16,(),())),()),(23,(19,(),(21,(20,(),()),(22,(),()))),(25,(24,(),()),(26,(),())))) +(8,(6,(5,(),()),(7,(),())),(12,(10,(9,(),()),(11,(),())),(14,(13,(),()),(16,(15,(),()),(17,(),()))))) 13 (13,(8,(6,(5,(),()),(7,(),())),(12,(10,(9,(),()),(11,(),())),())),(14,(),(16,(15,(),()),(17,(),())))) +(22,(16,(14,(13,(),()),(15,(),())),(18,(17,(),()),(20,(19,(),()),(21,(),())))),(24,(23,(),()),(25,(),()))) 17 (17,(16,(14,(13,(),()),(15,(),())),()),(22,(18,(),(20,(19,(),()),(21,(),()))),(24,(23,(),()),(25,(),())))) +(14,(12,(11,(),()),(13,(),())),(20,(16,(15,(),()),(18,(17,(),()),(19,(),()))),(22,(21,(),()),(23,(),())))) 15 (15,(14,(12,(11,(),()),(13,(),())),()),(16,(),(20,(18,(17,(),()),(19,(),())),(22,(21,(),()),(23,(),()))))) +(28,(24,(20,(19,(),()),(22,(21,(),()),(23,(),()))),(26,(25,(),()),(27,(),()))),(30,(29,(),()),(31,(),()))) 19 (19,(),(28,(20,(),(24,(22,(21,(),()),(23,(),())),(26,(25,(),()),(27,(),())))),(30,(29,(),()),(31,(),())))) +(3,(1,(0,(),()),(2,(),())),(7,(5,(4,(),()),(6,(),())),(11,(9,(8,(),()),(10,(),())),(15,(13,(12,(),()),(14,(),())),(16,(),()))))) 16 (16,(7,(3,(1,(0,(),()),(2,(),())),(5,(4,(),()),(6,(),()))),(15,(11,(9,(8,(),()),(10,(),())),(13,(12,(),()),(14,(),()))),())),()) +(25,(15,(13,(12,(),()),(14,(),())),(19,(17,(16,(),()),(18,(),())),(23,(21,(20,(),()),(22,(),())),(24,(),())))),(27,(26,(),()),(28,(),()))) 24 (24,(15,(13,(12,(),()),(14,(),())),(23,(19,(17,(16,(),()),(18,(),())),(21,(20,(),()),(22,(),()))),())),(25,(),(27,(26,(),()),(28,(),())))) +(11,(9,(8,(),()),(10,(),())),(21,(15,(13,(12,(),()),(14,(),())),(19,(17,(16,(),()),(18,(),())),(20,(),()))),(23,(22,(),()),(24,(),())))) 20 (20,(11,(9,(8,(),()),(10,(),())),(19,(15,(13,(12,(),()),(14,(),())),(17,(16,(),()),(18,(),()))),())),(21,(),(23,(22,(),()),(24,(),())))) +(33,(29,(23,(21,(20,(),()),(22,(),())),(27,(25,(24,(),()),(26,(),())),(28,(),()))),(31,(30,(),()),(32,(),()))),(35,(34,(),()),(36,(),()))) 28 (28,(27,(23,(21,(20,(),()),(22,(),())),(25,(24,(),()),(26,(),()))),()),(29,(),(33,(31,(30,(),()),(32,(),())),(35,(34,(),()),(36,(),()))))) +(9,(7,(6,(),()),(8,(),())),(13,(11,(10,(),()),(12,(),())),(19,(17,(15,(14,(),()),(16,(),())),(18,(),())),(21,(20,(),()),(22,(),()))))) 18 (18,(13,(9,(7,(6,(),()),(8,(),())),(11,(10,(),()),(12,(),()))),(17,(15,(14,(),()),(16,(),())),())),(19,(),(21,(20,(),()),(22,(),())))) +(31,(21,(19,(18,(),()),(20,(),())),(27,(25,(23,(22,(),()),(24,(),())),(26,(),())),(29,(28,(),()),(30,(),())))),(33,(32,(),()),(34,(),()))) 26 (26,(21,(19,(18,(),()),(20,(),())),(25,(23,(22,(),()),(24,(),())),())),(31,(27,(),(29,(28,(),()),(30,(),()))),(33,(32,(),()),(34,(),())))) +(17,(15,(14,(),()),(16,(),())),(27,(23,(21,(19,(18,(),()),(20,(),())),(22,(),())),(25,(24,(),()),(26,(),()))),(29,(28,(),()),(30,(),())))) 22 (22,(17,(15,(14,(),()),(16,(),())),(21,(19,(18,(),()),(20,(),())),())),(27,(23,(),(25,(24,(),()),(26,(),()))),(29,(28,(),()),(30,(),())))) +(39,(35,(31,(29,(27,(26,(),()),(28,(),())),(30,(),())),(33,(32,(),()),(34,(),()))),(37,(36,(),()),(38,(),()))),(41,(40,(),()),(42,(),()))) 30 (30,(29,(27,(26,(),()),(28,(),())),()),(35,(31,(),(33,(32,(),()),(34,(),()))),(39,(37,(36,(),()),(38,(),())),(41,(40,(),()),(42,(),()))))) +(8,(6,(5,(),()),(7,(),())),(12,(10,(9,(),()),(11,(),())),(16,(14,(13,(),()),(15,(),())),(18,(17,(),()),(20,(19,(),()),(21,(),())))))) 17 (17,(12,(8,(6,(5,(),()),(7,(),())),(10,(9,(),()),(11,(),()))),(16,(14,(13,(),()),(15,(),())),())),(18,(),(20,(19,(),()),(21,(),())))) +(30,(20,(18,(17,(),()),(19,(),())),(24,(22,(21,(),()),(23,(),())),(26,(25,(),()),(28,(27,(),()),(29,(),()))))),(32,(31,(),()),(33,(),()))) 25 (25,(20,(18,(17,(),()),(19,(),())),(24,(22,(21,(),()),(23,(),())),())),(30,(26,(),(28,(27,(),()),(29,(),()))),(32,(31,(),()),(33,(),())))) +(16,(14,(13,(),()),(15,(),())),(26,(20,(18,(17,(),()),(19,(),())),(22,(21,(),()),(24,(23,(),()),(25,(),())))),(28,(27,(),()),(29,(),())))) 21 (21,(16,(14,(13,(),()),(15,(),())),(20,(18,(17,(),()),(19,(),())),())),(26,(22,(),(24,(23,(),()),(25,(),()))),(28,(27,(),()),(29,(),())))) +(38,(34,(28,(26,(25,(),()),(27,(),())),(30,(29,(),()),(32,(31,(),()),(33,(),())))),(36,(35,(),()),(37,(),()))),(40,(39,(),()),(41,(),()))) 29 (29,(28,(26,(25,(),()),(27,(),())),()),(34,(30,(),(32,(31,(),()),(33,(),()))),(38,(36,(35,(),()),(37,(),())),(40,(39,(),()),(41,(),()))))) +(14,(12,(11,(),()),(13,(),())),(18,(16,(15,(),()),(17,(),())),(24,(20,(19,(),()),(22,(21,(),()),(23,(),()))),(26,(25,(),()),(27,(),()))))) 19 (19,(18,(14,(12,(11,(),()),(13,(),())),(16,(15,(),()),(17,(),()))),()),(20,(),(24,(22,(21,(),()),(23,(),())),(26,(25,(),()),(27,(),()))))) +(36,(26,(24,(23,(),()),(25,(),())),(32,(28,(27,(),()),(30,(29,(),()),(31,(),()))),(34,(33,(),()),(35,(),())))),(38,(37,(),()),(39,(),()))) 27 (27,(26,(24,(23,(),()),(25,(),())),()),(36,(28,(),(32,(30,(29,(),()),(31,(),())),(34,(33,(),()),(35,(),())))),(38,(37,(),()),(39,(),())))) +(22,(20,(19,(),()),(21,(),())),(32,(28,(24,(23,(),()),(26,(25,(),()),(27,(),()))),(30,(29,(),()),(31,(),()))),(34,(33,(),()),(35,(),())))) 23 (23,(22,(20,(19,(),()),(21,(),())),()),(32,(24,(),(28,(26,(25,(),()),(27,(),())),(30,(29,(),()),(31,(),())))),(34,(33,(),()),(35,(),())))) +(44,(40,(36,(32,(31,(),()),(34,(33,(),()),(35,(),()))),(38,(37,(),()),(39,(),()))),(42,(41,(),()),(43,(),()))),(46,(45,(),()),(47,(),()))) 31 (31,(),(40,(32,(),(36,(34,(33,(),()),(35,(),())),(38,(37,(),()),(39,(),())))),(44,(42,(41,(),()),(43,(),())),(46,(45,(),()),(47,(),()))))) +(3,(1,(0,(),()),(2,(),())),(7,(5,(4,(),()),(6,(),())),(11,(9,(8,(),()),(10,(),())),(15,(13,(12,(),()),(14,(),())),(19,(17,(16,(),()),(18,(),())),(20,(),())))))) 20 (20,(3,(1,(0,(),()),(2,(),())),(11,(7,(5,(4,(),()),(6,(),())),(9,(8,(),()),(10,(),()))),(19,(15,(13,(12,(),()),(14,(),())),(17,(16,(),()),(18,(),()))),()))),()) +(37,(23,(21,(20,(),()),(22,(),())),(27,(25,(24,(),()),(26,(),())),(31,(29,(28,(),()),(30,(),())),(35,(33,(32,(),()),(34,(),())),(36,(),()))))),(39,(38,(),()),(40,(),()))) 36 (36,(27,(23,(21,(20,(),()),(22,(),())),(25,(24,(),()),(26,(),()))),(35,(31,(29,(28,(),()),(30,(),())),(33,(32,(),()),(34,(),()))),())),(37,(),(39,(38,(),()),(40,(),())))) +(15,(13,(12,(),()),(14,(),())),(29,(19,(17,(16,(),()),(18,(),())),(23,(21,(20,(),()),(22,(),())),(27,(25,(24,(),()),(26,(),())),(28,(),())))),(31,(30,(),()),(32,(),())))) 28 (28,(15,(13,(12,(),()),(14,(),())),(19,(17,(16,(),()),(18,(),())),(27,(23,(21,(20,(),()),(22,(),())),(25,(24,(),()),(26,(),()))),()))),(29,(),(31,(30,(),()),(32,(),())))) +(49,(45,(35,(33,(32,(),()),(34,(),())),(39,(37,(36,(),()),(38,(),())),(43,(41,(40,(),()),(42,(),())),(44,(),())))),(47,(46,(),()),(48,(),()))),(51,(50,(),()),(52,(),()))) 44 (44,(35,(33,(32,(),()),(34,(),())),(43,(39,(37,(36,(),()),(38,(),())),(41,(40,(),()),(42,(),()))),())),(49,(45,(),(47,(46,(),()),(48,(),()))),(51,(50,(),()),(52,(),())))) +(11,(9,(8,(),()),(10,(),())),(15,(13,(12,(),()),(14,(),())),(25,(19,(17,(16,(),()),(18,(),())),(23,(21,(20,(),()),(22,(),())),(24,(),()))),(27,(26,(),()),(28,(),()))))) 24 (24,(11,(9,(8,(),()),(10,(),())),(15,(13,(12,(),()),(14,(),())),(23,(19,(17,(16,(),()),(18,(),())),(21,(20,(),()),(22,(),()))),()))),(25,(),(27,(26,(),()),(28,(),())))) +(45,(31,(29,(28,(),()),(30,(),())),(41,(35,(33,(32,(),()),(34,(),())),(39,(37,(36,(),()),(38,(),())),(40,(),()))),(43,(42,(),()),(44,(),())))),(47,(46,(),()),(48,(),()))) 40 (40,(31,(29,(28,(),()),(30,(),())),(39,(35,(33,(32,(),()),(34,(),())),(37,(36,(),()),(38,(),()))),())),(45,(41,(),(43,(42,(),()),(44,(),()))),(47,(46,(),()),(48,(),())))) +(23,(21,(20,(),()),(22,(),())),(37,(33,(27,(25,(24,(),()),(26,(),())),(31,(29,(28,(),()),(30,(),())),(32,(),()))),(35,(34,(),()),(36,(),()))),(39,(38,(),()),(40,(),())))) 32 (32,(23,(21,(20,(),()),(22,(),())),(31,(27,(25,(24,(),()),(26,(),())),(29,(28,(),()),(30,(),()))),())),(33,(),(37,(35,(34,(),()),(36,(),())),(39,(38,(),()),(40,(),()))))) +(57,(53,(49,(43,(41,(40,(),()),(42,(),())),(47,(45,(44,(),()),(46,(),())),(48,(),()))),(51,(50,(),()),(52,(),()))),(55,(54,(),()),(56,(),()))),(59,(58,(),()),(60,(),()))) 48 (48,(47,(43,(41,(40,(),()),(42,(),())),(45,(44,(),()),(46,(),()))),()),(57,(49,(),(53,(51,(50,(),()),(52,(),())),(55,(54,(),()),(56,(),())))),(59,(58,(),()),(60,(),())))) +(9,(7,(6,(),()),(8,(),())),(13,(11,(10,(),()),(12,(),())),(17,(15,(14,(),()),(16,(),())),(23,(21,(19,(18,(),()),(20,(),())),(22,(),())),(25,(24,(),()),(26,(),())))))) 22 (22,(9,(7,(6,(),()),(8,(),())),(17,(13,(11,(10,(),()),(12,(),())),(15,(14,(),()),(16,(),()))),(21,(19,(18,(),()),(20,(),())),()))),(23,(),(25,(24,(),()),(26,(),())))) +(43,(29,(27,(26,(),()),(28,(),())),(33,(31,(30,(),()),(32,(),())),(39,(37,(35,(34,(),()),(36,(),())),(38,(),())),(41,(40,(),()),(42,(),()))))),(45,(44,(),()),(46,(),()))) 38 (38,(33,(29,(27,(26,(),()),(28,(),())),(31,(30,(),()),(32,(),()))),(37,(35,(34,(),()),(36,(),())),())),(43,(39,(),(41,(40,(),()),(42,(),()))),(45,(44,(),()),(46,(),())))) +(21,(19,(18,(),()),(20,(),())),(35,(25,(23,(22,(),()),(24,(),())),(31,(29,(27,(26,(),()),(28,(),())),(30,(),())),(33,(32,(),()),(34,(),())))),(37,(36,(),()),(38,(),())))) 30 (30,(21,(19,(18,(),()),(20,(),())),(25,(23,(22,(),()),(24,(),())),(29,(27,(26,(),()),(28,(),())),()))),(35,(31,(),(33,(32,(),()),(34,(),()))),(37,(36,(),()),(38,(),())))) +(55,(51,(41,(39,(38,(),()),(40,(),())),(47,(45,(43,(42,(),()),(44,(),())),(46,(),())),(49,(48,(),()),(50,(),())))),(53,(52,(),()),(54,(),()))),(57,(56,(),()),(58,(),()))) 46 (46,(41,(39,(38,(),()),(40,(),())),(45,(43,(42,(),()),(44,(),())),())),(55,(51,(47,(),(49,(48,(),()),(50,(),()))),(53,(52,(),()),(54,(),()))),(57,(56,(),()),(58,(),())))) +(17,(15,(14,(),()),(16,(),())),(21,(19,(18,(),()),(20,(),())),(31,(27,(25,(23,(22,(),()),(24,(),())),(26,(),())),(29,(28,(),()),(30,(),()))),(33,(32,(),()),(34,(),()))))) 26 (26,(17,(15,(14,(),()),(16,(),())),(21,(19,(18,(),()),(20,(),())),(25,(23,(22,(),()),(24,(),())),()))),(31,(27,(),(29,(28,(),()),(30,(),()))),(33,(32,(),()),(34,(),())))) +(51,(37,(35,(34,(),()),(36,(),())),(47,(43,(41,(39,(38,(),()),(40,(),())),(42,(),())),(45,(44,(),()),(46,(),()))),(49,(48,(),()),(50,(),())))),(53,(52,(),()),(54,(),()))) 42 (42,(37,(35,(34,(),()),(36,(),())),(41,(39,(38,(),()),(40,(),())),())),(51,(47,(43,(),(45,(44,(),()),(46,(),()))),(49,(48,(),()),(50,(),()))),(53,(52,(),()),(54,(),())))) +(29,(27,(26,(),()),(28,(),())),(43,(39,(35,(33,(31,(30,(),()),(32,(),())),(34,(),())),(37,(36,(),()),(38,(),()))),(41,(40,(),()),(42,(),()))),(45,(44,(),()),(46,(),())))) 34 (34,(29,(27,(26,(),()),(28,(),())),(33,(31,(30,(),()),(32,(),())),())),(39,(35,(),(37,(36,(),()),(38,(),()))),(43,(41,(40,(),()),(42,(),())),(45,(44,(),()),(46,(),()))))) +(63,(59,(55,(51,(49,(47,(46,(),()),(48,(),())),(50,(),())),(53,(52,(),()),(54,(),()))),(57,(56,(),()),(58,(),()))),(61,(60,(),()),(62,(),()))),(65,(64,(),()),(66,(),()))) 50 (50,(49,(47,(46,(),()),(48,(),())),()),(63,(55,(51,(),(53,(52,(),()),(54,(),()))),(59,(57,(56,(),()),(58,(),())),(61,(60,(),()),(62,(),())))),(65,(64,(),()),(66,(),())))) +(8,(6,(5,(),()),(7,(),())),(12,(10,(9,(),()),(11,(),())),(16,(14,(13,(),()),(15,(),())),(20,(18,(17,(),()),(19,(),())),(22,(21,(),()),(24,(23,(),()),(25,(),()))))))) 21 (21,(8,(6,(5,(),()),(7,(),())),(16,(12,(10,(9,(),()),(11,(),())),(14,(13,(),()),(15,(),()))),(20,(18,(17,(),()),(19,(),())),()))),(22,(),(24,(23,(),()),(25,(),())))) +(42,(28,(26,(25,(),()),(27,(),())),(32,(30,(29,(),()),(31,(),())),(36,(34,(33,(),()),(35,(),())),(38,(37,(),()),(40,(39,(),()),(41,(),())))))),(44,(43,(),()),(45,(),()))) 37 (37,(32,(28,(26,(25,(),()),(27,(),())),(30,(29,(),()),(31,(),()))),(36,(34,(33,(),()),(35,(),())),())),(42,(38,(),(40,(39,(),()),(41,(),()))),(44,(43,(),()),(45,(),())))) +(20,(18,(17,(),()),(19,(),())),(34,(24,(22,(21,(),()),(23,(),())),(28,(26,(25,(),()),(27,(),())),(30,(29,(),()),(32,(31,(),()),(33,(),()))))),(36,(35,(),()),(37,(),())))) 29 (29,(20,(18,(17,(),()),(19,(),())),(24,(22,(21,(),()),(23,(),())),(28,(26,(25,(),()),(27,(),())),()))),(34,(30,(),(32,(31,(),()),(33,(),()))),(36,(35,(),()),(37,(),())))) +(54,(50,(40,(38,(37,(),()),(39,(),())),(44,(42,(41,(),()),(43,(),())),(46,(45,(),()),(48,(47,(),()),(49,(),()))))),(52,(51,(),()),(53,(),()))),(56,(55,(),()),(57,(),()))) 45 (45,(40,(38,(37,(),()),(39,(),())),(44,(42,(41,(),()),(43,(),())),())),(54,(50,(46,(),(48,(47,(),()),(49,(),()))),(52,(51,(),()),(53,(),()))),(56,(55,(),()),(57,(),())))) +(16,(14,(13,(),()),(15,(),())),(20,(18,(17,(),()),(19,(),())),(30,(24,(22,(21,(),()),(23,(),())),(26,(25,(),()),(28,(27,(),()),(29,(),())))),(32,(31,(),()),(33,(),()))))) 25 (25,(16,(14,(13,(),()),(15,(),())),(20,(18,(17,(),()),(19,(),())),(24,(22,(21,(),()),(23,(),())),()))),(30,(26,(),(28,(27,(),()),(29,(),()))),(32,(31,(),()),(33,(),())))) +(50,(36,(34,(33,(),()),(35,(),())),(46,(40,(38,(37,(),()),(39,(),())),(42,(41,(),()),(44,(43,(),()),(45,(),())))),(48,(47,(),()),(49,(),())))),(52,(51,(),()),(53,(),()))) 41 (41,(36,(34,(33,(),()),(35,(),())),(40,(38,(37,(),()),(39,(),())),())),(50,(46,(42,(),(44,(43,(),()),(45,(),()))),(48,(47,(),()),(49,(),()))),(52,(51,(),()),(53,(),())))) +(28,(26,(25,(),()),(27,(),())),(42,(38,(32,(30,(29,(),()),(31,(),())),(34,(33,(),()),(36,(35,(),()),(37,(),())))),(40,(39,(),()),(41,(),()))),(44,(43,(),()),(45,(),())))) 33 (33,(28,(26,(25,(),()),(27,(),())),(32,(30,(29,(),()),(31,(),())),())),(38,(34,(),(36,(35,(),()),(37,(),()))),(42,(40,(39,(),()),(41,(),())),(44,(43,(),()),(45,(),()))))) +(62,(58,(54,(48,(46,(45,(),()),(47,(),())),(50,(49,(),()),(52,(51,(),()),(53,(),())))),(56,(55,(),()),(57,(),()))),(60,(59,(),()),(61,(),()))),(64,(63,(),()),(65,(),()))) 49 (49,(48,(46,(45,(),()),(47,(),())),()),(62,(54,(50,(),(52,(51,(),()),(53,(),()))),(58,(56,(55,(),()),(57,(),())),(60,(59,(),()),(61,(),())))),(64,(63,(),()),(65,(),())))) +(14,(12,(11,(),()),(13,(),())),(18,(16,(15,(),()),(17,(),())),(22,(20,(19,(),()),(21,(),())),(28,(24,(23,(),()),(26,(25,(),()),(27,(),()))),(30,(29,(),()),(31,(),())))))) 23 (23,(14,(12,(11,(),()),(13,(),())),(22,(18,(16,(15,(),()),(17,(),())),(20,(19,(),()),(21,(),()))),())),(24,(),(28,(26,(25,(),()),(27,(),())),(30,(29,(),()),(31,(),()))))) +(48,(34,(32,(31,(),()),(33,(),())),(38,(36,(35,(),()),(37,(),())),(44,(40,(39,(),()),(42,(41,(),()),(43,(),()))),(46,(45,(),()),(47,(),()))))),(50,(49,(),()),(51,(),()))) 39 (39,(38,(34,(32,(31,(),()),(33,(),())),(36,(35,(),()),(37,(),()))),()),(48,(40,(),(44,(42,(41,(),()),(43,(),())),(46,(45,(),()),(47,(),())))),(50,(49,(),()),(51,(),())))) +(26,(24,(23,(),()),(25,(),())),(40,(30,(28,(27,(),()),(29,(),())),(36,(32,(31,(),()),(34,(33,(),()),(35,(),()))),(38,(37,(),()),(39,(),())))),(42,(41,(),()),(43,(),())))) 31 (31,(26,(24,(23,(),()),(25,(),())),(30,(28,(27,(),()),(29,(),())),())),(40,(32,(),(36,(34,(33,(),()),(35,(),())),(38,(37,(),()),(39,(),())))),(42,(41,(),()),(43,(),())))) +(60,(56,(46,(44,(43,(),()),(45,(),())),(52,(48,(47,(),()),(50,(49,(),()),(51,(),()))),(54,(53,(),()),(55,(),())))),(58,(57,(),()),(59,(),()))),(62,(61,(),()),(63,(),()))) 47 (47,(46,(44,(43,(),()),(45,(),())),()),(60,(56,(48,(),(52,(50,(49,(),()),(51,(),())),(54,(53,(),()),(55,(),())))),(58,(57,(),()),(59,(),()))),(62,(61,(),()),(63,(),())))) +(22,(20,(19,(),()),(21,(),())),(26,(24,(23,(),()),(25,(),())),(36,(32,(28,(27,(),()),(30,(29,(),()),(31,(),()))),(34,(33,(),()),(35,(),()))),(38,(37,(),()),(39,(),()))))) 27 (27,(22,(20,(19,(),()),(21,(),())),(26,(24,(23,(),()),(25,(),())),())),(36,(28,(),(32,(30,(29,(),()),(31,(),())),(34,(33,(),()),(35,(),())))),(38,(37,(),()),(39,(),())))) +(56,(42,(40,(39,(),()),(41,(),())),(52,(48,(44,(43,(),()),(46,(45,(),()),(47,(),()))),(50,(49,(),()),(51,(),()))),(54,(53,(),()),(55,(),())))),(58,(57,(),()),(59,(),()))) 43 (43,(42,(40,(39,(),()),(41,(),())),()),(56,(52,(44,(),(48,(46,(45,(),()),(47,(),())),(50,(49,(),()),(51,(),())))),(54,(53,(),()),(55,(),()))),(58,(57,(),()),(59,(),())))) +(34,(32,(31,(),()),(33,(),())),(48,(44,(40,(36,(35,(),()),(38,(37,(),()),(39,(),()))),(42,(41,(),()),(43,(),()))),(46,(45,(),()),(47,(),()))),(50,(49,(),()),(51,(),())))) 35 (35,(34,(32,(31,(),()),(33,(),())),()),(44,(36,(),(40,(38,(37,(),()),(39,(),())),(42,(41,(),()),(43,(),())))),(48,(46,(45,(),()),(47,(),())),(50,(49,(),()),(51,(),()))))) +(68,(64,(60,(56,(52,(51,(),()),(54,(53,(),()),(55,(),()))),(58,(57,(),()),(59,(),()))),(62,(61,(),()),(63,(),()))),(66,(65,(),()),(67,(),()))),(70,(69,(),()),(71,(),()))) 51 (51,(),(68,(60,(52,(),(56,(54,(53,(),()),(55,(),())),(58,(57,(),()),(59,(),())))),(64,(62,(61,(),()),(63,(),())),(66,(65,(),()),(67,(),())))),(70,(69,(),()),(71,(),())))) diff --git a/02-splay_operation/cpp/test_main.cpp b/02-splay_operation/cpp/test_main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f4aff0785f636b7fd0ea1a15aa69dafe06f290f --- /dev/null +++ b/02-splay_operation/cpp/test_main.cpp @@ -0,0 +1,43 @@ +#include <cstdlib> +#include <functional> +#include <iostream> +#include <string> +#include <utility> +#include <vector> + +using namespace std; + +extern vector<pair<string, function<void()>>> tests; + +void expect_failed(const string& message) { + cerr << "Test error: " << message << endl; + exit(1); +} + +int main(int argc, char* argv[]) { + vector<string> required_tests; + + if (argc > 1) { + required_tests.assign(argv + 1, argv + argc); + } else { + for (const auto& test : tests) + required_tests.push_back(test.first); + } + + for (const auto& required_test : required_tests) { + bool found = false; + for (const auto& test : tests) + if (required_test == test.first) { + cerr << "Running test " << required_test << endl; + test.second(); + found = true; + break; + } + if (!found) { + cerr << "Unknown test " << required_test << endl; + return 1; + } + } + + return 0; +} diff --git a/02-splay_operation/python/splay_operation.py b/02-splay_operation/python/splay_operation.py new file mode 100644 index 0000000000000000000000000000000000000000..4e40e04ca2ad5a6423a3ca189faabb933d3d498e --- /dev/null +++ b/02-splay_operation/python/splay_operation.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 + +class Node: + """Node in a binary tree `Tree`""" + + def __init__(self, key, left=None, right=None, parent=None): + self.key = key + self.parent = parent + self.left = left + self.right = right + if left is not None: left.parent = self + if right is not None: right.parent = self + +class Tree: + """A simple binary search tree""" + + def __init__(self, root=None): + self.root = root + + def rotate(self, node): + """ Rotate the given `node` up. + + Performs a single rotation of the edge between the given node + and its parent, choosing left or right rotation appropriately. + """ + if node.parent is not None: + if node.parent.left == node: + if node.right is not None: node.right.parent = node.parent + node.parent.left = node.right + node.right = node.parent + else: + if node.left is not None: node.left.parent = node.parent + node.parent.right = node.left + node.left = node.parent + if node.parent.parent is not None: + if node.parent.parent.left == node.parent: + node.parent.parent.left = node + else: + node.parent.parent.right = node + else: + self.root = node + node.parent.parent, node.parent = node, node.parent.parent + + def lookup(self, key): + """Look up the given key in the tree. + + Returns the node with the requested key or `None`. + """ + # TODO: Utilize splay suitably. + node = self.root + while node is not None: + if node.key == key: + return node + if key < node.key: + node = node.left + else: + node = node.right + return None + + def insert(self, key): + """Insert key into the tree. + + If the key is already present, nothing happens. + """ + # TODO: Utilize splay suitably. + if self.root is None: + self.root = Node(key) + return + + node = self.root + while node.key != key: + if key < node.key: + if node.left is None: + node.left = Node(key, parent=node) + node = node.left + else: + if node.right is None: + node.right = Node(key, parent=node) + node = node.right + + def remove(self, key): + """Remove given key from the tree. + + It the key is not present, nothing happens. + """ + # TODO: Utilize splay suitably. + node = self.root + while node is not None and node.key != key: + if key < node.key: + node = node.left + else: + node = node.right + + if node is not None: + if node.left is not None and node.right is not None: + replacement = node.right + while replacement.left is not None: + replacement = replacement.left + node.key = replacement.key + node = replacement + + replacement = node.left if node.left is not None else node.right + if node.parent is not None: + if node.parent.left == node: node.parent.left = replacement + else: node.parent.right = replacement + else: + self.root = replacement + if replacement is not None: + replacement.parent = node.parent + + def splay(self, node): + """Splay the given node. + + If a single rotation needs to be performed, perform it as the last rotation + (i.e., to move the splayed node to the root of the tree). + """ + # TODO: Implement + raise NotImplementedError diff --git a/02-splay_operation/python/splay_operation_test.py b/02-splay_operation/python/splay_operation_test.py new file mode 100644 index 0000000000000000000000000000000000000000..b342520d608ef65eec87adce7f927187defc6205 --- /dev/null +++ b/02-splay_operation/python/splay_operation_test.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python3 +import itertools +import math +import sys + +from splay_operation import Tree, Node + +def flatten(tree): + """Flatten given tree in ascending order.""" + L, R, F = 0, 1, 2 + + node, stack, flattened = tree.root, [L], [] + while node is not None: + if stack[-1] == L: + stack[-1] = R + if node.left is not None: + node = node.left + stack.append(L) + elif stack[-1] == R: + flattened.append(node.key) + stack[-1] = F + if node.right is not None: + node = node.right + stack.append(L) + else: + node = node.parent + stack.pop() + + return flattened + +def test_splay(): + def deserialize_tree(string): + def deserialize_node(i): + assert string[i] == "(" + i += 1 + if string[i] == ")": + return i + 1, None + else: + comma = string.find(",", i) + comma2, left = deserialize_node(comma + 1) + rparen, right = deserialize_node(comma2 + 1) + assert string[rparen] == ")" + return rparen + 1, Node(int(string[i : comma]), left=left, right=right) + + index, root = deserialize_node(0) + assert index == len(string) + return Tree(root) + + def compare(system, gold): + if system is None and gold is not None: + return "expected node with key {}, found None".format(gold.key) + elif system is not None and gold is None: + return "expected None, found node with key {}".format(system.key) + elif system is not None and gold is not None: + if system.key != gold.key: + return "expected node with key {}, found {}".format(gold.key, system.key) + return compare(system.left, gold.left) or compare(system.right, gold.right) + + with open("splay_tests.txt", "r") as splay_tests_file: + for line in splay_tests_file: + original_serialized, target_serialized, splayed_serialized = line.rstrip("\n").split() + original = deserialize_tree(original_serialized) + splayed = deserialize_tree(splayed_serialized) + target = int(target_serialized) + + node = original.root + while node is not None and node.key != target: + if target < node.key: node = node.left + else: node = node.right + assert node is not None + + original.splay(node) + error = compare(original.root, splayed.root) + assert not error, "Error running splay on key {} of {}: {}".format(node.key, original_serialized, error) + +def test_lookup(): + tree = Tree() + for elem in range(0, 100000, 2): + tree.insert(elem) + + # Find non-existing + for elem in range(1, 100000, 2): + for _ in range(10): + assert tree.lookup(elem) is None, "Non-existing element was found" + + # Find existing + for elem in range(0, 100000, 2): + for _ in range(10): + assert tree.lookup(elem) is not None, "Existing element was not found" + +def test_insert(): + # Test validity first + tree = Tree() + sequence = [pow(997, i, 1999) for i in range(1, 1999)] + for elem in sequence: + tree.insert(elem) + assert flatten(tree) == sorted(sequence), "Incorrect tree after a sequence of inserts" + + # Test speed + tree = Tree() + for elem in range(200000): + for _ in range(10): + tree.insert(elem) + +def test_remove(): + # Test validity first + tree = Tree() + for elem in range(2, 1999 * 2): + tree.insert(elem) + + sequence = [2 * pow(997, i, 1999) for i in range(1, 1999)] + for elem in sequence: + tree.remove(elem + 1) + assert flatten(tree) == sorted(sequence), "Incorrect tree after a sequence of removes" + + # Test speed + tree = Tree() + for elem in range(0, 100000, 2): + tree.insert(elem) + + # Non-existing elements + for elem in range(1, 100000, 2): + for _ in range(10): + tree.remove(elem) + + # Existing elements + for elem in range(2, 100000, 2): + tree.remove(elem) + +tests = [ + ("splay", test_splay), + ("lookup", test_lookup), + ("insert", test_insert), + ("remove", test_remove), +] + +if __name__ == "__main__": + for required_test in sys.argv[1:] or [name for name, _ in tests]: + for name, test in tests: + if name == required_test: + print("Running test {}".format(name), file=sys.stderr) + test() + break + else: + raise ValueError("Unknown test {}".format(name)) diff --git a/02-splay_operation/python/splay_tests.txt b/02-splay_operation/python/splay_tests.txt new file mode 100644 index 0000000000000000000000000000000000000000..7f3259e5d6a4689f8e7cc608e450905b82647b7b --- /dev/null +++ b/02-splay_operation/python/splay_tests.txt @@ -0,0 +1,62 @@ +(3,(1,(0,(),()),(2,(),())),(4,(),())) 4 (4,(3,(1,(0,(),()),(2,(),())),()),()) +(6,(5,(),()),(8,(7,(),()),(9,(),()))) 5 (5,(),(6,(),(8,(7,(),()),(9,(),())))) +(3,(1,(0,(),()),(2,(),())),(7,(5,(4,(),()),(6,(),())),(8,(),()))) 8 (8,(7,(3,(1,(0,(),()),(2,(),())),(5,(4,(),()),(6,(),()))),()),()) +(11,(9,(7,(6,(),()),(8,(),())),(10,(),())),(13,(12,(),()),(14,(),()))) 10 (10,(9,(7,(6,(),()),(8,(),())),()),(11,(),(13,(12,(),()),(14,(),())))) +(8,(6,(5,(),()),(7,(),())),(10,(9,(),()),(12,(11,(),()),(13,(),())))) 9 (9,(8,(6,(5,(),()),(7,(),())),()),(10,(),(12,(11,(),()),(13,(),())))) +(16,(12,(11,(),()),(14,(13,(),()),(15,(),()))),(18,(17,(),()),(19,(),()))) 11 (11,(),(12,(),(16,(14,(13,(),()),(15,(),())),(18,(17,(),()),(19,(),()))))) +(3,(1,(0,(),()),(2,(),())),(7,(5,(4,(),()),(6,(),())),(11,(9,(8,(),()),(10,(),())),(12,(),())))) 12 (12,(3,(1,(0,(),()),(2,(),())),(11,(7,(5,(4,(),()),(6,(),())),(9,(8,(),()),(10,(),()))),())),()) +(17,(11,(9,(8,(),()),(10,(),())),(15,(13,(12,(),()),(14,(),())),(16,(),()))),(19,(18,(),()),(20,(),()))) 16 (16,(15,(11,(9,(8,(),()),(10,(),())),(13,(12,(),()),(14,(),()))),()),(17,(),(19,(18,(),()),(20,(),())))) +(9,(7,(6,(),()),(8,(),())),(15,(13,(11,(10,(),()),(12,(),())),(14,(),())),(17,(16,(),()),(18,(),())))) 14 (14,(9,(7,(6,(),()),(8,(),())),(13,(11,(10,(),()),(12,(),())),())),(15,(),(17,(16,(),()),(18,(),())))) +(23,(19,(17,(15,(14,(),()),(16,(),())),(18,(),())),(21,(20,(),()),(22,(),()))),(25,(24,(),()),(26,(),()))) 18 (18,(17,(15,(14,(),()),(16,(),())),()),(23,(19,(),(21,(20,(),()),(22,(),()))),(25,(24,(),()),(26,(),())))) +(8,(6,(5,(),()),(7,(),())),(12,(10,(9,(),()),(11,(),())),(14,(13,(),()),(16,(15,(),()),(17,(),()))))) 13 (13,(8,(6,(5,(),()),(7,(),())),(12,(10,(9,(),()),(11,(),())),())),(14,(),(16,(15,(),()),(17,(),())))) +(22,(16,(14,(13,(),()),(15,(),())),(18,(17,(),()),(20,(19,(),()),(21,(),())))),(24,(23,(),()),(25,(),()))) 17 (17,(16,(14,(13,(),()),(15,(),())),()),(22,(18,(),(20,(19,(),()),(21,(),()))),(24,(23,(),()),(25,(),())))) +(14,(12,(11,(),()),(13,(),())),(20,(16,(15,(),()),(18,(17,(),()),(19,(),()))),(22,(21,(),()),(23,(),())))) 15 (15,(14,(12,(11,(),()),(13,(),())),()),(16,(),(20,(18,(17,(),()),(19,(),())),(22,(21,(),()),(23,(),()))))) +(28,(24,(20,(19,(),()),(22,(21,(),()),(23,(),()))),(26,(25,(),()),(27,(),()))),(30,(29,(),()),(31,(),()))) 19 (19,(),(28,(20,(),(24,(22,(21,(),()),(23,(),())),(26,(25,(),()),(27,(),())))),(30,(29,(),()),(31,(),())))) +(3,(1,(0,(),()),(2,(),())),(7,(5,(4,(),()),(6,(),())),(11,(9,(8,(),()),(10,(),())),(15,(13,(12,(),()),(14,(),())),(16,(),()))))) 16 (16,(7,(3,(1,(0,(),()),(2,(),())),(5,(4,(),()),(6,(),()))),(15,(11,(9,(8,(),()),(10,(),())),(13,(12,(),()),(14,(),()))),())),()) +(25,(15,(13,(12,(),()),(14,(),())),(19,(17,(16,(),()),(18,(),())),(23,(21,(20,(),()),(22,(),())),(24,(),())))),(27,(26,(),()),(28,(),()))) 24 (24,(15,(13,(12,(),()),(14,(),())),(23,(19,(17,(16,(),()),(18,(),())),(21,(20,(),()),(22,(),()))),())),(25,(),(27,(26,(),()),(28,(),())))) +(11,(9,(8,(),()),(10,(),())),(21,(15,(13,(12,(),()),(14,(),())),(19,(17,(16,(),()),(18,(),())),(20,(),()))),(23,(22,(),()),(24,(),())))) 20 (20,(11,(9,(8,(),()),(10,(),())),(19,(15,(13,(12,(),()),(14,(),())),(17,(16,(),()),(18,(),()))),())),(21,(),(23,(22,(),()),(24,(),())))) +(33,(29,(23,(21,(20,(),()),(22,(),())),(27,(25,(24,(),()),(26,(),())),(28,(),()))),(31,(30,(),()),(32,(),()))),(35,(34,(),()),(36,(),()))) 28 (28,(27,(23,(21,(20,(),()),(22,(),())),(25,(24,(),()),(26,(),()))),()),(29,(),(33,(31,(30,(),()),(32,(),())),(35,(34,(),()),(36,(),()))))) +(9,(7,(6,(),()),(8,(),())),(13,(11,(10,(),()),(12,(),())),(19,(17,(15,(14,(),()),(16,(),())),(18,(),())),(21,(20,(),()),(22,(),()))))) 18 (18,(13,(9,(7,(6,(),()),(8,(),())),(11,(10,(),()),(12,(),()))),(17,(15,(14,(),()),(16,(),())),())),(19,(),(21,(20,(),()),(22,(),())))) +(31,(21,(19,(18,(),()),(20,(),())),(27,(25,(23,(22,(),()),(24,(),())),(26,(),())),(29,(28,(),()),(30,(),())))),(33,(32,(),()),(34,(),()))) 26 (26,(21,(19,(18,(),()),(20,(),())),(25,(23,(22,(),()),(24,(),())),())),(31,(27,(),(29,(28,(),()),(30,(),()))),(33,(32,(),()),(34,(),())))) +(17,(15,(14,(),()),(16,(),())),(27,(23,(21,(19,(18,(),()),(20,(),())),(22,(),())),(25,(24,(),()),(26,(),()))),(29,(28,(),()),(30,(),())))) 22 (22,(17,(15,(14,(),()),(16,(),())),(21,(19,(18,(),()),(20,(),())),())),(27,(23,(),(25,(24,(),()),(26,(),()))),(29,(28,(),()),(30,(),())))) +(39,(35,(31,(29,(27,(26,(),()),(28,(),())),(30,(),())),(33,(32,(),()),(34,(),()))),(37,(36,(),()),(38,(),()))),(41,(40,(),()),(42,(),()))) 30 (30,(29,(27,(26,(),()),(28,(),())),()),(35,(31,(),(33,(32,(),()),(34,(),()))),(39,(37,(36,(),()),(38,(),())),(41,(40,(),()),(42,(),()))))) +(8,(6,(5,(),()),(7,(),())),(12,(10,(9,(),()),(11,(),())),(16,(14,(13,(),()),(15,(),())),(18,(17,(),()),(20,(19,(),()),(21,(),())))))) 17 (17,(12,(8,(6,(5,(),()),(7,(),())),(10,(9,(),()),(11,(),()))),(16,(14,(13,(),()),(15,(),())),())),(18,(),(20,(19,(),()),(21,(),())))) +(30,(20,(18,(17,(),()),(19,(),())),(24,(22,(21,(),()),(23,(),())),(26,(25,(),()),(28,(27,(),()),(29,(),()))))),(32,(31,(),()),(33,(),()))) 25 (25,(20,(18,(17,(),()),(19,(),())),(24,(22,(21,(),()),(23,(),())),())),(30,(26,(),(28,(27,(),()),(29,(),()))),(32,(31,(),()),(33,(),())))) +(16,(14,(13,(),()),(15,(),())),(26,(20,(18,(17,(),()),(19,(),())),(22,(21,(),()),(24,(23,(),()),(25,(),())))),(28,(27,(),()),(29,(),())))) 21 (21,(16,(14,(13,(),()),(15,(),())),(20,(18,(17,(),()),(19,(),())),())),(26,(22,(),(24,(23,(),()),(25,(),()))),(28,(27,(),()),(29,(),())))) +(38,(34,(28,(26,(25,(),()),(27,(),())),(30,(29,(),()),(32,(31,(),()),(33,(),())))),(36,(35,(),()),(37,(),()))),(40,(39,(),()),(41,(),()))) 29 (29,(28,(26,(25,(),()),(27,(),())),()),(34,(30,(),(32,(31,(),()),(33,(),()))),(38,(36,(35,(),()),(37,(),())),(40,(39,(),()),(41,(),()))))) +(14,(12,(11,(),()),(13,(),())),(18,(16,(15,(),()),(17,(),())),(24,(20,(19,(),()),(22,(21,(),()),(23,(),()))),(26,(25,(),()),(27,(),()))))) 19 (19,(18,(14,(12,(11,(),()),(13,(),())),(16,(15,(),()),(17,(),()))),()),(20,(),(24,(22,(21,(),()),(23,(),())),(26,(25,(),()),(27,(),()))))) +(36,(26,(24,(23,(),()),(25,(),())),(32,(28,(27,(),()),(30,(29,(),()),(31,(),()))),(34,(33,(),()),(35,(),())))),(38,(37,(),()),(39,(),()))) 27 (27,(26,(24,(23,(),()),(25,(),())),()),(36,(28,(),(32,(30,(29,(),()),(31,(),())),(34,(33,(),()),(35,(),())))),(38,(37,(),()),(39,(),())))) +(22,(20,(19,(),()),(21,(),())),(32,(28,(24,(23,(),()),(26,(25,(),()),(27,(),()))),(30,(29,(),()),(31,(),()))),(34,(33,(),()),(35,(),())))) 23 (23,(22,(20,(19,(),()),(21,(),())),()),(32,(24,(),(28,(26,(25,(),()),(27,(),())),(30,(29,(),()),(31,(),())))),(34,(33,(),()),(35,(),())))) +(44,(40,(36,(32,(31,(),()),(34,(33,(),()),(35,(),()))),(38,(37,(),()),(39,(),()))),(42,(41,(),()),(43,(),()))),(46,(45,(),()),(47,(),()))) 31 (31,(),(40,(32,(),(36,(34,(33,(),()),(35,(),())),(38,(37,(),()),(39,(),())))),(44,(42,(41,(),()),(43,(),())),(46,(45,(),()),(47,(),()))))) +(3,(1,(0,(),()),(2,(),())),(7,(5,(4,(),()),(6,(),())),(11,(9,(8,(),()),(10,(),())),(15,(13,(12,(),()),(14,(),())),(19,(17,(16,(),()),(18,(),())),(20,(),())))))) 20 (20,(3,(1,(0,(),()),(2,(),())),(11,(7,(5,(4,(),()),(6,(),())),(9,(8,(),()),(10,(),()))),(19,(15,(13,(12,(),()),(14,(),())),(17,(16,(),()),(18,(),()))),()))),()) +(37,(23,(21,(20,(),()),(22,(),())),(27,(25,(24,(),()),(26,(),())),(31,(29,(28,(),()),(30,(),())),(35,(33,(32,(),()),(34,(),())),(36,(),()))))),(39,(38,(),()),(40,(),()))) 36 (36,(27,(23,(21,(20,(),()),(22,(),())),(25,(24,(),()),(26,(),()))),(35,(31,(29,(28,(),()),(30,(),())),(33,(32,(),()),(34,(),()))),())),(37,(),(39,(38,(),()),(40,(),())))) +(15,(13,(12,(),()),(14,(),())),(29,(19,(17,(16,(),()),(18,(),())),(23,(21,(20,(),()),(22,(),())),(27,(25,(24,(),()),(26,(),())),(28,(),())))),(31,(30,(),()),(32,(),())))) 28 (28,(15,(13,(12,(),()),(14,(),())),(19,(17,(16,(),()),(18,(),())),(27,(23,(21,(20,(),()),(22,(),())),(25,(24,(),()),(26,(),()))),()))),(29,(),(31,(30,(),()),(32,(),())))) +(49,(45,(35,(33,(32,(),()),(34,(),())),(39,(37,(36,(),()),(38,(),())),(43,(41,(40,(),()),(42,(),())),(44,(),())))),(47,(46,(),()),(48,(),()))),(51,(50,(),()),(52,(),()))) 44 (44,(35,(33,(32,(),()),(34,(),())),(43,(39,(37,(36,(),()),(38,(),())),(41,(40,(),()),(42,(),()))),())),(49,(45,(),(47,(46,(),()),(48,(),()))),(51,(50,(),()),(52,(),())))) +(11,(9,(8,(),()),(10,(),())),(15,(13,(12,(),()),(14,(),())),(25,(19,(17,(16,(),()),(18,(),())),(23,(21,(20,(),()),(22,(),())),(24,(),()))),(27,(26,(),()),(28,(),()))))) 24 (24,(11,(9,(8,(),()),(10,(),())),(15,(13,(12,(),()),(14,(),())),(23,(19,(17,(16,(),()),(18,(),())),(21,(20,(),()),(22,(),()))),()))),(25,(),(27,(26,(),()),(28,(),())))) +(45,(31,(29,(28,(),()),(30,(),())),(41,(35,(33,(32,(),()),(34,(),())),(39,(37,(36,(),()),(38,(),())),(40,(),()))),(43,(42,(),()),(44,(),())))),(47,(46,(),()),(48,(),()))) 40 (40,(31,(29,(28,(),()),(30,(),())),(39,(35,(33,(32,(),()),(34,(),())),(37,(36,(),()),(38,(),()))),())),(45,(41,(),(43,(42,(),()),(44,(),()))),(47,(46,(),()),(48,(),())))) +(23,(21,(20,(),()),(22,(),())),(37,(33,(27,(25,(24,(),()),(26,(),())),(31,(29,(28,(),()),(30,(),())),(32,(),()))),(35,(34,(),()),(36,(),()))),(39,(38,(),()),(40,(),())))) 32 (32,(23,(21,(20,(),()),(22,(),())),(31,(27,(25,(24,(),()),(26,(),())),(29,(28,(),()),(30,(),()))),())),(33,(),(37,(35,(34,(),()),(36,(),())),(39,(38,(),()),(40,(),()))))) +(57,(53,(49,(43,(41,(40,(),()),(42,(),())),(47,(45,(44,(),()),(46,(),())),(48,(),()))),(51,(50,(),()),(52,(),()))),(55,(54,(),()),(56,(),()))),(59,(58,(),()),(60,(),()))) 48 (48,(47,(43,(41,(40,(),()),(42,(),())),(45,(44,(),()),(46,(),()))),()),(57,(49,(),(53,(51,(50,(),()),(52,(),())),(55,(54,(),()),(56,(),())))),(59,(58,(),()),(60,(),())))) +(9,(7,(6,(),()),(8,(),())),(13,(11,(10,(),()),(12,(),())),(17,(15,(14,(),()),(16,(),())),(23,(21,(19,(18,(),()),(20,(),())),(22,(),())),(25,(24,(),()),(26,(),())))))) 22 (22,(9,(7,(6,(),()),(8,(),())),(17,(13,(11,(10,(),()),(12,(),())),(15,(14,(),()),(16,(),()))),(21,(19,(18,(),()),(20,(),())),()))),(23,(),(25,(24,(),()),(26,(),())))) +(43,(29,(27,(26,(),()),(28,(),())),(33,(31,(30,(),()),(32,(),())),(39,(37,(35,(34,(),()),(36,(),())),(38,(),())),(41,(40,(),()),(42,(),()))))),(45,(44,(),()),(46,(),()))) 38 (38,(33,(29,(27,(26,(),()),(28,(),())),(31,(30,(),()),(32,(),()))),(37,(35,(34,(),()),(36,(),())),())),(43,(39,(),(41,(40,(),()),(42,(),()))),(45,(44,(),()),(46,(),())))) +(21,(19,(18,(),()),(20,(),())),(35,(25,(23,(22,(),()),(24,(),())),(31,(29,(27,(26,(),()),(28,(),())),(30,(),())),(33,(32,(),()),(34,(),())))),(37,(36,(),()),(38,(),())))) 30 (30,(21,(19,(18,(),()),(20,(),())),(25,(23,(22,(),()),(24,(),())),(29,(27,(26,(),()),(28,(),())),()))),(35,(31,(),(33,(32,(),()),(34,(),()))),(37,(36,(),()),(38,(),())))) +(55,(51,(41,(39,(38,(),()),(40,(),())),(47,(45,(43,(42,(),()),(44,(),())),(46,(),())),(49,(48,(),()),(50,(),())))),(53,(52,(),()),(54,(),()))),(57,(56,(),()),(58,(),()))) 46 (46,(41,(39,(38,(),()),(40,(),())),(45,(43,(42,(),()),(44,(),())),())),(55,(51,(47,(),(49,(48,(),()),(50,(),()))),(53,(52,(),()),(54,(),()))),(57,(56,(),()),(58,(),())))) +(17,(15,(14,(),()),(16,(),())),(21,(19,(18,(),()),(20,(),())),(31,(27,(25,(23,(22,(),()),(24,(),())),(26,(),())),(29,(28,(),()),(30,(),()))),(33,(32,(),()),(34,(),()))))) 26 (26,(17,(15,(14,(),()),(16,(),())),(21,(19,(18,(),()),(20,(),())),(25,(23,(22,(),()),(24,(),())),()))),(31,(27,(),(29,(28,(),()),(30,(),()))),(33,(32,(),()),(34,(),())))) +(51,(37,(35,(34,(),()),(36,(),())),(47,(43,(41,(39,(38,(),()),(40,(),())),(42,(),())),(45,(44,(),()),(46,(),()))),(49,(48,(),()),(50,(),())))),(53,(52,(),()),(54,(),()))) 42 (42,(37,(35,(34,(),()),(36,(),())),(41,(39,(38,(),()),(40,(),())),())),(51,(47,(43,(),(45,(44,(),()),(46,(),()))),(49,(48,(),()),(50,(),()))),(53,(52,(),()),(54,(),())))) +(29,(27,(26,(),()),(28,(),())),(43,(39,(35,(33,(31,(30,(),()),(32,(),())),(34,(),())),(37,(36,(),()),(38,(),()))),(41,(40,(),()),(42,(),()))),(45,(44,(),()),(46,(),())))) 34 (34,(29,(27,(26,(),()),(28,(),())),(33,(31,(30,(),()),(32,(),())),())),(39,(35,(),(37,(36,(),()),(38,(),()))),(43,(41,(40,(),()),(42,(),())),(45,(44,(),()),(46,(),()))))) +(63,(59,(55,(51,(49,(47,(46,(),()),(48,(),())),(50,(),())),(53,(52,(),()),(54,(),()))),(57,(56,(),()),(58,(),()))),(61,(60,(),()),(62,(),()))),(65,(64,(),()),(66,(),()))) 50 (50,(49,(47,(46,(),()),(48,(),())),()),(63,(55,(51,(),(53,(52,(),()),(54,(),()))),(59,(57,(56,(),()),(58,(),())),(61,(60,(),()),(62,(),())))),(65,(64,(),()),(66,(),())))) +(8,(6,(5,(),()),(7,(),())),(12,(10,(9,(),()),(11,(),())),(16,(14,(13,(),()),(15,(),())),(20,(18,(17,(),()),(19,(),())),(22,(21,(),()),(24,(23,(),()),(25,(),()))))))) 21 (21,(8,(6,(5,(),()),(7,(),())),(16,(12,(10,(9,(),()),(11,(),())),(14,(13,(),()),(15,(),()))),(20,(18,(17,(),()),(19,(),())),()))),(22,(),(24,(23,(),()),(25,(),())))) +(42,(28,(26,(25,(),()),(27,(),())),(32,(30,(29,(),()),(31,(),())),(36,(34,(33,(),()),(35,(),())),(38,(37,(),()),(40,(39,(),()),(41,(),())))))),(44,(43,(),()),(45,(),()))) 37 (37,(32,(28,(26,(25,(),()),(27,(),())),(30,(29,(),()),(31,(),()))),(36,(34,(33,(),()),(35,(),())),())),(42,(38,(),(40,(39,(),()),(41,(),()))),(44,(43,(),()),(45,(),())))) +(20,(18,(17,(),()),(19,(),())),(34,(24,(22,(21,(),()),(23,(),())),(28,(26,(25,(),()),(27,(),())),(30,(29,(),()),(32,(31,(),()),(33,(),()))))),(36,(35,(),()),(37,(),())))) 29 (29,(20,(18,(17,(),()),(19,(),())),(24,(22,(21,(),()),(23,(),())),(28,(26,(25,(),()),(27,(),())),()))),(34,(30,(),(32,(31,(),()),(33,(),()))),(36,(35,(),()),(37,(),())))) +(54,(50,(40,(38,(37,(),()),(39,(),())),(44,(42,(41,(),()),(43,(),())),(46,(45,(),()),(48,(47,(),()),(49,(),()))))),(52,(51,(),()),(53,(),()))),(56,(55,(),()),(57,(),()))) 45 (45,(40,(38,(37,(),()),(39,(),())),(44,(42,(41,(),()),(43,(),())),())),(54,(50,(46,(),(48,(47,(),()),(49,(),()))),(52,(51,(),()),(53,(),()))),(56,(55,(),()),(57,(),())))) +(16,(14,(13,(),()),(15,(),())),(20,(18,(17,(),()),(19,(),())),(30,(24,(22,(21,(),()),(23,(),())),(26,(25,(),()),(28,(27,(),()),(29,(),())))),(32,(31,(),()),(33,(),()))))) 25 (25,(16,(14,(13,(),()),(15,(),())),(20,(18,(17,(),()),(19,(),())),(24,(22,(21,(),()),(23,(),())),()))),(30,(26,(),(28,(27,(),()),(29,(),()))),(32,(31,(),()),(33,(),())))) +(50,(36,(34,(33,(),()),(35,(),())),(46,(40,(38,(37,(),()),(39,(),())),(42,(41,(),()),(44,(43,(),()),(45,(),())))),(48,(47,(),()),(49,(),())))),(52,(51,(),()),(53,(),()))) 41 (41,(36,(34,(33,(),()),(35,(),())),(40,(38,(37,(),()),(39,(),())),())),(50,(46,(42,(),(44,(43,(),()),(45,(),()))),(48,(47,(),()),(49,(),()))),(52,(51,(),()),(53,(),())))) +(28,(26,(25,(),()),(27,(),())),(42,(38,(32,(30,(29,(),()),(31,(),())),(34,(33,(),()),(36,(35,(),()),(37,(),())))),(40,(39,(),()),(41,(),()))),(44,(43,(),()),(45,(),())))) 33 (33,(28,(26,(25,(),()),(27,(),())),(32,(30,(29,(),()),(31,(),())),())),(38,(34,(),(36,(35,(),()),(37,(),()))),(42,(40,(39,(),()),(41,(),())),(44,(43,(),()),(45,(),()))))) +(62,(58,(54,(48,(46,(45,(),()),(47,(),())),(50,(49,(),()),(52,(51,(),()),(53,(),())))),(56,(55,(),()),(57,(),()))),(60,(59,(),()),(61,(),()))),(64,(63,(),()),(65,(),()))) 49 (49,(48,(46,(45,(),()),(47,(),())),()),(62,(54,(50,(),(52,(51,(),()),(53,(),()))),(58,(56,(55,(),()),(57,(),())),(60,(59,(),()),(61,(),())))),(64,(63,(),()),(65,(),())))) +(14,(12,(11,(),()),(13,(),())),(18,(16,(15,(),()),(17,(),())),(22,(20,(19,(),()),(21,(),())),(28,(24,(23,(),()),(26,(25,(),()),(27,(),()))),(30,(29,(),()),(31,(),())))))) 23 (23,(14,(12,(11,(),()),(13,(),())),(22,(18,(16,(15,(),()),(17,(),())),(20,(19,(),()),(21,(),()))),())),(24,(),(28,(26,(25,(),()),(27,(),())),(30,(29,(),()),(31,(),()))))) +(48,(34,(32,(31,(),()),(33,(),())),(38,(36,(35,(),()),(37,(),())),(44,(40,(39,(),()),(42,(41,(),()),(43,(),()))),(46,(45,(),()),(47,(),()))))),(50,(49,(),()),(51,(),()))) 39 (39,(38,(34,(32,(31,(),()),(33,(),())),(36,(35,(),()),(37,(),()))),()),(48,(40,(),(44,(42,(41,(),()),(43,(),())),(46,(45,(),()),(47,(),())))),(50,(49,(),()),(51,(),())))) +(26,(24,(23,(),()),(25,(),())),(40,(30,(28,(27,(),()),(29,(),())),(36,(32,(31,(),()),(34,(33,(),()),(35,(),()))),(38,(37,(),()),(39,(),())))),(42,(41,(),()),(43,(),())))) 31 (31,(26,(24,(23,(),()),(25,(),())),(30,(28,(27,(),()),(29,(),())),())),(40,(32,(),(36,(34,(33,(),()),(35,(),())),(38,(37,(),()),(39,(),())))),(42,(41,(),()),(43,(),())))) +(60,(56,(46,(44,(43,(),()),(45,(),())),(52,(48,(47,(),()),(50,(49,(),()),(51,(),()))),(54,(53,(),()),(55,(),())))),(58,(57,(),()),(59,(),()))),(62,(61,(),()),(63,(),()))) 47 (47,(46,(44,(43,(),()),(45,(),())),()),(60,(56,(48,(),(52,(50,(49,(),()),(51,(),())),(54,(53,(),()),(55,(),())))),(58,(57,(),()),(59,(),()))),(62,(61,(),()),(63,(),())))) +(22,(20,(19,(),()),(21,(),())),(26,(24,(23,(),()),(25,(),())),(36,(32,(28,(27,(),()),(30,(29,(),()),(31,(),()))),(34,(33,(),()),(35,(),()))),(38,(37,(),()),(39,(),()))))) 27 (27,(22,(20,(19,(),()),(21,(),())),(26,(24,(23,(),()),(25,(),())),())),(36,(28,(),(32,(30,(29,(),()),(31,(),())),(34,(33,(),()),(35,(),())))),(38,(37,(),()),(39,(),())))) +(56,(42,(40,(39,(),()),(41,(),())),(52,(48,(44,(43,(),()),(46,(45,(),()),(47,(),()))),(50,(49,(),()),(51,(),()))),(54,(53,(),()),(55,(),())))),(58,(57,(),()),(59,(),()))) 43 (43,(42,(40,(39,(),()),(41,(),())),()),(56,(52,(44,(),(48,(46,(45,(),()),(47,(),())),(50,(49,(),()),(51,(),())))),(54,(53,(),()),(55,(),()))),(58,(57,(),()),(59,(),())))) +(34,(32,(31,(),()),(33,(),())),(48,(44,(40,(36,(35,(),()),(38,(37,(),()),(39,(),()))),(42,(41,(),()),(43,(),()))),(46,(45,(),()),(47,(),()))),(50,(49,(),()),(51,(),())))) 35 (35,(34,(32,(31,(),()),(33,(),())),()),(44,(36,(),(40,(38,(37,(),()),(39,(),())),(42,(41,(),()),(43,(),())))),(48,(46,(45,(),()),(47,(),())),(50,(49,(),()),(51,(),()))))) +(68,(64,(60,(56,(52,(51,(),()),(54,(53,(),()),(55,(),()))),(58,(57,(),()),(59,(),()))),(62,(61,(),()),(63,(),()))),(66,(65,(),()),(67,(),()))),(70,(69,(),()),(71,(),()))) 51 (51,(),(68,(60,(52,(),(56,(54,(53,(),()),(55,(),())),(58,(57,(),()),(59,(),())))),(64,(62,(61,(),()),(63,(),())),(66,(65,(),()),(67,(),())))),(70,(69,(),()),(71,(),())))) diff --git a/02-splay_operation/task.md b/02-splay_operation/task.md new file mode 100644 index 0000000000000000000000000000000000000000..86157d290268c1cfb5005c8c3f26bf2873b9a5b0 --- /dev/null +++ b/02-splay_operation/task.md @@ -0,0 +1,7 @@ +Given an implementation of a binary search tree including parent pointers: +- implement `splay` method, preferably utilizing the provided `rotate` operation + performing a single rotation; +- update `lookup`, `insert` and `remove` methods to utilize it correctly. + +You should submit the `splay_operation.*` file (but not the +`splay_operation_test.*`). diff --git a/03-splay_experiment/cpp/Makefile b/03-splay_experiment/cpp/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..aa0b7d534cd4240f8073fbbb4896685105db0ac9 --- /dev/null +++ b/03-splay_experiment/cpp/Makefile @@ -0,0 +1,22 @@ +STUDENT_ID ?= PLEASE_SET_STUDENT_ID + +.PHONY: test +test: splay_experiment + @rm -rf out && mkdir out + @for test in sequential random subset ; do \ + for mode in std naive ; do \ + echo t-$$test-$$mode ; \ + ./splay_experiment $$test $(STUDENT_ID) $$mode >out/t-$$test-$$mode ; \ + done ; \ + done + +INCLUDE ?= . +CXXFLAGS=-std=c++11 -O2 -Wall -Wextra -g -Wno-sign-compare -I$(INCLUDE) + +splay_experiment: splay_operation.h splay_experiment.cpp $(INCLUDE)/random.h + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $@ + +.PHONY: clean +clean: + rm -f splay_experiment + rm -rf out diff --git a/03-splay_experiment/cpp/random.h b/03-splay_experiment/cpp/random.h new file mode 100644 index 0000000000000000000000000000000000000000..5ef10aeb1fe7e58a48277fb3565169ec267d43d9 --- /dev/null +++ b/03-splay_experiment/cpp/random.h @@ -0,0 +1,61 @@ +#ifndef DS1_RANDOM_H +#define DS1_RANDOM_H + +#include <cstdint> + +/* + * This is the xoroshiro128+ random generator, designed in 2016 by David Blackman + * and Sebastiano Vigna, distributed under the CC-0 license. For more details, + * see http://vigna.di.unimi.it/xorshift/. + * + * Rewritten to C++ by Martin Mares, also placed under CC-0. + */ + +class RandomGen { + uint64_t state[2]; + + uint64_t rotl(uint64_t x, int k) + { + return (x << k) | (x >> (64 - k)); + } + + public: + // Initialize the generator, set its seed and warm it up. + RandomGen(unsigned int seed) + { + state[0] = seed * 0xdeadbeef; + state[1] = seed ^ 0xc0de1234; + for (int i=0; i<100; i++) + next_u64(); + } + + // Generate a random 64-bit number. + uint64_t next_u64(void) + { + uint64_t s0 = state[0], s1 = state[1]; + uint64_t result = s0 + s1; + s1 ^= s0; + state[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); + state[1] = rotl(s1, 36); + return result; + } + + // Generate a random 32-bit number. + uint32_t next_u32(void) + { + return next_u64() >> 11; + } + + // Generate a number between 0 and range-1. + unsigned int next_range(unsigned int range) + { + /* + * This is not perfectly uniform, unless the range is a power of two. + * However, for 64-bit random values and 32-bit ranges, the bias is + * insignificant. + */ + return next_u64() % range; + } +}; + +#endif diff --git a/03-splay_experiment/cpp/splay_experiment.cpp b/03-splay_experiment/cpp/splay_experiment.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a47da8b11bcff20db58805a330f8b05d0a6c15b5 --- /dev/null +++ b/03-splay_experiment/cpp/splay_experiment.cpp @@ -0,0 +1,208 @@ +#include <algorithm> +#include <functional> +#include <string> +#include <utility> +#include <vector> +#include <iostream> +#include <cmath> + +#include "splay_operation.h" +#include "random.h" + +using namespace std; + +/* + * A modified Splay tree for benchmarking. + * + * We inherit the implementation of operations from the Tree class + * and extend it by keeping statistics on the number of splay operations + * and the total number of rotations. Also, if naive is turned on, + * splay uses only single rotations. + * + * Please make sure that your Tree class defines the rotate() and splay() + * methods as virtual. + */ + +class BenchmarkingTree : public Tree { +public: + int num_operations; + int num_rotations; + bool do_naive; + + BenchmarkingTree(bool naive=false) + { + do_naive = naive; + reset(); + } + + void reset() + { + num_operations = 0; + num_rotations = 0; + } + + void rotate(Node *node) override + { + num_rotations++; + Tree::rotate(node); + } + + void splay(Node *node) override + { + num_operations++; + if (do_naive) { + while (node->parent) + rotate(node); + } else { + Tree::splay(node); + } + } + + // Return the average number of rotations per operation. + double rot_per_op() + { + if (num_operations > 0) + return (double) num_rotations / num_operations; + else + return 0; + } +}; + +bool naive; // Use of naive rotations requested +RandomGen *rng; // Random generator object + +void test_sequential() +{ + for (int n=100; n<=3000; n+=100) { + BenchmarkingTree tree = BenchmarkingTree(naive); + + for (int x=0; x<n; x++) + tree.insert(x); + + for (int i=0; i<5; i++) + for (int x=0; x<n; x++) + tree.lookup(x); + + cout << n << " " << tree.rot_per_op() << endl; + } +} + +// An auxiliary function for generating a random permutation. +vector<int> random_permutation(int n) +{ + vector<int> perm; + for (int i=0; i<n; i++) + perm.push_back(i); + for (int i=0; i<n-1; i++) + swap(perm[i], perm[i + rng->next_range(n-i)]); + return perm; +} + +void test_random() +{ + for (int e=32; e<=64; e++) { + int n = (int) pow(2, e/4.); + BenchmarkingTree tree = BenchmarkingTree(naive); + + vector<int> perm = random_permutation(n); + for (int x : perm) + tree.insert(x); + + for (int i=0; i<5*n; i++) + tree.lookup(rng->next_range(n)); + + cout << n << " " << tree.rot_per_op() << endl; + } +} + +/* + * An auxiliary function for constructing arithmetic progressions. + * The vector seq will be modified to contain an arithmetic progression + * of elements in interval [A,B] starting from position s with step inc. + */ +void make_progression(vector<int> &seq, int A, int B, int s, int inc) +{ + for (int i=0; i<seq.size(); i++) + while (seq[i] >= A && seq[i] <= B && s + inc*(seq[i]-A) != i) + swap(seq[i], seq[s + inc*(seq[i] - A)]); +} + +void test_subset_s(int sub) +{ + for (int e=32; e<=64; e++) { + int n = (int) pow(2, e/4.); + if (n < sub) + continue; + + // We will insert elements in order, which contain several + // arithmetic progressions interspersed with random elements. + vector<int> seq = random_permutation(n); + make_progression(seq, n/4, n/4 + n/20, n/10, 1); + make_progression(seq, n/2, n/2 + n/20, n/10, -1); + make_progression(seq, 3*n/4, 3*n/4 + n/20, n/2, -4); + make_progression(seq, 17*n/20, 17*n/20 + n/20, 2*n/5, 5); + + BenchmarkingTree tree = BenchmarkingTree(naive); + for (int x : seq) + tree.insert(x); + tree.reset(); + + for (int i=0; i<10000; i++) + tree.lookup(seq[rng->next_range(sub)]); + + cout << sub << " " << n << " " << tree.rot_per_op() << endl; + } +} + +void test_subset() +{ + test_subset_s(10); + test_subset_s(100); + test_subset_s(1000); +} + +vector<pair<string, function<void()>>> tests = { + { "sequential", test_sequential }, + { "random", test_random }, + { "subset", test_subset }, +}; + +int main(int argc, char **argv) +{ + if (argc != 4) { + cerr << "Usage: " << argv[0] << " <test> <student-id> (std|naive)" << endl; + return 1; + } + + string which_test = argv[1]; + string id_str = argv[2]; + string mode = argv[3]; + + try { + rng = new RandomGen(stoi(id_str)); + } catch (...) { + cerr << "Invalid student ID" << endl; + return 1; + } + + if (mode == "std") + naive = false; + else if (mode == "naive") + naive = true; + else + { + cerr << "Last argument must be either 'std' or 'naive'" << endl; + return 1; + } + + for (const auto& test : tests) { + if (test.first == which_test) + { + cout.precision(12); + test.second(); + return 0; + } + } + cerr << "Unknown test " << which_test << endl; + return 1; +} diff --git a/03-splay_experiment/python/Makefile b/03-splay_experiment/python/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..ac6c02d43598e1fd3745820a9a7b3995e8377774 --- /dev/null +++ b/03-splay_experiment/python/Makefile @@ -0,0 +1,15 @@ +STUDENT_ID ?= PLEASE_SET_STUDENT_ID + +.PHONY: test +test: splay_experiment.py + @rm -rf out && mkdir out + @for test in sequential random subset ; do \ + for mode in std naive ; do \ + echo t-$$test-$$mode ; \ + ./splay_experiment.py $$test $(STUDENT_ID) $$mode >out/t-$$test-$$mode ; \ + done ; \ + done + +.PHONY: clean +clean: + rm -rf out diff --git a/03-splay_experiment/python/splay_experiment.py b/03-splay_experiment/python/splay_experiment.py new file mode 100755 index 0000000000000000000000000000000000000000..8cf3d6d6af1564973bd17a43f2fa731cce083da7 --- /dev/null +++ b/03-splay_experiment/python/splay_experiment.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 + +import sys +import random + +from splay_operation import Tree + +class BenchmarkingTree(Tree): + """ A modified Splay tree for benchmarking. + + We inherit the implementation of operations from the Tree class + and extend it by keeping statistics on the number of splay operations + and the total number of rotations. Also, if naive is turned on, + splay uses only single rotations. + """ + + def __init__(self, naive=False): + Tree.__init__(self) + self.do_naive = naive + self.reset() + + def reset(self): + """Reset statistics.""" + self.num_rotations = 0; + self.num_operations = 0; + + def rotate(self, node): + self.num_rotations += 1 + Tree.rotate(self, node) + + def splay(self, node): + self.num_operations += 1 + if self.do_naive: + while node.parent is not None: + self.rotate(node) + else: + Tree.splay(self, node) + + def rot_per_op(self): + """Return the average number of rotations per operation.""" + if self.num_operations > 0: + return self.num_rotations / self.num_operations + else: + return 0 + +def test_sequential(): + for n in range(100, 3001, 100): + tree = BenchmarkingTree(naive) + for elem in range(n): + tree.insert(elem) + + for _ in range(5): + for elem in range(n): + tree.lookup(elem) + + print(n, tree.rot_per_op()) + +def test_random(): + for exp in range(32, 64): + n = int(2**(exp/4)) + tree = BenchmarkingTree(naive) + + for elem in random.sample(range(n), n): + tree.insert(elem) + + for _ in range(5*n): + tree.lookup(random.randrange(n)) + + print(n, tree.rot_per_op()) + +def make_progression(seq, A, B, s, inc): + """An auxiliary function for constructing arithmetic progressions. + + The array seq will be modified to contain an arithmetic progression + of elements in interval [A,B] starting from position s with step inc. + """ + for i in range(len(seq)): + while seq[i] >= A and seq[i] <= B and s + inc*(seq[i]-A) != i: + pos = s + inc*(seq[i]-A) + seq[i], seq[pos] = seq[pos], seq[i] + +def test_subset(): + for sub in [10, 100, 1000]: + for exp in range(32,64): + n = int(2**(exp/4)) + if n < sub: + continue + + # We will insert elements in order, which contain several + # arithmetic progressions interspersed with random elements. + seq = random.sample(range(n), n) + make_progression(seq, n//4, n//4 + n//20, n//10, 1) + make_progression(seq, n//2, n//2 + n//20, n//10, -1) + make_progression(seq, 3*n//4, 3*n//4 + n//20, n//2, -4) + make_progression(seq, 17*n//20, 17*n//20 + n//20, 2*n//5, 5) + + tree = BenchmarkingTree(naive) + for elem in seq: + tree.insert(elem) + tree.reset() + + for _ in range(10000): + tree.lookup(seq[random.randrange(sub)]) + + print(sub, n, tree.rot_per_op()) + +tests = { + "sequential": test_sequential, + "random": test_random, + "subset": test_subset, +} + +if len(sys.argv) == 4: + test, student_id = sys.argv[1], sys.argv[2] + if sys.argv[3] == "std": + naive = False + elif sys.argv[3] == "naive": + naive = True + else: + raise ValueError("Last argument must be either 'std' or 'naive'") + random.seed(student_id) + if test in tests: + tests[test]() + else: + raise ValueError("Unknown test {}".format(test)) +else: + raise ValueError("Usage: {} <test> <student-id> (std|naive)".format(sys.argv[0])) diff --git a/03-splay_experiment/task.md b/03-splay_experiment/task.md new file mode 100644 index 0000000000000000000000000000000000000000..8120d9a05a42ccdcb2ddee6ab285255a1c8d890e --- /dev/null +++ b/03-splay_experiment/task.md @@ -0,0 +1,85 @@ +## Goal + +The goal of this assignment is to evaluate your implementation of Splay trees +experimentally and to compare it with a "naive" implementation which splays +using single rotations only. + +You are given a test program (`splay_experiment`) which calls your +implementation from the previous assignment to perform the following +experiments: + +- _Sequential test:_ Insert _n_ elements sequentially and then repeatedly + find them all in sequential order. +- _Random test:_ Insert _n_ elements in random order and then find _5n_ + random elements. +- _Subset test:_ Insert a sequence of _n_ elements, which contains arithmetic + progressions interspersed with random elements. Then repeatedly access + a small subset of these elements in random order. Try this with subsets of + different cardinalities. + +The program tries each experiment with different values of _n_. In each try, +it prints the average number of rotations per splay operation. + +You should perform these experiments and write a report, which contains the following +plots of the measured data. Each plot should show the dependence of the average +number of rotations on the set size _n_. + +- The sequential test: one curve for the standard implementation, one for the naive one. +- The random test: one curve for the standard implementation, one for the naive one. +- The subset test: three curves for the standard implementation with different sizes + of the subset, three for the naive implementation with the same sizes. + +The report should discuss the experimental results and try to explain the observed +behavior using theory from the lectures. (If you want, you can carry out further +experiments to gain better understanding of the data structure and include these +in the report. This is strictly optional.) + +You should submit a PDF file with the report (and no source code). +You will get 1 temporary point upon submission if the file is syntantically correct; +proper points will be assigned later. + +## Test program + +The test program is given three arguments: +- The name of the test (`sequential`, `random`, `subset`). +- The random seed: you should use the last 2 digits of your student ID (you can find + it in the Study Information System – just click on the Personal data icon). Please + include the random seed in your report. +- The implementation to test (`std` or `naive`). + +The output of the program contains one line per experiment, which consists of: +- For the sequential and random test: the set size and the average number of rotations. +- For the subset test: the subset size, the set size, and the average number of rotations + per find. The initial insertions of the full set are not counted. + +## Your implementation + +Please use your implementation from the previous exercise. Methods `splay()` +and `rotate()` will be augmented by the test program. If you are performing +a double rotation directly instead of composing it from single rotations, you +need to adjust the `BenchmarkingTree` class accordingly. + +## Hints + +The following tools can be useful for producing nice plots: +- [pandas](https://pandas.pydata.org/) +- [matplotlib](https://matplotlib.org/) +- [gnuplot](http://www.gnuplot.info/) + +A quick checklist for plots: +- Is there a caption explaining what is plotted? +- Are the axes clearly labelled? Do they have value ranges and units? +- Have you mentioned that this axis has logarithmic scale? (Logarithmic graphs + are more fitting in some cases, but you should tell.) +- Is it clear which curve means what? +- Is it clear what are the measured points and what is an interpolated + curve between them? +- Are there any overlaps? (E.g., the most interesting part of the curve + hidden underneath a label?) + +In your discussion, please distinguish the following kinds of claims. +It should be always clear which is which: +- Experimental results (i.e., the raw data you obtained from the experiments) +- Theoretical facts (i.e., claims we have proved mathematically) +- Your hypotheses (e.g., when you claim that the graph looks like something is true, + but you are not able to prove rigorously that it always holds)