From 9fa7211a2b7d006114209f99abc8b9d3ca2ba171 Mon Sep 17 00:00:00 2001 From: kaller01 <martin@kallers.se> Date: Fri, 1 Dec 2023 15:45:17 +0100 Subject: [PATCH] seminar7-8 Co-authored-by: Albin <albarv340@users.noreply.github.com> --- seminar7/deque.cc | 206 +++++++++++++++++++++++++++++++++++++++++++++ seminar7/deque.h | 38 +++++++++ seminar7/deque.tcc | 173 +++++++++++++++++++++++++++++++++++++ seminar8/tests.cc | 93 ++++++++++++++++++++ 4 files changed, 510 insertions(+) create mode 100644 seminar7/deque.cc create mode 100644 seminar7/deque.h create mode 100644 seminar7/deque.tcc create mode 100644 seminar8/tests.cc diff --git a/seminar7/deque.cc b/seminar7/deque.cc new file mode 100644 index 0000000..b9c0f60 --- /dev/null +++ b/seminar7/deque.cc @@ -0,0 +1,206 @@ +#include "deque.h" + +#include <cassert> + +int main() +{ + deque<int, 3> d{}; + deque<int, 3> const& c{d}; + + assert(d.size() == 0); + assert(c.size() == 0); + + try + { + d.pop_back(); + assert(false); + } + catch (...) { } + + try + { + d.pop_front(); + assert(false); + } + catch (...) { } + + try + { + d.at(0); + assert(false); + } + catch (...) { } + + d.push_back(1); + + assert(d.size() == 1); + assert(d.at(0) == 1); + assert(d[0] == 1); + assert(c.at(0) == 1); + assert(c[0] == 1); + + int* ptr1 {&d[0]}; + + d.push_back(3); + d.push_back(5); + d.push_back(2); + + int* ptr2 {&d[3]}; + + assert(d.size() == 4); + assert(d[0] == 1); + assert(d[1] == 3); + assert(d[2] == 5); + assert(d[3] == 2); + + d.push_front(7); + assert(d[0] == 7); + assert(d[1] == 1); + assert(d[2] == 3); + assert(d[3] == 5); + assert(d[4] == 2); + + d.push_front(12); + assert(d[0] == 12); + assert(d[1] == 7); + assert(d[2] == 1); + assert(d[3] == 3); + assert(d[4] == 5); + assert(d[5] == 2); + + d.push_front(-5); + assert(d[0] == -5); + assert(d[1] == 12); + assert(d[2] == 7); + assert(d[3] == 1); + assert(d[4] == 3); + assert(d[5] == 5); + assert(d[6] == 2); + + d.push_back(-99); + assert(d[0] == -5); + assert(d[1] == 12); + assert(d[2] == 7); + assert(d[3] == 1); + assert(d[4] == 3); + assert(d[5] == 5); + assert(d[6] == 2); + assert(d[7] == -99); + + assert(d.size() == 8); + + { + auto cpy {d}; + + cpy.pop_front(); + assert(cpy[0] == 12); + assert(cpy[1] == 7); + assert(cpy[2] == 1); + assert(cpy[3] == 3); + assert(cpy[4] == 5); + assert(cpy[5] == 2); + assert(cpy[6] == -99); + assert(cpy.size() == 7); + + cpy.pop_front(); + assert(cpy[0] == 7); + assert(cpy[1] == 1); + assert(cpy[2] == 3); + assert(cpy[3] == 5); + assert(cpy[4] == 2); + assert(cpy[5] == -99); + assert(cpy.size() == 6); + + cpy.pop_front(); + assert(cpy[0] == 1); + assert(cpy[1] == 3); + assert(cpy[2] == 5); + assert(cpy[3] == 2); + assert(cpy[4] == -99); + assert(cpy.size() == 5); + + cpy.pop_front(); + assert(cpy[0] == 3); + assert(cpy[1] == 5); + assert(cpy[2] == 2); + assert(cpy[3] == -99); + assert(cpy.size() == 4); + + cpy.pop_front(); + assert(cpy[0] == 5); + assert(cpy[1] == 2); + assert(cpy[2] == -99); + assert(cpy.size() == 3); + + cpy.pop_front(); + assert(cpy[0] == 2); + assert(cpy[1] == -99); + assert(cpy.size() == 2); + + cpy.pop_front(); + assert(cpy[0] == -99); + assert(cpy.size() == 1); + + cpy.pop_front(); + assert(cpy.size() == 0); + } + + { + auto cpy {d}; + + cpy.pop_back(); + assert(cpy[0] == -5); + assert(cpy[1] == 12); + assert(cpy[2] == 7); + assert(cpy[3] == 1); + assert(cpy[4] == 3); + assert(cpy[5] == 5); + assert(cpy[6] == 2); + assert(cpy.size() == 7); + + cpy.pop_back(); + assert(cpy[0] == -5); + assert(cpy[1] == 12); + assert(cpy[2] == 7); + assert(cpy[3] == 1); + assert(cpy[4] == 3); + assert(cpy[5] == 5); + assert(cpy.size() == 6); + + cpy.pop_back(); + assert(cpy[0] == -5); + assert(cpy[1] == 12); + assert(cpy[2] == 7); + assert(cpy[3] == 1); + assert(cpy[4] == 3); + assert(cpy.size() == 5); + + cpy.pop_back(); + assert(cpy[0] == -5); + assert(cpy[1] == 12); + assert(cpy[2] == 7); + assert(cpy[3] == 1); + assert(cpy.size() == 4); + + cpy.pop_back(); + assert(cpy[0] == -5); + assert(cpy[1] == 12); + assert(cpy[2] == 7); + assert(cpy.size() == 3); + + cpy.pop_back(); + assert(cpy[0] == -5); + assert(cpy[1] == 12); + assert(cpy.size() == 2); + + cpy.pop_back(); + assert(cpy[0] == -5); + assert(cpy.size() == 1); + + cpy.pop_back(); + assert(cpy.size() == 0); + } + + assert(*ptr1 == 1); + assert(*ptr2 == 2); +} \ No newline at end of file diff --git a/seminar7/deque.h b/seminar7/deque.h new file mode 100644 index 0000000..814f355 --- /dev/null +++ b/seminar7/deque.h @@ -0,0 +1,38 @@ +#pragma once + +template <typename T, unsigned chunk_size> +class deque +{ +private: + unsigned begin{}; + unsigned data_size{10}; + T **data = new T*[data_size] {}; + unsigned size_internal{0}; + unsigned chunks{1}; + +public: + deque(); + deque(deque const&); + deque(deque&&); + ~deque(); + void push_front(T v); + void push_back(T v); + T pop_front(); + T pop_back(); + T& operator[](unsigned index) const; + T& at(unsigned index) const; + unsigned size() const; + deque& operator=(deque const&); + deque& operator=(deque&&); + +}; +/* + +data => | 0 | <= begin + | 1 2 3 | + | | + + +data[0][begin] +*/ +#include "deque.tcc" diff --git a/seminar7/deque.tcc b/seminar7/deque.tcc new file mode 100644 index 0000000..ffa5131 --- /dev/null +++ b/seminar7/deque.tcc @@ -0,0 +1,173 @@ +#pragma once +#include <algorithm> +#include <stdexcept> + +template <typename T, unsigned chunk_size> +deque<T, chunk_size>::deque() +{ + data[0] = new T[chunk_size]{}; +}; + +template <typename T, unsigned chunk_size> +deque<T, chunk_size>::~deque() +{ + std::for_each(data, data + chunks, [](T *&chunk) + { delete[] chunk; }); + + delete[] data; +}; + +template <typename T, unsigned chunk_size> +deque<T, chunk_size>::deque(deque const& other) +{ + data[0] = new T[chunk_size]{}; + *this = other; +}; + +template <typename T, unsigned chunk_size> +deque<T, chunk_size>& deque<T, chunk_size>::operator=(deque const& other) +{ + for (unsigned i = 0; i < other.size(); i++) + { + push_back(other[i]); + } + return *this; +}; + +template <typename T, unsigned chunk_size> +deque<T, chunk_size>::deque(deque &&other) +{ + *this = std::move(other); +}; + +template <typename T, unsigned chunk_size> +deque<T, chunk_size>& deque<T, chunk_size>::operator=(deque &&other) +{ + std::swap(data, other.data); + std::swap(data_size, other.data_size); + std::swap(chunks, other.chunks); + std::swap(size_internal, other.size_internal); + std::swap(begin, other.begin); + return *this; +}; + +template <typename T, unsigned chunk_size> +void deque<T, chunk_size>::push_front(T v) +{ + if (begin == 0) + { + if (chunks == data_size) + { + data_size *= 2; + T **tmp = new T *[data_size] {}; + std::copy(data, data + chunks, tmp + 1); + delete[] data; + data = tmp; + } + else + { + std::rotate(data, data + data_size - 1, data + data_size); + } + data[0] = new T[chunk_size]{}; + chunks++; + begin = chunk_size; + } + begin--; + data[0][begin] = v; + size_internal++; +} + +template <typename T, unsigned chunk_size> +void deque<T, chunk_size>::push_back(T v) +{ + // Find last used index + unsigned end_index = (begin + size_internal) - chunk_size * (chunks - 1); + if (end_index == chunk_size) + { + if (chunks == data_size) + { + data_size *= 2; + T **tmp = new T *[data_size] {}; + // std::copy(std::begin(data), std::end(data), std::begin(tmp)); + std::copy(data, data + chunks, tmp); + delete[] data; + data = tmp; + } + data[chunks++] = new T[chunk_size]{}; + // Advance to next chunk + end_index = 0; + } + data[chunks - 1][end_index] = v; + size_internal++; +} + +template <typename T, unsigned chunk_size> +T deque<T, chunk_size>::pop_front() +{ + if (size_internal == 0) + { + throw std::runtime_error{"hello"}; + } + T popped_v = std::move(data[0][begin++]); + if (begin == chunk_size) + { + delete[] data[0]; + // Left rotate + // std::rotate(std::begin(data), std::begin(data) + 1, std::end(data)); + std::rotate(data, data + 1, data + data_size); + begin = 0; + } + size_internal--; + return popped_v; +} + +template <typename T, unsigned chunk_size> +T deque<T, chunk_size>::pop_back() +{ + if (size_internal == 0) + { + throw std::runtime_error{"hello"}; + } + unsigned end_index = (begin + size_internal) - chunk_size * (chunks - 1); + T popped_v = std::move(data[chunks - 1][--end_index]); + if (end_index == 0) + { + delete[] data[--chunks]; + } + + size_internal--; + return popped_v; +} + +template <typename T, unsigned chunk_size> +T &deque<T, chunk_size>::operator[](unsigned index) const +{ + if (index >= size_internal) + { + throw std::runtime_error{"hello"}; + } + unsigned chunk_index = (begin + index) % chunk_size; + unsigned data_index = (begin + index) / chunk_size; + return data[data_index][chunk_index]; +} + +template <typename T, unsigned chunk_size> +T &deque<T, chunk_size>::at(unsigned index) const +{ + return (*this)[index]; +} + +template <typename T, unsigned chunk_size> +unsigned deque<T, chunk_size>::size() const +{ + return size_internal; +} +/* + +data => | 0 | <= begin + | 1 2 3 | + | 4 5 6 | <= chunks + + +data[0][begin] +*/ \ No newline at end of file diff --git a/seminar8/tests.cc b/seminar8/tests.cc new file mode 100644 index 0000000..300a9b0 --- /dev/null +++ b/seminar8/tests.cc @@ -0,0 +1,93 @@ +#include <ostream> +#include <iterator> +#include <utility> +#include <iostream> +#include <vector> +#include <map> +#include <tuple> +#include <array> +#include <string> +#include <algorithm> + +/* This should give the following output (or something similar at least): +5 +{1, 2, 3} +{(1 1), (2 2), (3 3)} +(5 3.14) +{hello, world} +{{ab, c}, {def, g, hi}} +SFINAE +string literal + */ + +void print(std::ostream &oss, char const *str) +{ + oss << str; +} + +void print(std::ostream &oss, std::string str) +{ + oss << str; +} + +// template <typename T> +template <typename T, typename = std::enable_if_t<!std::is_pointer_v<T>>> +auto print(std::ostream &oss, T t) -> decltype((oss << t), void()) +{ + oss << t; +} + +template <typename T> +auto print(std::ostream &oss, T &t) -> decltype((*std::begin(t)), (*std::end(t)), void()) +{ + oss << "{"; + for (auto &&e : t) + { + print(oss, e); + oss << ", "; + } + oss << "}"; +} + +int main() +{ + print(std::cout, 5); + std::cout << std::endl; + + std::vector<int> v{1, 2, 3}; + print(std::cout, v); + std::cout << std::endl; + + // std::map<int, int> m{{1, 1}, {2, 2}, {3, 3}}; + // print(std::cout, m); + // std::cout << std::endl; + + // std::tuple<int, double> t{5, 3.14}; + // print(std::cout, t); + // std::cout << std::endl; + // int i[]{1,3,3,7}; + // print(std::cout, i); + // std::cout << std::endl; + + std::string s[]{"hello", "world"}; + print(std::cout, s); + std::cout << std::endl; + + std::array<std::vector<std::string>, 2> a{ + std::vector<std::string>{"ab", "c"}, + std::vector<std::string>{"def", "g", "hi"}}; + + print(std::cout, a); + std::cout << std::endl; + + char const *str{"SFINAE"}; + print(std::cout, str); + std::cout << std::endl; + + const char literal[4] = {'a', 'b', 'c', 0}; + print(std::cout, literal); + std::cout << std::endl; + + print(std::cout, "string literal"); + std::cout << std::endl; +} \ No newline at end of file -- GitLab