Friday, May 19, 2017

A String Of Words

 
Copyright: My own work.

 

“I don't know half of you half as well as I should like; and I like less than half of you half as well as you deserve.”                                     Lord of the Rings


This quote summarizes my feeling towards Strings, C-Strings, String objects, ... better than I ever could. Translation: I learned about many aspects of strings and their member functions, but could not deepen my understanding. Many were just left unused in my effort to solve any one Programming Challenge, and those I touched, I hardly scratched the surface, yet would like to learn more about them.

A month plus some days ago I thought differently. Virtually every Challenge past 10.02 was a struggle. In theory what is presented in the Chapter should suffice to solve the challenge. It should, but didn't, because many functions wouldn't work without producing security warnings. As I said in a different chapter summary, I take warnings as errors and treat them as such. For instance take strtok, which takes two arguments, versus strtok_s I had to use in Programming Challenge 10.3 to get an accurate count of words. Another example would be Programming Challenge strcat. This is explained in the book, and looks sufficiently easy to use, but also causes a warning when used in VS. Instead I had to use strcat_s and learn how to use it correctly. Learning by doing was the only way to find out how things work this time around. And, surprisingly, maybe except the Morse Code Challenge, I learned solely about the topic the chapter was about. In the previous one's I learned about a myriad other things besides C++, which I truly enjoy, because one can never know enough, just sometimes too much. 

Speaking of Challenge 03, would you believe that this was the one that caused me to consider skipping the Challenges and moving on to the next chapter? Yes, true, I was stuck and started contemplating whether it is worth it. In the books TOC this chapter was on a side branch, pointing to chapters 10 on the left and 12 on the right hand side. It was not, as you probably think, a case of giving up in the face of a set of tough challenges ahead. It was rather just thinking whether it is truly worth it. What potential use will this chapter have in my future endeavor, creating my own game? After some deliberation with myself I decided that it is worth doing it. I wasn't able to see, as opposed to say with arrays what good they would be for, but why should I care? So I kept working, even though it has taken longer and longer from Challenge to Challenge to finish any one of them.

The most I struggled with this last one. It has taken the better part of 7 days to even find a way to achieve the desired output. From day one I was working to get correct results. Every time it looked like it would work, there was a range of digits that, due to the way I had written that part of code, would not display. For instance everything from 1 to 99, 100 to 199, 1100 to 9999 (and in some revisions up to 99,999.99) would show be displayed perfectly, but 1000 to 1100 would not. The output, if there even was one, would be something like "one thousand hundred eleven one," or "one thousand eleven hundred" and the like.

In one of my earliest attempts I tried solving it by accessing substrings to assign the index to the appropriate string array containing the number words, which looked like this:

 if (numStore < 20)
    {
        toWord.append(oToNine[stoi(amount.substr(1,0))]);
    }

    else if (numStore > 9)
    {
        toWord.append(toTwenty[stoi(amount.substr(1, 1))]);
    }
    else if (numStore > 19)
    {
        toWord.append(tenMult[stoi(amount.substr(0, 1))] +
            oToNine[stoi(amount.substr(1, 1))]);
    }

With lower numbers, this approach could have worked, but getting at the hundreds and thousands, it was a totally different story. Not only would the substring positions constantly change, requiring lots of chained lines of code, it would also have been of very limited use if the next Challenge, had there been any, would be to extend it so amounts above and beyond $9,999.99 would be allowed. After starting over again, the conclusion was that using substrings was part to solve the problem, but simply not in this way, or for this purpose. 

It didn't matter that I changed the approach so that it looks like in the final revision uploaded to this blog, there still remained one problem, a range of numbers would not translate correctly. For instance, consider the following function.

string toThousand(string amount, string *oToNine)
{
    string toWord;

    int tAmnt = stoi(amount);
    if (tAmnt % 100 < 100)
    {
        int wHundred = stoi(amount.substr(0,1));

        toWord.append(oToNine[wHundred] + " hundred ");
    }
    else
    {
        int tHundred = stoi(amount.substr(1, 1));

        toWord.append(oToNine[tHundred] + " hundred ");
    }
    return toWord;
}

With such conditions there would always be some overlap, so that instead of 110, "one hundred ten eleven" would be displayed. Or some other such nonsense that simply wasn't correct. Yet, this part in bold was what eventually led me in the direction of a promising solution. Still it was a long way to get there. Leading to detours such as this piece of code:

 getNum <= 99 ? mTen = ones(stoi(amount)) : mTen = tens(stoi(amount.substr(1, 1)));
 getNum < 10 ? toWord.append(one = ones(stoi(amount.substr(0,1)))) : amount;
 getNum % 10 == 0 ? toWord.append(mTen = tenMult(stoi(amount.substr(0, 1)))) : amount;
 getNum % 10 != 0 ? toWord.append(mTen = tenMult(stoi(amount.substr(0,1))) + one = ones(getNum % 10)) : amount;

Or how about this "beauty"? (Which actually works the way it was written and delivered the correct results for this limited range of numbers between 1 and 99. Hence this is also what I described in my last chapter summary when writing about chained conditional statements.)

  getNum < 10                                 ? one = ones(stoi(amount)) :
  getNum >= 10 && getNum < 20  ? mTen = tens(stoi(amount.substr(1,1))) :
  getNum >= 20                               ? mTen = tenMult(stoi(amount.substr(0,1))),
                                                           one = ones(stoi(amount.substr(1,1))) : amount;

Suffice to say that both of the above was very limited in use, and still another step leading my to a solution. When it finally clicked and I found that when using the modulo operator, not for the conditional statements, but for altering the amounts directly, this would be the way to go and it was. Seven days of hard work with hundreds and hundreds lines of failed code, plus an additional two or almost three days, to arrive at the final solution to the problem that actually worked was a long way to go. It has taken less time than the Monkey Business Challenge and its successor of late, the Median function one, but it felt to me as it has taken twice as long as both taken together!

Now, with all this behind me, my summary is still positive. On the whole it was worth every bit of effort to solve the Challenges and never give up just because the solution wouldn't come easy. I foresee that it will take longer still to get past the upcoming chapters, not even thinking about the Challenges lying in wait for me, but I will not skip any of it. Now past half the book and on my way to Chapter 11, I can only hope, as I always do, that it will not be as bad as this one.

With this, I will mentally prepare myself for whatever there may come, and it is once again my pleasure to thank my regular visitors for coming by, as well as a warm welcome to all my new and future visitors. I would also like to thank all my visitors past and present for their continued interest in my humble interpretation of the Rock-Paper-Scisscors game. I hope you enjoy it! For my fellow learners I hope that you will not be covered head to heel in a web of strings, loosing all hope to ever solve any of the Challenges. Never give up, you can do it, if I could! As for me, I will be back soon, with some more code.

No comments:

Post a Comment