Calculate Scrabble word scores for double letters

2019-09-18 00:29发布

问题:

My goal here is to create code that takes the letters in a string and gives out a score like in Scrabble. It has to account for double words scores (dictated by a !) and double letter score (dictated by a #).

Example: If you input was 'Hel#lo!', then the first 'l' was played on a
double letter score space, and the final 'o' was played on a            
double word score space. The output score would be 18.

Thanks to help from rayryeng I finally got it to read off the score value if there were no double words or double letters, but now I can't seem to get it to figure out those. If I could have some guidance in how to go about it, I would appreciate it.

doubleword = '#'; %// Here I labeled some things
doubleletter = '!';
doublew = strfind(word, doubleword-1); %// I want to find where the double words are
doublewb = 2;
trouble = strfind(word, doubleletter-1); %// I want to find where double letters are
troubleb = letterPoints*2;
Convert = word;
stringToConvert = lower(Convert);
ASCII = double(stringToConvert) - 96;
Origscore = (sum(values(ASCII)));
score = doublewb*(sum(Origscore)+troubleb);

The last line gives me trouble. I get an array and now just a nice clean number. Furthermore, when I try to run my simple string 'matlab', it gives me an error. Or a really weird, not a simple number. I think I need to do some further indexing, but I'm a little confused. I know this is supposed to be the hardest problem, though I've been struggling with them all. 'Q#uar!tz#ifer#ous!' should give 220. 'Ramblin!gwreck' should give 54.

回答1:

Why hello again! Let's recreate the lookup that we created in our previous post:

string1point = 'aeionrtlsu';
string2point = 'dg';
string3point = 'bcmp';
string4point = 'fhvwy';
string5point = 'k';
string8point = 'jx';
string10point = 'qz';
lookup = zeros(1,26);
lookup(double(string1point) - 96) = 1;
lookup(double(string2point) - 96) = 2;
lookup(double(string3point) - 96) = 3;
lookup(double(string4point) - 96) = 4;
lookup(double(string5point) - 96) = 5;
lookup(double(string8point) - 96) = 8;
lookup(double(string10point) - 96) = 10;

Before we do anything else, we need to lowercase all of the letters in order to access the lookup table.

lowerWord = lower(word);

Once we do this, let's figure out where the double letters and double words are located. You've almost got it right where you want to find which letters are double letters (#) and/or which tiles hit the double words tiles (!). You need to move the 1 outside of the brackets so you can figure out what the actual letter is, not where the symbol is located. In other words:

doublew = strfind(lowerWord, '!') - 1;
doublel = strfind(lowerWord, '#') - 1;

What we need to do now is extract the original string, without any symbols. We can do this by:

originalWord = lowerWord;
originalWord([doublew + 1 doublel + 1]) = [];

I have to add 1 to each of those locations because I want to access where the symbols are located. I use both locations of where the symbols are, then use [] to eliminate those symbols. This should give us our original word. Now, what we're going to do is access what each letter is worth in points in our lookup table and sum up the points. In other words:

ASCII = double(originalWord) - 96;
basePoints = sum(lookup(ASCII));

Right now, the amount of points we have is:

basePoints =

 8

8 points is how many points we have before any adjustment in score. Now, let's tackle each case one at a time:

Double Letters

If you remember from before, doublew and doublel will contain the locations of the letters that are subject to the increase in score.

First, let's figure out what letters are subject to doubling their point value, and figure out where these are in the lookup table and add up how much this score is:

doublelettersInd = double(lowerWord(doublel)) - 96;
sumLetters = sum(lookup(doublelettersInd));

sumLetters will contain the total score of all of these letters subject to be doubled in value. Now here's where it gets tricky. What I'm going to do next is take this score stored in sumLetters and add this on top of the base score (which is 8 in our case). This will effectively take those letters that are to be doubled and double them. Remember, if you add something to itself, you are doubling the value. Because in the base score, I've already added those letters that are just the base score, if I then find those letters that are to be doubled and get the scores of those and add them on top of our original score, I will be doubling the score of the corresponding letters:

doublePoints = basePoints + sumLetters;

Double Words

The last thing you need to do is count how many times we have encountered the double word tile. You would then take this number, and you'd have to use this as the exponent to a power of two as this would effectively show how many times you would need to double. If you hit the double tile once, you double your score (i.e. 2^1 = 2). If you hit the double word tile twice, you would quadruple your score (i.e. 2^2 = 4) , and so on. In other words:

finalPoints = (2^numel(doublew))*doublePoints;

numel counts how many elements are in an array or matrix. As such, the length of doublew will tell us how many times we have encountered a double word tile.

The ^ is important, as this will double correctly. The ^ stands for exponentiation, and this handles what we talked about when correctly doubling your score. This will be able to handle the case where we don't encounter any double word tiles, as 2^0 = 1.

Once we do all this, when you do word = 'Hel#lo!';, with the above code, we get:

finalPoints =

 18

With your other examples, I get:

.... cool? :)

Also, with your above test cases, for Ramblin!gwreck, I get:

finalPoints = 

54

For Q#uar!tz#ifer#ous!, I get:

finalPoints = 

220

To make this all nice so that you can copy and paste this into your editor so you can run it, here's the code in a single code block:

%// Define word here
word = 'Ramblin!gwreck';
%word = 'Q#uar!tz#ifer#ous!';

%// Convert word to lower case
lowerWord = lower(word);

%// Create look up table
string1point = 'aeionrtlsu';
string2point = 'dg';
string3point = 'bcmp';
string4point = 'fhvwy';
string5point = 'k';
string8point = 'jx';
string10point = 'qz';
lookup = zeros(1,26);
lookup(double(string1point) - 96) = 1;
lookup(double(string2point) - 96) = 2;
lookup(double(string3point) - 96) = 3;
lookup(double(string4point) - 96) = 4;
lookup(double(string5point) - 96) = 5;
lookup(double(string8point) - 96) = 8;
lookup(double(string10point) - 96) = 10;

%// Find letters that are either double word or double letter
doublew = strfind(lowerWord, '!') - 1;
doublel = strfind(lowerWord, '#') - 1;

%// Get original word without symbols
originalWord = lowerWord;
originalWord([doublew + 1 doublel + 1]) = [];

%// Get the base points of the word
ASCII = double(originalWord) - 96;
basePoints = sum(lookup(ASCII));

%// Find those letters that need to be doubled in point value
%// and double their score
doublelettersInd = double(lowerWord(doublel)) - 96;
sumLetters = sum(lookup(doublelettersInd));
doublePoints = basePoints + sumLetters;

%// Finally, if we need to double the word score, do it
finalPoints = (2^numel(doublew))*doublePoints;