12

I want to calculate area and perimeter of rects using the following code:

    rect a;
    a = ( -----
          !   !
          -----a );
std::cout << a.area() << std::endl;
std::cout << a.perimeter() << std::endl;

For this purpose I crafted the following class:

class rect
{
public:
    rect():w(0), h(2) {}
    rect& operator - () { w += 0.5f; return *this; }
    rect& operator - (rect&) { w += 0.5f; return *this; }
    rect& operator -- (int a) { w += a; return *this; }
    rect& operator -- () { w += 1; return *this; }
    rect& operator ! () { h += 0.5f; return *this; }
    void clear() { w = 0; h = 2; }
    int area() { return w * h; }
    int perimeter() { return 2 * w + 2 * h; }
    int width() { return w; }
    int height() { return h; }
private:
    float w;
    float h;
};

Here are some usage examples:

#include <iostream>

int main()
{
    rect a;

    a = ( -----
          !   !
          -----a );

    std::cout << a.area() << std::endl;
    std::cout << a.perimeter() << std::endl;
    std::cout << a.width()  << std::endl;
    std::cout << a.height() << std::endl;

    std::cout << std::endl;

    a.clear();

    a = ( ----------
          !        !
          !        !
          !        !
          !        !
          ---------a );

    std::cout << a.area() << std::endl;
    std::cout << a.perimeter() << std::endl;
    std::cout << a.width()  << std::endl;
    std::cout << a.height() << std::endl;

    return 0;
}

Here are my questions:

  1. Can it be done without involving any floating point arithmetic? (indeed, it is an integer grid)
  2. Can it be generalized on a 3D case? I.e:

    cuboid b;
    b = (  ---------
          /        /!
         ! -------! !
         !        ! !
         !        ! !
         !        !/
         ---------b );
    
    std::cout << b.volume() << std::endl;
    
Sergey K.
  • 24,894
  • 13
  • 106
  • 174

2 Answers2

8

I had to change the '/' operator to be '+', Since there is no prefix '/' operator. + works great though. Oh and it uses ints. I only tested it once with the case you provided but as far as I could tell it should work.

class cuboid
{
        int w,h,l;
public:
        cuboid () : w(2), h(3), l(6) {}
        cuboid& operator - () { w += 1; return *this; }
        cuboid& operator - (cuboid&) { w += 1; return *this; }
        cuboid& operator -- (int) { w += 2; return *this; }
        cuboid& operator -- () { w += 2; return *this; }
        cuboid& operator ! () { h += 1; return *this; }
        cuboid& operator + () { l += 1; return *this; }
        cuboid& operator + (cuboid&) { l += 1; return *this; }
        cuboid& operator ++ () { l += 2; return *this; }
        cuboid& operator ++ (int) { l += 2; return *this; }

        void clear () { w = 2; h = 3; l = 6; }
        int width () const { return w / 3; }
        int height () const { return h / 3; }
        int length () const { return l / 3; }
        int volume () const { return width() * height () * length (); }
        int surface_area() const { return width() * height () * 2 +
                                          width() * length () * 2 +
                                          length() * height () * 2; }
};

See it in action. http://ideone.com/vDqEm

Edit: You don't need the ++ operators since there shouldn't be two +'s next to each other. Woops.

Tocs
  • 752
  • 4
  • 17
2

Sort of. It's easy to validate an array as a rectangle and calculate stuff about it without floating point math as long as you assume that any character set has an equal height and width, or that your units are simply characters as opposed to pixels. So the actual shape of the rectangle will change based of the character set, but logically it will still be 3 characters by 2 characters.

BUT, you run into some issues with the 3D case. First off, you can't actually represent it using the grid-based layout using an array. Look at your ascii art again. What is the angle of front face? It's not zero, because you can observe the side-edge. If that is a 90 degree angle, if you can see the side, then the front face needs to be angled as well. So your method of representation simply isn't up to the task of representing 3d cuboids.

There's an alternative though. The 3D ascii art can be an abstraction of the 3D target you're talking about. The slash/backslash characters are now exactly one unit long, the same as the character '-' and '!' characters. With that assumption, the 3D version is also pretty trivial, even though it'll look pretty weird when you display it.

I mean, come on, look at these cubes, they are NOT euclidean friendly:

  ---
 / /!
--- !
! !/
---

   ----
  /  /|
 /  / |
----  |
|  | /
|  |/
----

So anyway, assuming these things are ascii-art strings representing 2D or 3D shapes, here you go:

//Skipping the validation step, assuming well formed ascii rectangles.
int height2D(char* rect, int size)
{
    int ret=0;
    int i=0;
    while(i++ < size) 
        if(rect[i] == '\n')
            ret++;
    return ret;
}

int width2D(char* rect, int size)
{
    int ret=0;
    while(rect[ret] == '-' && ret < size)
        ret++;
    return ret;
}

int area2D(char* rect, int size)
{
    //return height2D(rect, size) * width2D(rect, size);
    //ppfffft!
    return size;
}

int perimiter2D(char* rect, int size)
{
    return 2 * height2D(rect, size) + 2 * width2D(rect, size);
}



//Skipping the validation step, assuming well formed ascii cuboids
int height3D(char* rect, int size)
{
    int ret=0;
    int i=0;
    int depth;

    while(i++ < size) 
        if(rect[i] == '\n')
            ret++;
    depth = depth3D(rect, size);
    return ret - depth + 2;
}

int width3D(char* rect, int size)
{
    int ret=0;
    int i=0;
    while(rect[i] != '-' && ret < size)
        i++;
    while(rect[i++] == '-' && ret < size)
        ret++;

    return ret;
}

int depth3D(char* rect, int size)
{
    int ret=0;
    while(rect[ret] == ' ' && ret < size)
        ret++;
    return ret+1;
}

int volume3D(char* rect, int size)
{
    return height3D(rect, size) * width3D(rect, size) * depth3D(rect, size);
}

int area3D(char* rect, int size)
{
    return 2 * heigh3D(rect, size) * width3D(rect, size) + 
           2 * heigh3D(rect, sise) * depth3D(rect, size) + 
           2 * width3D(rect, size) * depth3D(rect, size);
}

Untested, unvalidated, I didn't even compile this. Hell, let's call it pseudo-code.

Philip
  • 1,539
  • 14
  • 23