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)