There is very big problems with complexity in the example above:
- The actual structure of the problem is 2d array (of booleans) where one dimension is boxes and another dimension is the properties. This structure is pretty much coming from visual basic from 1980.
- Then there is arbitrary boolean expressions manipulating these booleans from the 2d array
These two features together make it extreamly complex. For example, testing that the code works requires going through all elements of the 2d array (and evaluating boolean expression in each element of the 2d array) and then further evaluating the boolean expressions that connect the rows and columns of the 2d array. It's like adding your excel spreadsheet to your program and then making it calculate some values from the data; except that you need to add the setters/getters manually and manipulating the data is very burdensome. The complexity is still there.
So my recommendation is to try to make it simpler somehow - reducing rows/columns is a start, but try to get rid of the 2d array structure. So that you don't need to implement whole excel for it. Excel also uses this kind of 2d array where each node can have differently typed data in it. These conventions coming from C# seems to have this kind of hidden complexity in them.
Here's some c++ code which is pretty much equivalent of your code above, and allows you to see the actual 2d array structure:
template<class T> class Array1d { virtual T Map(int x) const=0; };
class Array2d { virtual bool Map(int x, int y) const=0; };
class Array2dImpl : public Array2d {
Array2dImpl(Array1d<Box> &b) : b(b) { }
bool Map(int x, int y) const
{ if (y==0) { return b.Map(x).width < maxwidth; }
if (y==1) { return b.Map(x).height < maxheight; }
... }
Array1d<Box> &b;
int maxwidth;
int maxheight;
};
class BooleanExpression : public Array1d<bool>
{
public:
BooleanExpression(Array2d &a) : a(a) { }
bool Map(int x) const { return a.Map(x,0) && a.Map(x,1) && a.Map(x,2) && a.Map(x,3); }
private:
Array2d &a;
};
Like your example above, this code can be used with a simple piece of code:
int main() {
Array1d<Box> boxes;
Array2dImpl array(boxes);
BooleanExpression e(array);
for(int i=0;i<e.size();i++)
{
if (e.Map(i)) { /* do something */ }
}
}
Now returning to your question about how to set the maxwidth variable in this example. It might seem that it requires separate setter for each property. But this is not the case, actually, best way forward is to add a function like this:
void SetElement(int x, int y, bool b);
This naturally belongs to the 2d array which is already included in your example. The real problem with this example is that there is 2^(x*y) different states the system can be in. This comes from x*y calls to SetElement. This kind of state explosion is completely crazy for such a system and this will break your software very badly.
Even if we assume you want to generate x*y booleans using the code above by just providing the dimensions, the trick how your example did the evil complexity is very hidden. Passing the box from foreach to PassesFilter() function looks very simple, but it causes all this trouble, reconfiguring all the booleans in single line of the excel. Related is also the state space involved in the coordinates of the boxes. Those are even worse problem.
(and no, hiding the 2d array by using C# code does not make it easier to understand,)
(In fact, it's very evil to post such code for other programmers to read, I hope you didn't know the 2d array is there and you still have a chance to somehow fix your software...)
C++
, I expect to seeC++
code. – DeadMG Sep 08 '11 at 15:39