单词博弈(http://hero.csdn.net/Question/Details?ExamID=163&ID=168&bsh_bid=323983132)
甲乙两个人用一个英语单词玩游戏。两个人轮流进行,每个人每次从中删掉任意一个字母,如果剩余的字母序列是严格单调递增的(按字典序a < b < c <....<z),则这个人胜利。两个人都足够聪明(即如果有赢的方案,都不会选输的方案 ),甲先开始,问他能赢么?
输入: 一连串英文小写字母,长度不超过15,保证最开始的状态不是一个严格单增的序列。
输出:1表示甲可以赢,0表示甲不能赢。
例如: 输入 bad, 则甲可以删掉b或者a,剩余的是ad或者bd,他就赢了,输出1。
又如: 输入 aaa, 则甲只能删掉1个a,乙删掉一个a,剩余1个a,乙获胜,输出0。
结果正确,效率没别人高(虽然最后时刻还加了一个缓存进去)。
为这题目专门看了好几天的博弈论算法(五子棋什么的),不过到最后发现可以如此简单的实现(也没用上那些算法)。
在群里见有人讨论时提到α分支裁剪什么的,太高深了我没投入过多精力去研究。
#include <iostream>
#include <string>
#include <map>
using namespace std;
bool is_ordered(const string& word)
{
if (word.length() <= 1)
return true;
bool order = true;
for (int i = 1; i < word.length(); i++) {
if (word[i] > word[i-1]) {
continue;
} else {
order = false;
break;
}
}
return order;
}
typedef map<string, bool> CacheMap;
CacheMap cachemap;
//check: at this point (word), i will win absolutely (i has one or more path to win)
//once a next point is failed for competitor, return true; all next points are successful for competitor, return false
bool check_success(const string& word)
{
//query cahce first
CacheMap::iterator it = cachemap.find(word);
if (it != cachemap.end()) {
return it->second;
}
if (is_ordered(word)) {
cachemap[word] = false;
return false;
}
for (int i = 0; i < word.length(); i++) {
string nextword(word);
nextword.erase(i,1);
if (!check_success(nextword)) {
cachemap[word] = true;
return true;
}
}
cachemap[word] = false;
return false;
}
int who(string word)
{
return int(check_success(word));
}
int main(int argc, char** argv)
{
char* tests[] = {"phqghumeaylnlfd",
"xfircvscxggbwkf",
"nqduxwfnfozvsrt",
"kjprepggxrpnrvy",
"stmwcysyycqpevi",
"keffmznimkkasvw",
"srenzkycxfxtlsg",
"ypsfadpooefxzbc",
"oejuvpvaboygpoe",
"ylfpbnpljvrvipy",
"amyehwqnqrqpmxu",
"jjloovaowuxwhms",
"ncbxcoksfzkvatx",
"dknlyjyhfixjswn",
"kkufnuxxzrzbmnm",
"gqooketlyhnkoau",
"gzqrcddiuteiojw",
"ayyzpvscmpsajlf",
"vgubfaaovlzylnt",
"rkdcpwsrtesjwhd"};
for (int index = 0; index < sizeof(tests)/sizeof(char*); index++)
printf("%s --> %d\n", tests[index], who(tests[index]));
getchar();
return 0;
}
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面是kabam game server(backend) c++编程测试题(前面都通关了,最后卡在跟老外项目制作人的英语交流上铩羽而归)
Question 2
Read the comments and code for the data structures in the file OrderedDatabase.cpp then implement these functions:A) OrderedDatabase::LinkInOrder
B) OrderedDatabase::SwapRecordValue
C) TestOrderedDatabase
Follow these coding guidelines:
1) All code needed to complete the task must be in the file provided.
2) Do not change the function prototypes or class variable declarations.
3) You can write additional helper functions to complete the task.
4) Include appropriate comments in your code.
5) Ensure that your code compiles and runs without crashing for all valid input.
6) Use asserts (defined in <assert.h>) to enforce your assumptions
#include <assert.h>
#include <stdio.h>
///
// struct Record
// In this question we will work with a database of data records. Each record holds
// an integer value. These values will be random, and not necessarily unique.
// The records also contains a pointer m_next which will be used to link records together.
///
struct Record
{
int m_value; // Value stored in the record.
Record* m_next; // Pointer used to link the records.
};
///
// class Database
// The records are stored in a database. The database consists of a variable
// number of arrays of records. The number of arrays is given by m_arrayCount.
// Each array must have the same number of records in it, given by m_arraySize.
//
// For example, this code initializes a database with 3 arrays that each contain 5 records.
// The m_value fields are just random.
//
// Record array0[5] = {{ 4, 0}, { 89, 0}, {189, 0}, { 76, 0}, {200, 0}};
// Record array1[5] = {{205, 0}, { 37, 0}, { 66, 0}, {105, 0}, { 13, 0}};
// Record array2[5] = {{ 13, 0}, {241, 0}, {158, 0}, { 22, 0}, {140, 0}};
// Record* arrays[3] = {array0, array1, array2};
// Database database(3, 5, arrays);
///
class Database
{
public:
Database(int arrayCount, int arraySize, Record** arrays)
: m_arrayCount(arrayCount), m_arraySize(arraySize), m_arrays(arrays)
{
}
Record** m_arrays;
int m_arrayCount;
int m_arraySize;
};
///
// class OrderedDatabase
// This subclass of Database keeps all of the records in order by their m_value variable,
// from smallest to largest. The records stay in their original location in memory, but are
// linked together in order using their m_next pointer. The first record in the ordering,
// i.e. the one with the smallest m_value, is pointed to by m_firstRecord.
//
// The function LinkInOrder initializes the links between the records.
// The function SwapRecordValue replaces one value in the database with another.
///
class OrderedDatabase : public Database
{
public:
OrderedDatabase(int arrayCount, int arraySize, Record** arrays)
: Database(arrayCount, arraySize, arrays)
{
LinkInOrder();
}
void LinkInOrder();
void SwapRecordValue(int oldValue, int newValue);
void PrintValues();
Record* m_firstRecord;
private:
Record* FetchPrevRecord(int value);
};
///
// Part A)
//
// Name: void OrderedDatabase::LinkInOrder();
//
// Input:
// The database must be initialized and have m_arrays, m_arrayCount and m_arraySize values set.
// Make no assumptions about how the Record m_next pointers are initially set.
//
// Output:
// The function should use the m_next pointers of the database records to link them together
// in sorted order by m_value, from smallest to largest. It should set m_firstRecord to be a
// pointer to the first record in the chain. The last record in the chain should have
// m_next == 0.
//
// Eg:
// For the example Database shown above, the OrderedDatabase would be linked like this:
// m_firstRecord->4->13->13->22->37->66->76->89->105->140->158->189->200->205->241->0
//
// Specifications:
// This code will run only at initialization time, so it is not called very often.
// Your algorithm should complete in O(n2) time and use O(1) memory.
// Your code should not crash as long as the database meets the specifications above.
///
void
OrderedDatabase::LinkInOrder()
{
//initialize m_next
for (int i = 0; i < m_arrayCount; i++) {
for(int j = 0; j < m_arraySize; j++) {
((*(m_arrays+i))+j)->m_next = 0;
}
}
m_firstRecord = 0; //the beginning of the sorted chain
Record* nextPtr = 0; //the end of the sorted chain
for (int count = 0; count < m_arrayCount*m_arraySize; count++) {
Record* smallPtr = 0; //the smallest record of the unsorted ones
for (int i = 0; i < m_arrayCount; i++){
for (int j = 0; j < m_arraySize; j++) {
Record* tmpPtr = (*(m_arrays+i))+j;
//found the first unsorted record
if (!smallPtr && (tmpPtr->m_next==0) && (tmpPtr!=nextPtr)) {
smallPtr = tmpPtr;
continue;
}
//found the smaller record in the unsorted ones
if (smallPtr && (tmpPtr->m_next==0) && (tmpPtr!=nextPtr) && (tmpPtr->m_value<smallPtr->m_value)) {
smallPtr = tmpPtr;
}
}
}
assert( smallPtr );
if (!m_firstRecord) {
nextPtr = m_firstRecord = smallPtr;
} else {
nextPtr->m_next = smallPtr;
nextPtr = smallPtr;
}
}
}
///
// Part B)
//
// Name: void OrderedDatabase::SwapRecordValues(int oldValue, int newValue);
//
// Input:
// Assuming that the database is already linked using the LinkInOrder() function.
//
// Output:
// The function should find all records that have m_value equal to oldValue and change
// their value to newValue. The links in the database should be fixed to maintain the sorted
// ordering.
//
// Eg:
// If the database is linked up so like this:
// m_firstRecord->4->13->13->22->37->66->76->89->105->140->158->189->200->205->241->0
//
// Calling:
// database.SwapRecordValue(13, 2);
//
// Will result in the database being like this:
// m_firstRecord->2->2->4->22->37->66->76->89->105->140->158->189->200->205->241->0
//
// Specifications:
// This function will be called on a large database several times per frame of the
// videogame, so performance is critical. It needs to be as fast as possible.
// Your algorithm should use O(1) memory.
// Your code should not crash as long as the database meets the specifications above.
///
void
OrderedDatabase::SwapRecordValue(int oldValue, int newValue)
{
if (!m_firstRecord || (m_firstRecord->m_value>oldValue) || (oldValue==newValue))
return;
//look for records equal to oldValue
Record* oldPrev = 0; //old pos
Record* newPrev = 0; //new pos
Record* ptr = m_firstRecord; //record to analyze
bool foundNewPrev = false; //avoid the duplicate seekings
while(ptr && ptr->m_value<=oldValue) {
if (ptr->m_value == oldValue) {
//look for newposition
if (!foundNewPrev) {
newPrev = FetchPrevRecord(newValue);
foundNewPrev = true;
}
//change value
ptr->m_value = newValue;
//"pos unchanged" or "new pos is old pos's left side" or "new pos is old pos's right side"
if ((newPrev==oldPrev) || (newPrev&&(newPrev->m_next==ptr||newPrev==ptr))) {
;
}else {
//delete from old position
if (!oldPrev) {
m_firstRecord = ptr->m_next;
} else {
oldPrev->m_next = ptr->m_next;
}
//add to new position
if (!newPrev) {
ptr->m_next = m_firstRecord;
m_firstRecord = ptr;
}else {
ptr->m_next = newPrev->m_next;
newPrev->m_next = ptr;
}
}
//ptr for next loop
if (!oldPrev) {
ptr = m_firstRecord;
}else {
ptr = oldPrev->m_next;
}
//not found
} else {
oldPrev = ptr;
ptr = ptr->m_next;
}
}
}
///
//
//look for the biggest record of the ones whose value < "value"
//
///
Record*
OrderedDatabase::FetchPrevRecord(int value)
{
assert(m_firstRecord);
if (m_firstRecord->m_value >= value)
return 0;
Record* newPrev = m_firstRecord;
while (newPrev->m_next && newPrev->m_next->m_value<value)
newPrev = newPrev->m_next;
return newPrev;
}
void
OrderedDatabase::PrintValues()
{
if (m_arrayCount*m_arraySize == 0) {
printf("empty\n\n");
return;
}
printf("unsorted values:\n");
for(int i = 0; i < m_arrayCount; i++) {
for (int j = 0; j < m_arraySize; j++) {
printf("%10d", ((*(m_arrays+i))+j)->m_value);
}
printf("\n");
}
printf("sorted values:\n");
Record* ptr = m_firstRecord;
int index = 1;
while (ptr) {
printf("%10d", ptr->m_value);
if (index%m_arraySize == 0)
printf("\n");
ptr = ptr->m_next;
index++;
}
printf("\n");
}
///
// Part C)
//
// Name: void TestOrderedDatabase(void);
//
//
// Specifications:
// Write test cases for the LinkInOrder and SwapRecordValue functions in OrderedDatabase
// to show that the functions meet the specifications.
///
void
TestOrderedDatabase()
{
OrderedDatabase* db = 0;
{
db = new OrderedDatabase(1, 0, 0);
db->PrintValues();
delete db;
}
{
db = new OrderedDatabase(0, 0, 0);
db->PrintValues();
delete db;
}
{
Record r1[3] = {{1,0}, {3,0}, {2,0}};
Record r2[3] = {{3,0}, {6,0}, {5,0}};
Record* records[2] = {r1, r2};
db = new OrderedDatabase(2, 3, records);
db->PrintValues();
printf("swap 3 to 9...\n");
db->SwapRecordValue(3, 9);
db->PrintValues();
printf("swap 9 to -1...\n");
db->SwapRecordValue(9, -1);
db->PrintValues();
printf("swap 6 to 6...\n");
db->SwapRecordValue(6, 6);
db->PrintValues();
printf("swap 100 to 10...\n");
db->SwapRecordValue(100, 10);
db->PrintValues();
delete db;
}
{
Record r1[1] = {{1,0}};
Record* records[1] = {r1};
db = new OrderedDatabase(1, 1, records);
db->PrintValues();
printf("swap 3 to 9...\n");
db->SwapRecordValue(3, 9);
db->PrintValues();
printf("swap 1 to 100...\n");
db->SwapRecordValue(1, 100);
db->PrintValues();
printf("swap 100 to 10...\n");
db->SwapRecordValue(100, 10);
db->PrintValues();
delete db;
}
}
// #define MAIN_DEBUG
// #ifdef MAIN_DEBUG
// int main(int argc, char** argv)
// {
// TestOrderedDatabase();
// getchar();
// return 0;
// }
// #endif
Question 4
This question is optional for junior programmers. Applicants for senior programming position MUST complete this question.
Read the comments and code for the data structures in the file ReverseWords.cpp then implement these functions:
A) ReverseWords
B) ReverseWordsInPlace
C) TestReverseWords
Follow these coding guidelines:
1) All code needed to complete the task must be in the file provided.
2) Do not change the function prototypes or class variable declarations.
3) You can write additional helper functions to complete the task.
4) Include appropriate comments in your code.
5) Ensure that your code compiles and runs without crashing for all valid input.
6) Use asserts (defined in <assert.h>) to enforce your assumptions
#include <assert.h>
#include <stdio.h>
///
// Part A)
//
// Name: void ReverseWords(char* inputString, char* outputString);
//
// Input:
// inputString: A NULL terminated character string consisting of words separated
// by a single whitespace.
// outputString: A buffer with enough space to store a copy of inputString.
//
// Output:
// outputString should have the same words as inputString, but with the words in reverse order.
// The letters in each word should not be reversed.
//
// For example:
// char* inputString = "Hello this is my BalancedWorlds programming TEST";
// char outputString[256];
// ReverseWords(inputString, outputString);
// Will result in outputSting being:
// "TEST programming BalancedWorlds my is this Hello"
//
// Important Specifications:
// Your code should work with the character data directly. Do NOT use the C++ string class or
// any standard library string manipulation functions such as sprintf, sscanf, etc.
//
// Your algorithm should complete in O(n) time and use O(1) memory. In other words, you may only
// use a constant amount of memory that does NOT depend on the size of the string or lengths
// of the words. The memory should be declared on the stack, not using dynamic allocations.
///
void ReverseWords(const char* inputString, char* outputString)
{
if (!inputString)
return;
//int len = strlen(inputString);
int len = 0;
while (*(inputString+len))
len++;
if (len == 0) {
*outputString = '\0';
return;
}
char* writePtr = outputString;
int start = -1; //the beginning of word
//scan inputString from end to begging
for (int cursor = len - 1; cursor >= 0; cursor--) {
char c = *(inputString+cursor);
//looking for the beginning of word
if (start == -1) {
if (c != ' ') { //found
start = cursor;
} else { //not found
*writePtr = c;
writePtr++;
}
}
//looking for the end of word
if (start != -1) {
if ((c==' ') || (cursor==0)) { //found
//calc word length and read position
int realCursor;
int wordLen;
if (cursor != 0) {
realCursor = cursor + 1;
wordLen = start - cursor;
} else {
realCursor = cursor;
wordLen = start - cursor + 1;
}
//copy the word from inputString to outputString
for (int i = 0; i < wordLen; i++) {
*writePtr = *(inputString + realCursor + i);
writePtr++;
}
//copy the blank char
if (cursor != 0) {
*writePtr = c;
writePtr++;
}
//reset start
start = -1;
} else { //not found
;
}
}
}
*writePtr = '\0';
}
void ReverseChars(char* begin, char* end)
{
char c;
while (begin < end)
{
c = *begin;
*begin++ = *end;
*end-- = c;
}
}
///
// Part B)
//
// Name: void ReverseWordsInPlace(char* string);
//
// Input:
// string: A NULL terminated character string consisting of words separated
// by a single whitespace.
//
// Output:
// The same as ReverseWords(), except that the result is returned in inputString.
//
// Specifications:
// Your code should work with the character data directly. Do NOT use the C++ string class or
// any standard library string manipulation functions such as sprintf, sscanf, etc.
//
// Your algorithm should complete in O(n) time and use O(1) memory. In other words, you may only
// use a constant amount of memory that does NOT depend on the size of the string or lengths
// of the words. The memory should be declared on the stack, not using dynamic allocations.
///
void ReverseWordsInPlace(char* inputString)
{
if (!inputString)
return;
//int len = strlen(inputString);
int len = 0;
while (*(inputString+len))
len++;
if (len == 0)
return;
int wordStart = -1;
char* ptr = inputString;
//reverse chars in word
for (ptr = inputString; *ptr; ptr++) {
//look for the beginning of word
if (wordStart == -1) {
if (*ptr != ' ') //found
wordStart = ptr - inputString;
}
//look for the end of word
if (wordStart != -1) {
if (*ptr == ' ') { //found
ReverseChars(inputString+wordStart, ptr-1);
wordStart = -1;
}
}
}
assert(!*ptr);
if (wordStart != -1)
ReverseChars(inputString+wordStart, ptr-1);
//reverse chars in string
ReverseChars(inputString, ptr-1);
}
void ReverseAndPrintf(const char* src, char* dst)
{
ReverseWords(src, dst);
printf("src :\"%s\"\n", src);
printf("dst :\"%s\"\n", dst);
ReverseWordsInPlace(dst);
printf("dst2:\"%s\"\n", dst);
printf("\n");
}
///
// Part C)
//
// Name: void TestReverseWords(void);
//
//
// Specifications:
// Write test cases for both ReverseWords and ReverseWordsInPlace to show that
// the functions meet the specifications.
///
void TestReverseWords(void)
{
{
const char* src = "hello world !";
char dst[14];
ReverseAndPrintf(src, dst);
}
{
const char* src = "a";
char dst[2];
ReverseAndPrintf(src, dst);
}
{
const char* src = "a ";
char dst[3];
ReverseAndPrintf(src, dst);
}
{
const char* src = "a ";
char dst[4];
ReverseAndPrintf(src, dst);
}
{
const char* src = " a";
char dst[3];
ReverseAndPrintf(src, dst);
}
{
const char* src = " ";
char dst[2];
ReverseAndPrintf(src, dst);
}
{
const char* src = "";
char dst[1];
ReverseAndPrintf(src, dst);
}
{
const char* src = "a b c ";
char dst[8];
ReverseAndPrintf(src, dst);
}
}
// #define MAIN_DEBUG
// #ifdef MAIN_DEBUG
// int main(int argc, char** argv)
// {
// TestReverseWords();
// getchar();
// return 0;
// }
// #endif
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
c切割字符和窜并存入数组
#include <string.h>
#include <stdlib.h>
#include <assert.h>
char ** array_string_split(const char *s, const char *sep)
{
//分隔符不能是'\0'
int buffer_len = 4;
char** buffer = (char**)malloc(sizeof(char*)*buffer_len);
int index = 0;
char* base_str = strdup(s);
char* str = base_str;
while (str != NULL) {
char* tmp_token = strsep(&str, sep);
if (strlen(tmp_token) > 0) {
if (index >= buffer_len-1) {
buffer_len *= 2;
char** tmp_buffer = (char**)malloc(sizeof(char*)*buffer_len);
assert(tmp_buffer);
memcpy(tmp_buffer, buffer, index*sizeof(char*));
free(buffer);
buffer = tmp_buffer;
}
*(buffer+index) = strdup(tmp_token);
index++;
}
}
*(buffer+index) = NULL;
free(base_str);
return buffer;
}
int array_string_search(/*const*/ char *array[], const char *needle)
{
int index = 0;
while (array[index] != NULL) {
if (strcmp(array[index],needle) == 0)
return index;
index++;
}
return -1;
}
void array_string_free(/*const */char *array[])
{
char** ptr = array;
while(*ptr != NULL) {
free(*ptr);
ptr++;
}
free(array);
}
#ifdef TEST
#include <stdio.h>
int main(int argc, char** argv)
{
char str[1024];
char sep[100];
printf("input your string:\n");
scanf("%s", str);
printf("inbput your sep:\n");
scanf("%s",sep);
char** tokens = array_string_split(str,sep);
char** token = tokens;
while(*token != NULL) {
printf("%s\n",*token);
token++;
}
char tmp[100];
while(1) {
printf("find (input 'exit!' to break.) > ");
scanf("%s",tmp);
if (strcmp(tmp,"exit!") == 0)
break;
printf("index = %d.\n",array_string_search(tokens,tmp));
}
array_string_free(tokens);
}
#endif
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
linux c++ -> ls
#include <dirent.h>
void ls(const char* path, vector<string>& files)
{
DIR* dp;
dirent *d;
dp = opendir(path);
while ((d=readdir(dp)) != NULL){
if (!string(d->d_name).compare(".") || !string(d->d_name).compare(".."))
continue;
files.push_back(string(d->d_name));
}
}
readdir非线程安全,应该改成readdir_r