Search code examples
cartificial-intelligenceconstraint-satisfaction

Zebra puzzle - Constraint Satisfaction in C


I'm trying to read up on constraint satisfaction problems and trying to code them to solve a few sample problems. I came across http://rosettacode.org/wiki/Zebra_puzzle#C.2B.2B to solve the classic zebra puzzle. In the C code given in rosetta code website, There was this following function. I have given only a few lines from it. I didn't know what the purpose of the two if statements is and how they worked. Can someone explain it?

int checkHouses(int ha[5][5])
{
...
    int c_add = 0, c_or = 0;
    int m_add = 0, m_or = 0;
    int d_add = 0, d_or = 0;
    int a_add = 0, a_or = 0;
    int s_add = 0, s_or = 0;

    for (int i = 0; i < 5; i++) {
        // Uniqueness tests.
        if (ha[i][C] >= 0) {
            c_add += (1 << ha[i][C]);
            c_or |= (1 << ha[i][C]);
        }
        if (ha[i][M] >= 0) {
            m_add += (1 << ha[i][M]);
            m_or |= (1 << ha[i][M]);
        }
        if (ha[i][D] >= 0) {
            d_add += (1 << ha[i][D]);
            d_or |= (1 << ha[i][D]);
        }
        if (ha[i][A] >= 0) {
            a_add += (1 << ha[i][A]);
            a_or |= (1 << ha[i][A]);
        }
        if (ha[i][S] >= 0) {
            s_add += (1 << ha[i][S]);
            s_or |= (1 << ha[i][S]);
        }
    }

    if ((c_add != c_or) || (m_add != m_or) || (d_add != d_or)
        || (a_add != a_or) || (s_add != s_or)) {
        return Invalid;
    }

    if ((c_add != 0b11111) || (m_add != 0b11111) || (d_add != 0b11111)
        || (a_add != 0b11111) || (s_add != 0b11111)) {

        return Underfull;
}

Solution

  • The comment actually explains it: they are verifying that there are no duplicate values between ha[0..4][x] for each value of x.

    As to how it is doing it: each value is assigned a bit position, such that 1<<ha[i][x] will yield a number with only the bit in that position set. x_or will be the OR of those values, while x_add is their sum. If there is a duplicate value, it will not have an effect on x_or (that bit is already set), but will on x_add; hence, they will be different.