0

So I am not sure how to describe this problem but I try my best. This problem is more or less language independent but I search for a solution in C++.

I want to create a data structure with an underlying array, where I can access the values in the array by increasing indices. After I reached the array size the indexing should decrease. I think an example will help here:

std::array<int, 3> A {-1, 9, 100}; //example values
A[-1] = "Error" => assert is ok
A[0] == -1;
A[1] == 9;
A[2] == 100; // highest possible index
A[3] == A[1] == 9;
A[4] == A[0] == -1;
A[5] = "Error" => assert is ok

So you see, I want to access value in the array up to index size() + size() - 1. I need this for any array size. Is there any data structure in C++ or mathematic formula (I can't think of any) to calculate the correct index?

Another example if it is not clear:

std::array<int, 4> A {-1, 9, 100, 0}; //example values
A[-1] = "Error" => assert is ok
A[0] == -1;
A[1] == 9;
A[2] == 100;
A[3] == 0; // highest possible index
A[4] == A[2] == 100;
A[5] == A[1] == 9;
A[6] == A[0] == -1;
A[7] = "Error" => assert is ok
RoQuOTriX
  • 2,871
  • 14
  • 25
  • `if (index >= size()) index = size - index;` ? (probably off by one) – 463035818_is_not_an_ai Oct 26 '20 at 09:58
  • @idclev463035818 so first examlpe: `index = 3 => size = 3 => size - index = 0` ? should be 1. Next `index = 4 -> => size = 3 => 3 - 4 = -1 = 2` seems not that correct to me – RoQuOTriX Oct 26 '20 at 10:01
  • 2
    I would say `if (index >= size()) index = 2*size - index - 1;` – Damien Oct 26 '20 at 10:02
  • yeah right it was wrong, just a first trial. Actually I am trying to understand what you are looking for. Would a correct formula answer the question? – 463035818_is_not_an_ai Oct 26 '20 at 10:03
  • @Damien should be -2 at the end, I think. Because I don't access the last element twice – RoQuOTriX Oct 26 '20 at 10:03
  • You ask about a data structure while I get the impression that you only need a special method of accessing a normal one. Also, are you going to read only or also write? (I might be confused by your use of `==` where I expect to see `= `...). Can you use a calculation function for accessing or do you really need `A[4]` to impllicitly access `A[2]`? – Yunnosch Oct 26 '20 at 10:03
  • @Yunnosch read and write. The `==` was used to imply that they are the same value – RoQuOTriX Oct 26 '20 at 10:04
  • @RoQuOTriX Right. I went too fast myself. `if (index >= size()) index = 2*size - index - 2;` – Damien Oct 26 '20 at 10:05
  • I think I will do it like @Damien mentioned, Overload the [] operator and do the calculation. It was that "easy" but I could not think of it... – RoQuOTriX Oct 26 '20 at 10:05
  • If you write a different value to `A[4]` than you read from `A[2]`, do you expect to read that new value next time from `A[2]`? I assume so but want you to confirm. – Yunnosch Oct 26 '20 at 10:06
  • @Yunnosch yes of course. A[4] should always the same as A[2]. If someone wants to know why I need this. I have overlying arrays of Vertices in a quad mesh. I need to access different points independed of the single quad, even if they share the same vertices with there neighboring quads – RoQuOTriX Oct 26 '20 at 10:08
  • You can create your own answer (or turn @Damien input into one, preferrably with their permission). That would get this out of the list of unanswered questions and still leave it open for further input by others. You could even accept your own answer. – Yunnosch Oct 26 '20 at 10:09
  • I will write an answer with a templated solution I write right now, thanks :D – RoQuOTriX Oct 26 '20 at 10:13
  • A comment is not an answer. This implies that of course you have my permission to use my very little contribution for your own answer. Even better of course if you add further details on how you finally solve it. – Damien Oct 26 '20 at 10:13
  • @Damien sorry I did not think about asking for your permission. Am I allowed to write a solution with the help of your comment? – RoQuOTriX Oct 26 '20 at 10:16
  • @RoQuOTriX Look at my previous comment. A comment is a temporary object. Thanks for asking for my permission, but it is not mandatory in such a case. – Damien Oct 26 '20 at 10:20
  • What you seem to want is a saw-tooth like curve for your indexes. There are a few algorithms to get such a curve, maybe try one of them? – Some programmer dude Oct 26 '20 at 10:20

2 Answers2

1

I solved the problem with help of @Damien.

I am using a templated class which wraps an std::array. In this class you could implement every needed method of the std::array. I did it like this (any comments are appreciated).

template<class TYPE, std::size_t SIZE>
class CyclicArray
{
public:

    TYPE& operator[] (int i)
    {
        return const_cast<TYPE&>(static_cast<const CyclicArray&>(*this)[i]);
    }
    const TYPE& operator[] (int i) const    
    {
        assert(i >= 0 && i <= SIZE * SIZE - 1);
        if (i < SIZE)
            return _Array[i];

        const auto newIndex = 2 * SIZE - i - 2;
        return _Array[newIndex];
    }
    
    auto begin() const { return _Array.begin(); }
    auto end() const { return _Array.end(); }
    
private:
    std::array<TYPE, SIZE> _Array{};
};
RoQuOTriX
  • 2,871
  • 14
  • 25
  • 1
    You can avoid duplication between const and non-const version like this: https://stackoverflow.com/questions/123758/how-do-i-remove-code-duplication-between-similar-const-and-non-const-member-func – Yksisarvinen Oct 26 '20 at 11:27
0
int reqIndex = 0;
int N = size;
for(int i = -1; i < (2*N); i++) {
    reqIndex = (i<N) ? i : (N-2)-(i%N);
    if (reqIndex == -1)
        cout << "...." << endl;
    else
        cout << A[reqIndex] << endl;
}
Michael Piefel
  • 18,660
  • 9
  • 81
  • 112
abhishekrn
  • 79
  • 8