Project Euler task 42

The nth term of the sequence of triangle numbers is given by, tn = ½n(n+1); so the first ten triangle numbers are:

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...

By converting each letter in a word to a number corresponding to its alphabetical position and adding these values we form a word value. For example, the word value for SKY is 19 + 11 + 25 = 55 = t10. If the word value is a triangle number then we shall call the word a triangle word.

Using words.txt (right click and 'Save Link/Target As...'), a 16K text file containing nearly two-thousand common English words, how many are triangle words?

-------------------------------------------------------------------------

#include
#include

const int MAXNAME = 100;

using namespace std;

__global__ void findTriangleWords(char * _dpNamesArray, char * _dpResult, int _iWordNum, int _iNameLength) {
int nThread = blockIdx.x * blockDim.x + threadIdx.x;

if (nThread >= _iWordNum)
return;

int iSum = 0;
// cycle through the letters
for (int i = 0; i < _iNameLength; i++) {
char c = _dpNamesArray[_iNameLength * nThread + i];
if (c == '\0')
continue;

iSum += (int) c - (int) 'A' + 1;
}

__syncthreads();

int iN = ((int) sqrt(float(1 + 4 * 2 * iSum)) - 1) / 2;
int tN = iN * (iN + 1) / 2;

if (tN == iSum)
_dpResult[nThread] = 1;
else
_dpResult[nThread] = 0;
}

int main() {
ifstream ifs("words.txt", ifstream::in);
char pName[MAXNAME];
size_t iMaxLen = 0;
int iWordNum = 0;

while (!ifs.getline(pName, MAXNAME, '"').eof()) {
if (pName[0] == ',')
continue;

size_t iLen = strlen(pName);
if (iLen > iMaxLen)
iMaxLen = iLen;

iWordNum++;
}

char * pNamesArray = new char[iMaxLen * iWordNum];
memset(pNamesArray, 0, sizeof(char));

ifs.clear();
ifs.seekg(0, ios_base::beg);
iWordNum = 0;
while (!ifs.getline(pName, MAXNAME, '"').eof()) {
if (pName[0] == ',')
continue;

if (!strlen(pName))
continue;

strncpy(&(pNamesArray[iWordNum * iMaxLen]), pName, iMaxLen);

iWordNum++;
}

ifs.close();

// now pNamesArray contains all the necessary names, calling kernel
char * dpNamesArray;
cudaMalloc(&dpNamesArray, iWordNum * iMaxLen * sizeof(char));

// sending array with words into GPU
cudaMemcpy(dpNamesArray, pNamesArray, iWordNum * iMaxLen * sizeof(char), cudaMemcpyHostToDevice);

char * dpResult;
cudaMalloc(&dpResult, iWordNum * sizeof(char));

int threadsPerBlock = 128;
int blocksNum = (iWordNum / threadsPerBlock) + 1;
findTriangleWords <<< blocksNum, threadsPerBlock >>> (dpNamesArray, dpResult, iWordNum, (int) iMaxLen);

// getting back the results from GPU
char * pResult = new char[iWordNum];
cudaMemcpy(pResult, dpResult, iWordNum * sizeof(char), cudaMemcpyDeviceToHost);

cudaFree(dpResult);
cudaFree(dpNamesArray);

// processing results pResult
int sum = 0;
for (int i = 0; i < iWordNum; i++)
sum += (int) pResult[i];

cout << sum << endl;

delete [] pResult;
delete [] pNamesArray;

return 0;
}

Comments

Popular Posts