单词博弈(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: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
#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