Skip to main content
added 6 characters in body
Source Link
Blasco
  • 753
  • 7
  • 22
#include <vector>
#include <iostream>
#include <algorithm>

using Matrix = std::vector<std::vector<int>>;

/**
 * Class implementing std::reference_wrapper that
 * cannot be rebound after creation.
 **/
template <class T>
class single_bind_reference_wrapper {

    // pointer to the original element
    T *p_;

public: 

    // typedefs
 
    using type = T;

    // Construct/Copy/Destroy
    single_bind_reference_wrapper(T& ref) noexcept : p_(std::addressof(ref)) {}
    single_bind_reference_wrapper(T&&) = delete;

    // Enable implicit convertsion from ref<T> to ref<const T>,
    // or ref<Derived> to ref<Base>
    template <class U, std::enable_if_t<std::is_convertible<U*, T*>{}, int> = 0>
    single_bind_reference_wrapper(const single_bind_reference_wrapper<U>& other) noexcept :
        p_(&other.get()) { }

    // Assignment
    template <class U>
    decltype(auto) operator=(U &&u) const 
          noexcept(std::is_nothrow_assignable<T, U>{}) {
        return get() = std::forward<U>(u);
    }

    decltype(auto) operator=(const single_bind_reference_wrapper& other) const
          noexcept(std::is_nothrow_assignable<T, T>{}) {
        return get() = other.get();
    }

    // Access
    operator T& () const noexcept { return *p_; }
    T& get() const noexcept { return *p_; }
};

template <class T>
void swap(single_bind_reference_wrapper<T> &lhs,
          single_bind_reference_wrapper<T> &rhs)
    noexcept(std::is_nothrow_move_constructible<T>::value &&
             std::is_nothrow_move_assignable<T>::value){
    auto tmp = std::move(lhs.get());
    lhs = std::move(rhs.get());
    rhs = std::move(tmp);
}

void rotate_mat (Matrix &mat, int r){
    auto m = mat.size(); // Number of rows
    auto n = mat[0].size(); // Number of columns
    auto n_rings = std::min(m,n)/2; // Number of rings
    for(auto ring_i=0; ring_i<n_rings; ++ring_i){
        // The elements of the ring are stored sequentially 
        // in v_ring so it can be rotated with std::rotate 
        std::vector<single_bind_reference_wrapper<int>>  v_ring;
        // Top side of the ring
        for(auto j=ring_i; j<=(n-1)-ring_i; ++j) {
            v_ring.push_back(mat[ring_i][j]);
        }
        // Right side of the ring
        for(auto i=ring_i+1; i<=(m-1)-ring_i; ++i) {
            v_ring.push_back(mat[i][(n-1)-ring_i]);
        }
        // Bottom size of the ring
        for(auto j=(n-1)-ring_i-1; j>ring_i; --j) {
            v_ring.push_back(mat[(m-1)-ring_i][j]);
        }
        // Left size of the ring
        for(auto i=(m-1)-ring_i; i>ring_i; --i) {
            v_ring.push_back(mat[i][ring_i]);
        }
        std::rotate(v_ring.begin(),v_ring.begin()+r%v_ring.size(),v_ring.end());
    }
};

Matrix read_matrix(int m, int n) {
    Matrix mat;
    mat.reserve(m);
    for(auto i=0; i<m; ++i) {
        mat.push_back(std::vector<int>{});
        mat[i].reserve(n);
        for(auto j=0; j<n; ++j) {
            int x; std::cin >> x;
            mat[i].push_back(x);
        }
    }
    return mat;
};

void print_matrix(Matrix &mat){
    for (auto& i : mat){
        for (auto& j : i) {
            std::cout << j << " ";
        }
        std::cout << "\n";
    }
};

int main() {
    int m,n; std::cin >> m >> n;
    int r; std::cin >> r;

    auto mat = read_matrix(m,n);
    rotate_mat(mat,r);
    print_matrix(mat);

    return 0;
}
#include <vector>
#include <iostream>
#include <algorithm>

using Matrix = std::vector<std::vector<int>>;

/**
 * Class implementing std::reference_wrapper that
 * cannot be rebound after creation.
 **/
template <class T>
class single_bind_reference_wrapper {

    // pointer to the original element
    T *p_;

public: // typedefs
 
    using type = T;

    // Construct/Copy/Destroy
    single_bind_reference_wrapper(T& ref) noexcept : p_(std::addressof(ref)) {}
    single_bind_reference_wrapper(T&&) = delete;

    // Enable implicit convertsion from ref<T> to ref<const T>,
    // or ref<Derived> to ref<Base>
    template <class U, std::enable_if_t<std::is_convertible<U*, T*>{}, int> = 0>
    single_bind_reference_wrapper(const single_bind_reference_wrapper<U>& other) noexcept :
        p_(&other.get()) { }

    // Assignment
    template <class U>
    decltype(auto) operator=(U &&u) const 
          noexcept(std::is_nothrow_assignable<T, U>{}) {
        return get() = std::forward<U>(u);
    }

    decltype(auto) operator=(const single_bind_reference_wrapper& other) const
          noexcept(std::is_nothrow_assignable<T, T>{}) {
        return get() = other.get();
    }

    // Access
    operator T& () const noexcept { return *p_; }
    T& get() const noexcept { return *p_; }
};

template <class T>
void swap(single_bind_reference_wrapper<T> &lhs,
          single_bind_reference_wrapper<T> &rhs)
    noexcept(std::is_nothrow_move_constructible<T>::value &&
             std::is_nothrow_move_assignable<T>::value){
    auto tmp = std::move(lhs.get());
    lhs = std::move(rhs.get());
    rhs = std::move(tmp);
}

void rotate_mat (Matrix &mat, int r){
    auto m = mat.size(); // Number of rows
    auto n = mat[0].size(); // Number of columns
    auto n_rings = std::min(m,n)/2; // Number of rings
    for(auto ring_i=0; ring_i<n_rings; ++ring_i){
        // The elements of the ring are stored sequentially 
        // in v_ring so it can be rotated with std::rotate 
        std::vector<single_bind_reference_wrapper<int>>  v_ring;
        // Top side of the ring
        for(auto j=ring_i; j<=(n-1)-ring_i; ++j) {
            v_ring.push_back(mat[ring_i][j]);
        }
        // Right side of the ring
        for(auto i=ring_i+1; i<=(m-1)-ring_i; ++i) {
            v_ring.push_back(mat[i][(n-1)-ring_i]);
        }
        // Bottom size of the ring
        for(auto j=(n-1)-ring_i-1; j>ring_i; --j) {
            v_ring.push_back(mat[(m-1)-ring_i][j]);
        }
        // Left size of the ring
        for(auto i=(m-1)-ring_i; i>ring_i; --i) {
            v_ring.push_back(mat[i][ring_i]);
        }
        std::rotate(v_ring.begin(),v_ring.begin()+r%v_ring.size(),v_ring.end());
    }
};

Matrix read_matrix(int m, int n) {
    Matrix mat;
    mat.reserve(m);
    for(auto i=0; i<m; ++i) {
        mat.push_back(std::vector<int>{});
        mat[i].reserve(n);
        for(auto j=0; j<n; ++j) {
            int x; std::cin >> x;
            mat[i].push_back(x);
        }
    }
    return mat;
};

void print_matrix(Matrix &mat){
    for (auto& i : mat){
        for (auto& j : i) {
            std::cout << j << " ";
        }
        std::cout << "\n";
    }
};

int main() {
    int m,n; std::cin >> m >> n;
    int r; std::cin >> r;

    auto mat = read_matrix(m,n);
    rotate_mat(mat,r);
    print_matrix(mat);

    return 0;
}
#include <vector>
#include <iostream>
#include <algorithm>

using Matrix = std::vector<std::vector<int>>;

/**
 * Class implementing std::reference_wrapper that
 * cannot be rebound after creation.
 **/
template <class T>
class single_bind_reference_wrapper {

    // pointer to the original element
    T *p_;

public: 

    // typedefs
    using type = T;

    // Construct/Copy/Destroy
    single_bind_reference_wrapper(T& ref) noexcept : p_(std::addressof(ref)) {}
    single_bind_reference_wrapper(T&&) = delete;

    // Enable implicit convertsion from ref<T> to ref<const T>,
    // or ref<Derived> to ref<Base>
    template <class U, std::enable_if_t<std::is_convertible<U*, T*>{}, int> = 0>
    single_bind_reference_wrapper(const single_bind_reference_wrapper<U>& other) noexcept :
        p_(&other.get()) { }

    // Assignment
    template <class U>
    decltype(auto) operator=(U &&u) const 
          noexcept(std::is_nothrow_assignable<T, U>{}) {
        return get() = std::forward<U>(u);
    }

    decltype(auto) operator=(const single_bind_reference_wrapper& other) const
          noexcept(std::is_nothrow_assignable<T, T>{}) {
        return get() = other.get();
    }

    // Access
    operator T& () const noexcept { return *p_; }
    T& get() const noexcept { return *p_; }
};

template <class T>
void swap(single_bind_reference_wrapper<T> &lhs,
          single_bind_reference_wrapper<T> &rhs)
    noexcept(std::is_nothrow_move_constructible<T>::value &&
             std::is_nothrow_move_assignable<T>::value){
    auto tmp = std::move(lhs.get());
    lhs = std::move(rhs.get());
    rhs = std::move(tmp);
}

void rotate_mat (Matrix &mat, int r){
    auto m = mat.size(); // Number of rows
    auto n = mat[0].size(); // Number of columns
    auto n_rings = std::min(m,n)/2; // Number of rings
    for(auto ring_i=0; ring_i<n_rings; ++ring_i){
        // The elements of the ring are stored sequentially 
        // in v_ring so it can be rotated with std::rotate 
        std::vector<single_bind_reference_wrapper<int>>  v_ring;
        // Top side of the ring
        for(auto j=ring_i; j<=(n-1)-ring_i; ++j) {
            v_ring.push_back(mat[ring_i][j]);
        }
        // Right side of the ring
        for(auto i=ring_i+1; i<=(m-1)-ring_i; ++i) {
            v_ring.push_back(mat[i][(n-1)-ring_i]);
        }
        // Bottom size of the ring
        for(auto j=(n-1)-ring_i-1; j>ring_i; --j) {
            v_ring.push_back(mat[(m-1)-ring_i][j]);
        }
        // Left size of the ring
        for(auto i=(m-1)-ring_i; i>ring_i; --i) {
            v_ring.push_back(mat[i][ring_i]);
        }
        std::rotate(v_ring.begin(),v_ring.begin()+r%v_ring.size(),v_ring.end());
    }
};

Matrix read_matrix(int m, int n) {
    Matrix mat;
    mat.reserve(m);
    for(auto i=0; i<m; ++i) {
        mat.push_back(std::vector<int>{});
        mat[i].reserve(n);
        for(auto j=0; j<n; ++j) {
            int x; std::cin >> x;
            mat[i].push_back(x);
        }
    }
    return mat;
};

void print_matrix(Matrix &mat){
    for (auto& i : mat){
        for (auto& j : i) {
            std::cout << j << " ";
        }
        std::cout << "\n";
    }
};

int main() {
    int m,n; std::cin >> m >> n;
    int r; std::cin >> r;

    auto mat = read_matrix(m,n);
    rotate_mat(mat,r);
    print_matrix(mat);

    return 0;
}
Source Link
Blasco
  • 753
  • 7
  • 22

I got the solution I was looking for from stackoverflow (check it here). Now it doesn't need the extra copy. I was expecting that this wouldn't be as verbose. I think being able to use the algorithms over a vector of references can be an useful feature.

#include <vector>
#include <iostream>
#include <algorithm>

using Matrix = std::vector<std::vector<int>>;

/**
 * Class implementing std::reference_wrapper that
 * cannot be rebound after creation.
 **/
template <class T>
class single_bind_reference_wrapper {

    // pointer to the original element
    T *p_;

public: // typedefs

    using type = T;

    // Construct/Copy/Destroy
    single_bind_reference_wrapper(T& ref) noexcept : p_(std::addressof(ref)) {}
    single_bind_reference_wrapper(T&&) = delete;

    // Enable implicit convertsion from ref<T> to ref<const T>,
    // or ref<Derived> to ref<Base>
    template <class U, std::enable_if_t<std::is_convertible<U*, T*>{}, int> = 0>
    single_bind_reference_wrapper(const single_bind_reference_wrapper<U>& other) noexcept :
        p_(&other.get()) { }

    // Assignment
    template <class U>
    decltype(auto) operator=(U &&u) const 
          noexcept(std::is_nothrow_assignable<T, U>{}) {
        return get() = std::forward<U>(u);
    }

    decltype(auto) operator=(const single_bind_reference_wrapper& other) const
          noexcept(std::is_nothrow_assignable<T, T>{}) {
        return get() = other.get();
    }

    // Access
    operator T& () const noexcept { return *p_; }
    T& get() const noexcept { return *p_; }
};

template <class T>
void swap(single_bind_reference_wrapper<T> &lhs,
          single_bind_reference_wrapper<T> &rhs)
    noexcept(std::is_nothrow_move_constructible<T>::value &&
             std::is_nothrow_move_assignable<T>::value){
    auto tmp = std::move(lhs.get());
    lhs = std::move(rhs.get());
    rhs = std::move(tmp);
}

void rotate_mat (Matrix &mat, int r){
    auto m = mat.size(); // Number of rows
    auto n = mat[0].size(); // Number of columns
    auto n_rings = std::min(m,n)/2; // Number of rings
    for(auto ring_i=0; ring_i<n_rings; ++ring_i){
        // The elements of the ring are stored sequentially 
        // in v_ring so it can be rotated with std::rotate 
        std::vector<single_bind_reference_wrapper<int>>  v_ring;
        // Top side of the ring
        for(auto j=ring_i; j<=(n-1)-ring_i; ++j) {
            v_ring.push_back(mat[ring_i][j]);
        }
        // Right side of the ring
        for(auto i=ring_i+1; i<=(m-1)-ring_i; ++i) {
            v_ring.push_back(mat[i][(n-1)-ring_i]);
        }
        // Bottom size of the ring
        for(auto j=(n-1)-ring_i-1; j>ring_i; --j) {
            v_ring.push_back(mat[(m-1)-ring_i][j]);
        }
        // Left size of the ring
        for(auto i=(m-1)-ring_i; i>ring_i; --i) {
            v_ring.push_back(mat[i][ring_i]);
        }
        std::rotate(v_ring.begin(),v_ring.begin()+r%v_ring.size(),v_ring.end());
    }
};

Matrix read_matrix(int m, int n) {
    Matrix mat;
    mat.reserve(m);
    for(auto i=0; i<m; ++i) {
        mat.push_back(std::vector<int>{});
        mat[i].reserve(n);
        for(auto j=0; j<n; ++j) {
            int x; std::cin >> x;
            mat[i].push_back(x);
        }
    }
    return mat;
};

void print_matrix(Matrix &mat){
    for (auto& i : mat){
        for (auto& j : i) {
            std::cout << j << " ";
        }
        std::cout << "\n";
    }
};

int main() {
    int m,n; std::cin >> m >> n;
    int r; std::cin >> r;

    auto mat = read_matrix(m,n);
    rotate_mat(mat,r);
    print_matrix(mat);

    return 0;
}