0

For my 2d array in C++, the 2d array needs to be flipped at a certain position. I have to write a function that flips the array Foe instance, Before:

double A[][2] = {{0,0}, {1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}, {7,7}}
                                         A     B     C       D

call function invert(or flip): invert(A, 8, 3, 4); after:

double A[][2] = { {0, 0}, {1, 1}, {2, 2},{6, 6}, {5, 5}, {4, 4}, {3, 3}, {7, 7}}
                                            D      C        B      A

Here is the attempt I have tried

  • @param A is the list of locations (x,y) of the cities in the current tour.
  • @param n is the number of cities in A.
  • @param start is the index of the beginning of the section to be inverted.
  • @param len is the length of the segment to invert(or flip).
    void invert ( double A[][2], int n, int start, int len ) {
          int(*tmp)[2] = new int[][2];
          for(int i = 0; i >= A.length; i--){
               for(int j = 0; j >= A[i].length; j--){
                    if( i > start)
                        tmp = A[i][j];
                 }
           }
               for(i = start; i < A.length; i++)
                  for(j = start; j < A[i].length; j++){
                     while (i <= end){
                        tmp = A[i][j];
                   }
                }
       }

The errors I have are

  • expressions must have class type
  • a value of type double cannot be assigned to an entity of type "double(*)[2]
  • cannot determine which instance of overload function "end" is intended

I am fully aware that most of the errors in my code are evident to find, but I needed to start somewhere.

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
jb20
  • 19
  • 4
  • 4
    With `std::pair a[] = {..};`, it would be `std::reverse(a + 3, a + 7);`. – Jarod42 Apr 22 '21 at 13:25
  • 3
    c-arrays dont have a `length` member. Is the array of fixed size? – 463035818_is_not_an_ai Apr 22 '21 at 13:25
  • Maybe you are using `using namespace std;`? [It is bad](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice). – MikeCAT Apr 22 '21 at 13:27
  • asked differently: Do you need to resize the array at runtime? – 463035818_is_not_an_ai Apr 22 '21 at 13:27
  • Yeah the array needs to be resized at runtime – jb20 Apr 22 '21 at 13:30
  • In the context of this problem, the array doesn't need to be resized. Maybe it does at other places, but it would be more effective to first focus on the issue at hand (reversing a sub-array). – hugo Apr 22 '21 at 13:55
  • @hugo a `std::array` cannot be resized at other places, even if it is not resized in this context, thats why I asked for clarification. A resizable container is different from a non-resizable one, even if you do not resize it ;) – 463035818_is_not_an_ai Apr 22 '21 at 13:57
  • @largest_prime_is_463035818 That’s not what my comment says. My point is, resizability is completely irrelevant here — I don’t see why it’s even mentioned. – hugo Apr 22 '21 at 14:07
  • @hugo I dont get your point. I was asking for clarification because if OP needs something that can be resized (if not here then perhaps elsewhere) then suggesting them to use `std::array` would be silly. On the other hand if they need something of fixed size then suggesting `std::vector` would be silly – 463035818_is_not_an_ai Apr 22 '21 at 14:09
  • Is there a way I can solve this problem without resizing the array? I am open to many options – jb20 Apr 22 '21 at 14:26
  • OP’s code currently uses fixed-size arrays, and OP is asking how to perform an operation that can be done efficiently without resize. That’s why the matter is off-topic. “(if not here then perhaps elsewhere)”: see the 2nd sentence of my initial comment. – hugo Apr 22 '21 at 14:28
  • @JeremieBastien Have you considered @Jarod42’s suggestion? I think he’s right on the money. To be clear, I don’t see a reason to consider resizing the arrays. – hugo Apr 22 '21 at 14:38
  • There is nothing special about so-called "2D" arrays in C++. They are just arrays that happen to have arrays as their elements. An array or a part thereof can be reversed with `std::reverse`, regardless of whether its elements are arrays or not.. This is literally a one-liner, `std::reverse(A+start, A+start+len);` – n. m. could be an AI Apr 25 '21 at 08:00
  • @Jarod42 it works perfectly fine with array elements that are pairs, built-in arrays, std::arrays. or anything else that is swappable. – n. m. could be an AI Apr 25 '21 at 08:07

2 Answers2

2

I admit, I don't know how to do it with a 2D C-array. I can only tell you about the simple way to do it.

First, a general advice: Name your stuff. What if I had to read only your code to see that you are dealing with locations of cities, that have x and y coordinates, instead of having to read your text, wouldn't that be great?

Next, for resizable arrays, you can (/should) use std::vector instead of C-arrays. C-arrays decay to pointers when passed to functions. C-arrays have their size as part of their type, but it is inconvenient to access it (and impossible once decayed to a pointer). And manually resizing dynamic C-arrays isn't much fun either.

Eventually, the "simple way" is to use an existing algorithm. To reverse elements in a range it is std::reverse:

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

struct location {
    int x;
    int y;
};

int main() {

    std::vector<location> cities{{0,0}, {1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}, {7,7}};
    for (const auto& loc : cities){
        std::cout << loc.x << " " << loc.y << "\n";
    } 
    std::cout << "\n";
    std::reverse(cities.begin()+ 3,cities.begin() + 7);
    for (const auto& loc : cities){
        std::cout << loc.x << " " << loc.y << "\n";
    } 
    
}

Output:

0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7

0 0
1 1
2 2
6 6
5 5
4 4
3 3
7 7

Actually with a 1-D c-array it is almost the same. The major difference is that c-arrays do not have begin as member. This produces same output as above:

location cities2[] = {{0,0}, {1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}, {7,7}};
for (const auto& loc : cities2){
    std::cout << loc.x << " " << loc.y << "\n";
} 
std::cout << "\n";
std::reverse(std::begin(cities2)+ 3,std::begin(cities2) + 7);
for (const auto& loc : cities2){
    std::cout << loc.x << " " << loc.y << "\n";
} 

And if you want to wrap it in a function you need to take care of the array decaying to a pointer:

void my_reverse(location* loc, size_t len, size_t first, size_t last){
    std::reverse(loc + first, loc + last + 1);
}

(I choose last to be the last element to be reversed. Note that the algorithm takes an iterator to the element one past the last element to be reversed).

Complete example with all three variants: https://godbolt.org/z/WMdea7WP3

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • Is there a way to do this without resizable arrays? Also, is there anything I can do with my variables in the parameter such as start and len? I apologize for the questions. – jb20 Apr 22 '21 at 14:44
  • @JeremieBastien as I mentioned in the beginning of the question, I didnt actually answer your question. It was not a joke, If I had to do it with a 2D c-array I would have to sit down and carefully test and debug some code that I would consider complicated. More closer to your original is what Jarod42 suggested in a comment. Use a 1-D c-array of `std::pair`s (or `location`s) then you can use `std::reverse` the same way as in my answer – 463035818_is_not_an_ai Apr 22 '21 at 15:36
  • @JeremieBastien I added solution for (1d) c-arrays. – 463035818_is_not_an_ai Apr 22 '21 at 15:45
  • @JeremieBastien sorry for the confusion about the resizing thing. I dont know why it is so much picked on. You can replace `std::vector` with `std::array` in my code and it should work as well – 463035818_is_not_an_ai Apr 22 '21 at 15:47
0

That's how I'd write the function if I knew it would always be used with 2 column arrays

void invert(double cities[][2], int size, int start, int len) {
    if (size < 0 || len < 0)
        return;

    double tempCoordsX, tempCoordsY;
    int endPos = start + len - 1;

    for (int i = start; i < (start + len/2); i++) {
        int mirroredPos = (endPos - (i - start)) % size;

        tempCoordsX = cities[i][0];
        tempCoordsY = cities[i][1];
        cities[i][0] = cities[mirroredPos][0];
        cities[i][1] = cities[mirroredPos][1];
        cities[mirroredPos][0] = tempCoordsX;
        cities[mirroredPos][1] = tempCoordsY;
    }

}

I repeat: please name your stuff