3

I'm translating such fragment of this Python file to C++:

SIDE = 3
LINES = []
for y in range(SIDE):
    row = tuple((x, y) for x in range(SIDE))
    LINES.append(row)
for x in range(SIDE):
    col = tuple((x, y) for y in range(SIDE))
    LINES.append(col)
LINES.append(tuple((x, x) for x in range(SIDE)))
LINES.append(tuple((SIDE - x - 1, x) for x in range(SIDE)))

LINES holds (x, y) coordinates of possible lines in Tic Tac Toe game. So for SIDE = 3 it holds:

[((0, 0), (1, 0), (2, 0)), 
 ((0, 1), (1, 1), (2, 1)), 
 ((0, 2), (1, 2), (2, 2)), 
 ((0, 0), (0, 1), (0, 2)), 
 ((1, 0), (1, 1), (1, 2)), 
 ((2, 0), (2, 1), (2, 2)), 
 ((0, 0), (1, 1), (2, 2)), 
 ((2, 0), (1, 1), (0, 2))]

SIDE value can change.

What I've tried

Performance is crucial (that's why I reached for C++), so I would like to calculate LINES only once. Thus, I've chosen to implement LINES as a static member of the class TicTacToeState.

I started with such code:

static char init_lines() {
    return 'a';
}

class TicTacToeState {
    static char LINES;
};

char TicTacToeState::LINES = init_lines();

It works. How to change LINES to an array? Maybe vector will be better? With pairs?

Maybe static member is not the best choice, maybe there is an easier way?

How would you translate it to C++?

We know the size of LINES, it's always 2 * SIDE + 2.

Special requirement

All C++ code must be in one .cpp file, no headers. Why? Because this is fragment of a library for bot competitions and it's typical that you can submit only one file.

3
  • you can just return a char* pointing to the first element of the array, that's how you would normally return arrays in C++. Check out stackoverflow.com/questions/5660527/… or stackoverflow.com/questions/3473438/return-array-in-a-function Commented Oct 14, 2015 at 23:43
  • @RNar You are missing the point of the question. I'm not asking how to return an array from a function, I'm asking how to initialize static member array with anything I would like. Commented Oct 14, 2015 at 23:47
  • my bad, i thought you were just using char as an example. Commented Oct 14, 2015 at 23:48

2 Answers 2

2

In C++ you can initialize static array members using group initialization

    static int a[10] = {5}; //this will initialize first position item with 5 and rest with 0s
    static char b[2] = {'b', 'b'};
    static int c[2][2] = { {1,1}, {1,2} };

    int main()
    {
        cout<< a[0] << endl; //output: 5
        cout<< a[1] << endl; //output: 0

        cout<< b[0] << endl; //output: b

        cout<< c[0][1] << endl; //output: 1
    }

Although the fact is you need to know size of the array not like in Python's list that are dynamically


If you need to insert to the table values calculated dynamically the best way to do this is to create factory method

    static int** fact(int width, int height)
    {
        int** a;

        a = new int*[width]; //we can do it when it is DYNAMIC array! 

        a[0] = new int[height];
        a[1] = new int[height];

        for(int i = 0; i < width; i++)
            for(int k = 0; k < height; k++)
                a[i][k] = i*k;

        return a;
    }

    static int** c = fact(2, 2); //you can call it with your SIDE var

    int main()
    {
        cout<< c[1][1] << endl; //output: 1
    }

Of course you can process it in loops

The same approach will be proper when you will decide to use std Vector class which is equvalent of Python's dynamic list

Sign up to request clarification or add additional context in comments.

8 Comments

There is a bigger problem - I can't initialize it with { } array initializer and constant values given in it. As you can see in Python code I need to dynamically calculate the coordinates based on SIDE value.
Why didn't you use a vector?
Accessing elements of a vector is just as fast as accessing elements of an array, if you use v[i] syntax. The difference will be when allocating and deallocating, but if the size isn't known at compile time you can't avoid that.
@m.antkowicz Stack-based (or static) arrays are faster than a std::vector because you don't have to allocate memory for them. (Note you can use std::array which has equal performance in this case, though.) Once you reach for new, you can – at the same cost but without all the trouble – use a std::vector.
@m.antkowicz They should be comparable in performance for accessing/writing. Under the hood, a vector is implemented as a dynamically allocated array after all. It's only slower when you resize it above what it had already reserved in memory. But then again, you don't actually have that functionality natively with arrays.
|
1

I suppose you could do this using a lambda function like this:

#include <vector>
#include <iostream>

const auto SIDE = 3U;

struct coord
{
    unsigned x;
    unsigned y;
    coord(unsigned x, unsigned y): x(x), y(y) {}
};

static const auto lines = [] // lambda function
{
    // returned data structure
    std::vector<std::vector<coord>> lines;

    for(auto y = 0U; y < SIDE; ++y)
    {
        lines.emplace_back(); // add a new line to back()
        for(auto x = 0U; x < SIDE; ++x)
            lines.back().emplace_back(x, y); // add a new coord to that line
    }

    for(auto x = 0U; x < SIDE; ++x)
    {
        lines.emplace_back();
        for(auto y = 0U; y < SIDE; ++y)
            lines.back().emplace_back(x, y);
    }

    lines.emplace_back();
    for(auto i = 0U; i < SIDE; ++i)
        lines.back().emplace_back(i, i);

    lines.emplace_back();
    for(auto i = 0U; i < SIDE; ++i)
        lines.back().emplace_back(SIDE - i - 1, i);

    return lines;
}(); // NOTE: () is important to run the lambda function

int main()
{
    for(auto const& line: lines)
    {
        std::cout << "(";
        for(auto const& coord: line)
            std::cout << "(" << coord.x << ", " << coord.y << ")";
        std::cout << ")\n";
    }
}

Output:

((0, 0)(1, 0)(2, 0))
((0, 1)(1, 1)(2, 1))
((0, 2)(1, 2)(2, 2))
((0, 0)(0, 1)(0, 2))
((1, 0)(1, 1)(1, 2))
((2, 0)(2, 1)(2, 2))
((0, 0)(1, 1)(2, 2))
((2, 0)(1, 1)(0, 2))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.