Exemplo n.º 1
0
Arquivo: solve.c Projeto: MSaito/NumPl
/**
 * 二つのナンプレ盤面配列が等しいか調べる
 * @param a ナンプレ盤面配列1
 * @param b ナンプレ盤面配列2
 * @return 1 等しい
 * @return 0 等しくない
 */
int equal(const numpl_array * a, const numpl_array * b)
{
    for (int i = 0; i < ARRAY_SIZE; i++) {
        if (a->ar[i].symbol != b->ar[i].symbol ||
            a->ar[i].fixed != b->ar[i].fixed ||
            is_single(a->ar[i]) != is_single(b->ar[i])) {
            return 0;
        }
    }
    return 1;
}
Exemplo n.º 2
0
Arquivo: solve.c Projeto: MSaito/NumPl
/**
 * 再帰的解法(実体)
 * 人間的な解法アルゴリズムは使わずに機械的解法で解く
 * 機械的解法で解けないときは、複数候補のあるマスの候補から一つ選んで解けるか試す
 * ということを再帰的に実行する。
 * また、解が複数あるかどうかもチェックする。
 * 解けたときは array に解をセットする。
 * @param array ナンプレ盤面配列
 * @param data 再帰用持ち回しデータ
 * @return -1 矛盾があって解けない
 * @return 1 解けた
 * @return 2 解が複数存在する。
 */
static int recursion_solve_sub(numpl_array * array, recursion_solve_t *data)
{
    numpl_array work;
    work = *array;
    int solved = simple_solve(&work);
    if (solved < 0) {
        return solved;
    }
    solved = is_solved(&work);
    if (solved == 1) {
        if (!data->saved) {
            data->save = work;
            data->saved = 1;
        } else if (!equal(&data->save, &work)) {
            solved = 2;
        }
    }
    if (solved != 0) {
        *array = work;
        return solved;
    }
    int result = -1;
    for (int i = 0; i < ARRAY_SIZE; i++) {
        if (is_single(work.ar[i])) {
            continue;
        }
        cell_t s = work.ar[i];
        for (int j = 0; j < LINE_SIZE; j++) {
            work.ar[i] = s;
            unsigned int mask = s.symbol & (1 << j);
            if (!mask) {
                continue;
            }
            work.ar[i].symbol = mask;
            solved = recursion_solve_sub(&work, data);
            if (solved > 1) {
                *array = work;
                return solved;
            } else if (solved == 1) {
                *array = work;
                result = 1;
            }
        }
        break;
    }
    return result;
}
Exemplo n.º 3
0
void sequence_formatter::log_current_state() const {
    BOOST_LOG_SEV(lg, debug) << "Position: " << position_
                             << " element separator: " << element_separator_
                             << " is first: " << is_first()
                             << " is last: " << is_last()
                             << " is single: " << is_single();

    BOOST_LOG_SEV(lg, debug) << "Prefix configuration: "
                             << prefix_configuration_;
    BOOST_LOG_SEV(lg, debug) << "Value for prefix position: "
                             << value_for_position(prefix_configuration_);

    BOOST_LOG_SEV(lg, debug) << "Postfix configuration: "
                             << postfix_configuration_;
    BOOST_LOG_SEV(lg, debug) << "Value for postfix position: "
                             << value_for_position(postfix_configuration_);
}
Exemplo n.º 4
0
Arquivo: solve.c Projeto: MSaito/NumPl
/**
 * マス1つ分の出力を作る
 * 単一数字か固定なら[]で囲って出力する。そうでなければ候補をすべて出力
 * @param str 出力文字列
 * @param s 出力するマス
 */
static void to_string_detail(char str[3][4], cell_t s)
{
    if (is_single(s) || s.fixed) {
        int i = 1;
        int count = 0;
        for (uint16_t mask = 1; mask < FULL_SYMBOL; mask = mask << 1) {
            if (s.symbol & mask) {
                strcpy(str[0], "   ");
                strcpy(str[2], "   ");
                sprintf(str[1], "[%d]", i);
                count++;
                break;
            }
            i++;
        }
        if (count == 0) {
            strcpy(str[0], "   ");
            if (s.fixed) {
                strcpy(str[1], "$0$");
            } else {
                strcpy(str[1], "!0!");
            }
            strcpy(str[2], "   ");
        }
    } else {
        uint16_t mask = 1;
        char st[LINE_SIZE + 1];
        for (int i = 0; i < LINE_SIZE; i++) {
            if (s.symbol & mask) {
                st[i] = i + '1';
            } else {
                st[i] = ' ';
            }
            mask = mask << 1;
        }
        strncpy(str[0], &st[0], 3);
        strncpy(str[1], &st[3], 3);
        strncpy(str[2], &st[6], 3);
        str[0][3] = '\0';
        str[1][3] = '\0';
        str[2][3] = '\0';
    }
}
Exemplo n.º 5
0
std::string sequence_formatter::
value_for_position(const infix_configuration& ic) const {
    if (is_single()) {
        if (!ic.first().empty()) {
            // when we are single, first takes priority if supplied.
            return ic.first();
        }
        return ic.last();
    } else if (is_first() && !ic.first().empty()) {
        // if is first and first has been supplied, it takes precedence.
        return ic.first();
    } else if (!is_last() && !ic.not_last().empty()) {
        // if we are not last (including first) and not last has been
        // supplied.
        return ic.not_last();
    } else if (!is_first() && (!is_last() || !ic.not_first().empty())) {
        // when we are last, not first takes precedence if supplied.
        return ic.not_first();
    } else if (is_last())
        return ic.last();

    return empty;
}
Exemplo n.º 6
0
/*
 * MAIN
 */
int main(int argc, char *argv[]) {

    int sock_fd;
    int err;
    int optval;
    int conn;
    struct sockaddr_in *addr, *client_addr;
    socklen_t client_addr_size;
    struct hsearch_data *htab;
    pthread_t thread;
    thdata *thread_data = malloc(sizeof(thdata));

    // Create hashmap storage
    htab = calloc(1, sizeof(struct hsearch_data));
    if (hcreate_r(10000, htab) == -1) {
        printf("Error on hcreate\n");
    }

    // Create socket
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (sock_fd == -1) {
        printf("Error creating socket: %d\n", errno);
    }

    // Allow address reuse
    optval = 1;
    err = setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int));
    if (err == -1) {
        printf("Error setting SO_REUSEADDR on socket: %d\n", errno);
    }

    // bind
    addr = calloc(1, sizeof(struct sockaddr_in));
    addr->sin_family = AF_INET;
    addr->sin_port = htons(11211);  // htons: Convert to network byte order
    addr->sin_addr.s_addr = INADDR_ANY;
    err = bind(sock_fd, (struct sockaddr *)addr, sizeof(struct sockaddr));
    free(addr);
    if (err == -1) {
        printf("bind error: %d\n", errno);
    }

    err = listen(sock_fd, 1);
    if (err == -1) {
        printf("listen error: %d\n", errno);
    }

    if (is_single(argc, argv)) {

        client_addr = malloc(sizeof(struct sockaddr_in));
        client_addr_size = sizeof(struct sockaddr);
        conn = accept(sock_fd, (struct sockaddr *)client_addr, &client_addr_size);
        free(client_addr);

        thread_data->conn = conn;
        thread_data->htab = htab;
        handle_conn(thread_data);
        close(conn);

    } else {
        while (1) {

            client_addr = malloc(sizeof(struct sockaddr_in));
            client_addr_size = sizeof(struct sockaddr);
            conn = accept(
                    sock_fd,
                    (struct sockaddr *)client_addr,
                    &client_addr_size);
            free(client_addr);

            thread_data->conn = conn;
            thread_data->htab = htab;
            pthread_create(
                    &thread,
                    NULL,
                    handle_conn,
                    thread_data);
        }
    }

    close(sock_fd);
    free(thread_data);
    hdestroy_r(htab);
    free(htab);

    return 0;
}
Exemplo n.º 7
0
//
// Function:
//      can_follow_poker
// Description:
//      根据请求,检查要出的牌是否合法。如果合法,则将牌的属性保存在pp。(用于接牌)
// Parameter:
//      pp  - 用于保存扑克牌序列的属性
//      vec - 扑克牌的索引数组,其元素为指向POKER的索引,取值范围为0~53
//      num - 索引数组的长度
//      req - 请求出牌的属性
// Return:
//      操作成功返回true,否则返回false.
// Remark:
//      调用者需判断该函数的返回值,若返回false,表示无法判断牌的属性,该组牌
//      为不合法序列。
//      传入的参数 vec 为全局扑克牌的索引,而不是玩家当前牌的索引,否则,调用
//      该函数前需要进行转换。
//
POKER_API 
bool can_follow_poker(POKER_PROPERTY* pp, int vec[], int num, POKER_PROPERTY* req)
{
    int value;

    assert((pp != NULL) && (req != NULL));

    // 当前要出的牌是双王炸弹
    if (is_king_bomb(vec, num, &value)) {
        pp->type = BOMB;
        goto can_follow;
    }

    // 当前要出的牌是炸弹
    if (is_four_bomb(vec, num, &value)) {
        if ((req->type != BOMB) || ((req->type == BOMB) && (value > req->value))) {
            pp->type = BOMB;
            goto can_follow;
        } else {
            return false;
        }
    }

    // 当前要出的牌不是炸弹,但上家的牌是炸弹
    if (req->type == BOMB) {
        return false;
    }
    
    // 上家的牌不是炸弹,当前要打出的牌也不是炸弹
    if (num != req->num) {
        return false;
    }

    //
    // 到这里,说明上家出的牌与当前要出的牌都不是炸弹,并且数量相等,因此,
    // 只需要比较它们的类型和值即可。
    //
    switch (req->type) {
        case SINGLE:
            if (is_single(vec, num, &value)) {
                goto type_matched;
            } else {
                return false;
            }

        case PAIR:
            if (is_pair(vec, num, &value)) {
                goto type_matched;
            } else {
                return false;
            }

        case TRIANGLE:
            if (is_triangle(vec, num, &value)) {
                goto type_matched;
            } else {
                return false;
            }

        case THREE_PLUS_ONE:
            if (is_three_plus_one(vec, num, &value)) {
                goto type_matched;
            } else {
                return false;
            }

        case THREE_PLUS_TWO:
            if (is_three_plus_two(vec, num, &value)) {
                goto type_matched;
            } else {
                return false;
            }

        case FOUR_PLUS_TWO:
            if (is_four_plus_two(vec, num, &value)) {
                goto type_matched;
            } else {
                return false;
            }

        case FOUR_PLUS_FOUR:
            if (is_four_plus_four(vec, num, &value)) {
                goto type_matched;
            } else {
                return false;
            }

        case SERIES:
            if (is_series(vec, num, &value)) {
                goto type_matched;
            } else {
                return false;
            }

        case SERIES_PAIR:
            if (is_series_pair(vec, num, &value)) {
                goto type_matched;
            } else {
                return false;
            }

        case SERIES_TRIANGLE:
            if (is_series_triangle(vec, num, &value)) {
                goto type_matched;
            } else {
                return false;
            }

        case SERIES_THREE_PLUS_ONE:
            if (is_series_three_plus_one(vec, num, &value)) {
                goto type_matched;
            } else {
                return false;
            }

        case SERIES_THREE_PLUS_TWO:
            if (is_series_three_plus_two(vec, num, &value)) {
                goto type_matched;
            } else {
                return false;
            }

        case SERIES_FOUR:
            if (is_series_four(vec, num, &value)) {
                goto type_matched;
            } else {
                return false;
            }

        case SERIES_FOUR_PLUS_TWO:
            if (is_series_four_plus_two(vec, num, &value)) {
                goto type_matched;
            } else {
                return false;
            }

        case SERIES_FOUR_PLUS_FOUR:
            if (is_series_four_plus_four(vec, num, &value)) {
                goto type_matched;
            } else {
                return false;
            }

        default:
            return false;
    }

type_matched:
    if (value <= req->value) {
        return false;
    }

    pp->type = req->type;

can_follow:
    pp->value = value;
    pp->num = num;

    return true;
}
Exemplo n.º 8
0
//
// Function:
//      get_poker_property
// Description:
//      获取出牌的相关属性
// Parameter:
//      pp  - [out] poker property if succeed
//      vec - poker vector to be analyzed. The element are indexes to GLOBAL poker.
//      num - poker num to be analyzed
// Return:
//      E_NONE if everything is OK, else the pokers are not valid.
// Remark:
//      the poker vector in array vec should be sorted in ascend.
//
POKER_RET get_poker_property(POKER_PROPERTY* pp, int vec[], int num)
{
    int value;

    assert(pp != NULL);

    if (is_single(vec, num, &value)) {
        pp->type = SINGLE;
        goto match_succeed;
    } else if (is_pair(vec, num, &value)) {
        pp->type = PAIR;
        goto match_succeed;
    } else if (is_king_bomb(vec, num, &value)) {
        pp->type = BOMB;
        goto match_succeed;
    } else if (is_triangle(vec, num, &value)) {
        pp->type = TRIANGLE;
        goto match_succeed;
    } else if (is_four_bomb(vec, num, &value)) {
        pp->type = BOMB;
        goto match_succeed;
    } else if (is_three_plus_one(vec, num, &value)) {
        pp->type = THREE_PLUS_ONE;
        goto match_succeed;
    } else if (is_three_plus_two(vec, num, &value)) {
        pp->type = THREE_PLUS_TWO;
        goto match_succeed;
    } else if (is_four_plus_two(vec, num, &value)) {
        pp->type = FOUR_PLUS_TWO;
        goto match_succeed;
    } else if (is_four_plus_four(vec, num, &value)) {
        pp->type = FOUR_PLUS_FOUR;
        goto match_succeed;
    } else if (is_series(vec, num, &value)) {
        pp->type = SERIES;
        goto match_succeed;
    } else if (is_series_pair(vec, num, &value)) {
        pp->type = SERIES_PAIR;
        goto match_succeed;
    } else if (is_series_triangle(vec, num, &value)) {
        pp->type = SERIES_TRIANGLE;
        goto match_succeed;
    } else if (is_series_three_plus_one(vec, num, &value)) {
        pp->type = SERIES_THREE_PLUS_ONE;
        goto match_succeed;
    } else if (is_series_three_plus_two(vec, num, &value)) {
        pp->type = SERIES_THREE_PLUS_TWO;
        goto match_succeed;
    } else if (is_series_four(vec, num, &value)) {
        pp->type = SERIES_FOUR;
        goto match_succeed;
    } else if (is_series_four_plus_two(vec, num, &value)) {
        pp->type = SERIES_FOUR_PLUS_TWO;
        goto match_succeed;
    } else if (is_series_four_plus_four(vec, num, &value)) {
        pp->type = SERIES_FOUR_PLUS_FOUR;
        goto match_succeed;
    } else {
        return E_INVALID;
    }

match_succeed:
    pp->value = value;
    pp->num = num;

    return E_NONE;
}