/** * 二つのナンプレ盤面配列が等しいか調べる * @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; }
/** * 再帰的解法(実体) * 人間的な解法アルゴリズムは使わずに機械的解法で解く * 機械的解法で解けないときは、複数候補のあるマスの候補から一つ選んで解けるか試す * ということを再帰的に実行する。 * また、解が複数あるかどうかもチェックする。 * 解けたときは 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; }
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_); }
/** * マス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'; } }
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; }
/* * 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; }
// // 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; }
// // 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; }