How can I get the following compiled on UVA?

Posted by Michael Tsang on Stack Overflow See other posts from Stack Overflow or by Michael Tsang
Published on 2010-03-28T12:02:17Z Indexed on 2010/03/28 12:03 UTC
Read the original article Hit count: 423

Filed under:
|
|
|

Note the comment below. It cannot compiled on UVA because of a bug in GCC.

#include <cstdio>
#include <cstring>
#include <cctype>
#include <map>
#include <stdexcept>

class Board {
public:
    bool read(FILE *);
    enum Colour {none, white, black};
    Colour check() const;
private:
    struct Index {
            size_t x;
            size_t y;
            Index &operator+=(const Index &) throw(std::range_error);
            Index operator+(const Index &) const throw(std::range_error);
    };
    const static std::size_t size = 8;
    char data[size][size];
    // Cannot be compiled on GCC 4.1.2 due to GCC bug 29993
    // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29993
    typedef bool CheckFunction(Colour, const Index &) const;
    CheckFunction pawn, knight, bishop, king, rook;

    bool queen(const Colour c, const Index &location) const {
            return rook(c, location) || bishop(c, location);
    }

    static char get_king(Colour c) {
            return c == white ? 'k' : 'K';
    }

    template<std::size_t n>
    bool check_consecutive(Colour c, const Index &location, const Index (&offsets)[n]) const {
            for(const Index *p = offsets; p != (&offsets)[1]; ++p) {
                    try {
                            Index target = location + *p;
                            for(; data[target.x][target.y] == '.'; target += *p) {
                            }
                            if(data[target.x][target.y] == get_king(c)) return true;
                    } catch(std::range_error &) {
                    }
            }
            return false;
    }

    template<std::size_t n>
    bool check_distinct(Colour c, const Index &location, const Index (&offsets)[n]) const {
            for(const Index *p = offsets; p != (&offsets)[1]; ++p) {
                    try {
                            Index target = location + *p;
                            if(data[target.x][target.y] == get_king(c)) return true;
                    } catch(std::range_error &) {
                    }
            }
            return false;
    }
};

int main() {
    Board board;
    for(int d = 1; board.read(stdin); ++d) {
            Board::Colour c = board.check();
            const char *sp;
            switch(c) {
            case Board::black:
                    sp = "white";
                    break;
            case Board::white:
                    sp = "black";
                    break;
            case Board::none:
                    sp = "no";
                    break;
            }
            std::printf("Game #%d: %s king is in check.\n", d, sp);
            std::getchar(); // discard empty line
    }
}

bool Board::read(FILE *f) {
    static const char empty[] =
            "........"
            "........"
            "........"
            "........"
            "........"
            "........"
            "........"
            "........";     // 64 dots
    for(char (*p)[size] = data; p != (&data)[1]; ++p) {
            std::fread(*p, size, 1, f);
            std::fgetc(f);  // discard new-line
    }
    return std::memcmp(empty, data, sizeof data);
}

Board::Colour Board::check() const {
    std::map<char, CheckFunction Board::*> fp;
    fp['P'] = &Board::pawn;
    fp['N'] = &Board::knight;
    fp['B'] = &Board::bishop;
    fp['Q'] = &Board::queen;
    fp['K'] = &Board::king;
    fp['R'] = &Board::rook;
    for(std::size_t i = 0; i != size; ++i) {
            for(std::size_t j = 0; j != size; ++j) {
                    CheckFunction Board::* p = fp[std::toupper(data[i][j])];
                    if(p) {
                            Colour ret;
                            if(std::isupper(data[i][j])) ret = white;
                            else ret = black;
                            if((this->*p)(ret, (Index){i, j}/* C99 extension */)) return ret;
                    }
            }
    }
    return none;
}

bool Board::pawn(const Colour c, const Index &location) const {
    const std::ptrdiff_t sh = c == white ? -1 : 1;
    const Index offsets[] = {
            {sh, 1},
            {sh, -1}
    };
    return check_distinct(c, location, offsets);
}

bool Board::knight(const Colour c, const Index &location) const {
    static const Index offsets[] = {
            {1, 2},
            {2, 1},
            {2, -1},
            {1, -2},
            {-1, -2},
            {-2, -1},
            {-2, 1},
            {-1, 2}
    };
    return check_distinct(c, location, offsets);
}

bool Board::bishop(const Colour c, const Index &location) const {
    static const Index offsets[] = {
            {1, 1},
            {1, -1},
            {-1, -1},
            {-1, 1}
    };
    return check_consecutive(c, location, offsets);
}

bool Board::rook(const Colour c, const Index &location) const {
    static const Index offsets[] = {
            {1, 0},
            {0, -1},
            {0, 1},
            {-1, 0}
    };
    return check_consecutive(c, location, offsets);
}

bool Board::king(const Colour c, const Index &location) const {
    static const Index offsets[] = {
            {-1, -1},
            {-1, 0},
            {-1, 1},
            {0, 1},
            {1, 1},
            {1, 0},
            {1, -1},
            {0, -1}
    };
    return check_distinct(c, location, offsets);
}

Board::Index &Board::Index::operator+=(const Index &rhs) throw(std::range_error) {
    if(x + rhs.x >= size || y + rhs.y >= size) throw std::range_error("result is larger than size");
    x += rhs.x;
    y += rhs.y;
    return *this;
}

Board::Index Board::Index::operator+(const Index &rhs) const throw(std::range_error) {
    Index ret = *this;
    return ret += rhs;
}

© Stack Overflow or respective owner

Related posts about c++

Related posts about uva

  • UVA #10410 Tree Reconstruction

    as seen on Stack Overflow - Search for 'Stack Overflow'
    I have worked on UVA 10410 Tree Reconstruction several days. But I can't get the correct answer unitl now. I have used an algorithm similar to the one which we always use to recovery a binary tree through the preorder traversal and the inorder traversal. But it can't work. Can anyone help me? Thanks… >>> More

  • 3n+1 problem at UVa

    as seen on Stack Overflow - Search for 'Stack Overflow'
    Hello, I am having trouble with the first question in the Programming Challenges book by Skiena and Revilla. I keep getting a "Wrong Answer" error message, and I don't know why. I've ran my code against the sample input, and I keep getting the right answer. Anyways, if anyone could help me, I would… >>> More

  • UVa #112 Tree Summing

    as seen on Stack Overflow - Search for 'Stack Overflow'
    I'm working on UVa #112 Tree Summing. I have what I think should be a working solution but it is not accepted by the online judge due to a basic misunderstanding of the problem on my part. Consider the following inputs: -1 (-1()()) 77 (77(1()())()) or diagrammatically, the trees look like: -1… >>> More

  • Uva's 3n+1 problem

    as seen on Stack Overflow - Search for 'Stack Overflow'
    I'm solving Uva's 3n+1 problem and I don't get why the judge is rejecting my answer. The time limit hasn't been exceeded and the all test cases I've tried have run correctly so far. import java.io.*; public class NewClass{ /** * @param args the command line arguments */ … >>> More

  • UVA Online Judge 3n+1 : Right answer is Wrong answer

    as seen on Stack Overflow - Search for 'Stack Overflow'
    Ive been toying with this problem for more than a week now, I have optimized it a lot, I seem to be getting the right answer, since it's the same as when I compare it to other's answers that got accepted, but I keep getting wrong answer. Im not sure what's going on! Anyone have any advice? I think… >>> More