Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 117 additions & 4 deletions src/adagrams.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,128 @@
const LETTER_POOL = {
'A': 9,
'B': 2,
'C': 2,
'D': 4,
'E': 12,
'F': 2,
'G': 3,
'H': 2,
'I': 9,
'J': 1,
'K': 1,
'L': 4,
'M': 2,
'N': 6,
'O': 8,
'P': 2,
'Q': 1,
'R': 6,
'S': 4,
'T': 6,
'U': 4,
'V': 2,
'W': 2,
'X': 1,
'Y': 2,
'Z': 1
};

const SCORE_CHART_DICT = {
1: ['A', 'E', 'I', 'O', 'U', 'L', 'N', 'R', 'S', 'T'],
2: ['D', 'G'],
3: ['B', 'C', 'M', 'P'],
4: ['F', 'H', 'V', 'W', 'Y'],
5: ['K'],
8: ['J', 'X'],
10: ['Q','Z']
};

export const drawLetters = () => {
// Implement this method for wave 1
const arrLetterPool = [];

// Convert letterPool to list
for (let [letter, frequency] of Object.entries(LETTER_POOL)) {
let countLetters = 0;
while (countLetters < frequency) {
arrLetterPool.push(letter);
countLetters++;
}
Comment on lines +45 to +49

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we didn't want to manage the count ourself, a for loop would work great here:

for (let [letter, frequency] of Object.entries(LETTER_POOL)) {
    for (let i = 0; i < frequency; i++) {
        arrLetterPool.push(letter);
    }
}

}

const drawnLetters = [];

while (drawnLetters.length < 10) {
let randomLetter = Math.floor(Math.random() * arrLetterPool.length);
let removedLetter = arrLetterPool.splice(randomLetter, 1)[0];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great use for splice! Another way to get the single value from what splice returns is with array unpacking syntax:

    const [removedLetter] = availablePool.splice(randomIndex, 1);

drawnLetters.push(removedLetter);
}

return drawnLetters;
};

// Test code
// console.log(drawLetters());

export const usesAvailableLetters = (input, lettersInHand) => {
// Implement this method for wave 2
};
let lettersInHandCopy = Array.from(lettersInHand);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another common syntax for copying arrays is the spread operator ...:

const lettersInHandCopy = [...lettersInHand];


for (let i = 0; i < input.length; i++) {
const currentLetter = input[i];
//Line below is needed because the letterIndex is what is used to loop through the lettersInHandCopy array
//If the currentLetter is not found, indexOf() returns -1.
const letterIndex = lettersInHandCopy.indexOf(currentLetter)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indexOf needs to scan through a list to find the element to return the index, what is the time complexity of this function overall? What strategies could we use to try and reduce the complexity?

if (letterIndex !== -1) {
lettersInHandCopy.splice (letterIndex, 1);
} else {
return false;
}
}
return true;
}

export const scoreWord = (word) => {
// Implement this method for wave 3
let score = 0;

if (word.length >= 7) {
score += 8;
}
Comment on lines +86 to +88

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be a great place for a ternary operator:

// Ternary operator structure: 
// var = (conditional) ? (value if true) : (value if false)
score = (word.length >= 7) ? (score + 8) : score


const wordUpper = word.toUpperCase();

for (let letter of wordUpper) {
for (let [points, letters] of Object.entries(SCORE_CHART_DICT)) {
if (letters.includes(letter)) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to use the current data formatting of SCORE_CHART_DICT, I would strongly consider changing SCORE_CHART_DICT to use sets for the values to store the letters for each score key so that we can check for membership in O(1) time. When they are arrays includes will scan through each element in the list to check for membership.

score += parseInt(points);
}
}
}
return score;
};

export const highestScoreFrom = (words) => {
// Implement this method for wave 4
const scoresObj = {};
for (let word of words) {
scoresObj[word] = scoreWord(word);
}

let highScore = 0;
let shortestWord = "";

for (let [word, score] of Object.entries(scoresObj)) {
if (score > highScore) {
highScore = score;
shortestWord = word;
} else if (score === highScore) {
if (shortestWord.length === 10) {
shortestWord = shortestWord;
} else if (word.length === 10) {
shortestWord = word;
} else if (word.length < shortestWord.length) {
shortestWord = word;
Comment on lines +117 to +122

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the result is no change for the first conditional, we could refactor to remove the assignment of shortestWord to itself. There are many ways to approach it, one option is to use variables to represent the conditionals we need to consider:

const isBestTen = shortestWord.length === 10
const isWordTen = word.length === 10
const isWordShorter = word.length < shortestWord.length
if ((isWordTen && !isBestTen) || (isWordShorter && !isBestTen)) {
    shortestWord = word;
}

}
}
}
const winningScore = { "score": highScore, "word": shortestWord };
return winningScore;
};
18 changes: 15 additions & 3 deletions test/adagrams.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ const LETTER_POOL = {
Z: 1,
};

const SCORE_CHART_DICT = {
1: ['A', 'E', 'I', 'O', 'U', 'L', 'N', 'R', 'S', 'T'],
2: ['D', 'G'],
3: ['B', 'C', 'M', 'P'],
4: ['F', 'H', 'V', 'W', 'Y'],
5: ['K'],
8: ['J', 'X'],
10: ['Q','Z']
};

describe("Adagrams", () => {
describe("drawLetters", () => {
it("draws ten letters from the letter pool", () => {
Expand Down Expand Up @@ -120,7 +130,9 @@ describe("Adagrams", () => {
});

it("returns a score of 0 if given an empty input", () => {
throw "Complete test";
expectScores({
"" : 0
});
});

it("adds an extra 8 points if word is 7 or more characters long", () => {
Expand All @@ -133,7 +145,7 @@ describe("Adagrams", () => {
});
});

describe.skip("highestScoreFrom", () => {
describe("highestScoreFrom", () => {
it("returns a hash that contains the word and score of best word in an array", () => {
const words = ["X", "XX", "XXX", "XXXX"];
const correct = { word: "XXXX", score: scoreWord("XXXX") };
Expand All @@ -145,7 +157,7 @@ describe("Adagrams", () => {
const words = ["XXX", "XXXX", "X", "XX"];
const correct = { word: "XXXX", score: scoreWord("XXXX") };

throw "Complete test by adding an assertion";
expect(highestScoreFrom(words)).toEqual(correct);
});

describe("in case of tied score", () => {
Expand Down
2 changes: 1 addition & 1 deletion test/demo/model.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Model from 'demo/model';
import Adagrams from 'demo/adagrams';

describe.skip('Game Model', () => {
describe('Game Model', () => {
const config = {
players: [
'Player A',
Expand Down