Skip to content

Sunitha-Sphinx-JS Adagrams #30

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
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
135 changes: 135 additions & 0 deletions src/adagrams.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,150 @@
/*constructing a leeterpool object with letter as key and no. of times it can be drawn as value*/
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,
};

export const drawLetters = () => {

Choose a reason for hiding this comment

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

Overall, I'd prefer the logic related to creating an entire pool of letters to be in its own helper function. Something like:

export const createLetterPool = () =>
  const listOfAllLetters = [];

  for (const [letter, letterFrequency] of Object.entries(LETTERPOOL)) {
    for (let i = 0; i < letterFrequency; i++) {
      listOfAllLetters.push(letter);
    }
  }

  return listOfAllLetters;
}

Then the logic in drawLetters is only responsible for drawing a hand of ten letters and can invoke createLetterPool.

How could we simplify the code for drawLetters? What if you generate a random index and use it to access a random letter in your letter pool array and add it to drawnLetters. After that you can use a strategy of virtually "dividing" the list of all letters in a letter pool array into a 'used' and 'unused' side. Then you can swap a value to the used side.

export const drawLetters = () => {
  // invoke createLetterPool
  // get random index
  // get random letter from letter pool and add to drawnLetters list
  // swap random letter from unused side to used side of your letter pool
}

This can be done in 4 lines and would be a little easier to understand.

// Implement this method for wave 1
const drawnLetters = [];

Choose a reason for hiding this comment

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

Nice job using const here!

//Evaluating total size of probable letters can be drawn
let totalSize = Object.values(LETTERPOOL).reduce((acc, val) => acc + val, 0);
let letterPoolArr = Object.entries(LETTERPOOL);
let count = 0;
let letterIdx;
const HAND_SIZE = 10;

while (drawnLetters.length < handSize) {
if (totalSize === 0) {
console.log('No more letters available to draw.');
break;
}

letterIdx = Math.random() * totalSize;
for (const [letter, frequency] of letterPoolArr) {
count += frequency;
if (letterIdx < count) {
drawnLetters.push(letter);
totalSize -= 1;
//updating array with already drawn letters
const updatedArr = letterPoolArr.map(([l, freq]) =>
l === letter ? [l, freq - 1] : [l, freq]
Comment on lines +54 to +55

Choose a reason for hiding this comment

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

These two lines are pretty jam packed with logic which makes it a little challenging to decipher. I'd prefer l to have a more descriptive name to make it easier to read.

);
letterPoolArr = updatedArr.filter(([l, freq]) => freq > 0);
break;
}
}
}
return drawnLetters;
};

export const usesAvailableLetters = (input, lettersInHand) => {
// Implement this method for wave 2
const letterObj = {};
for (let letter of lettersInHand.toUpperCase()) {
letterObj[letter] ? letterObj[letter]++ : (letterObj[letter] = 1);
}
//Utilizing object to track the letters drawn
for (let letter of input.toUpperCase()) {
if (letterObj[letter] === undefined || letterObj[letter] === 0)
return false;
else {
letterObj[letter] -= 1;
}
}
return true;
};

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

const LETTER_SCORES = {
A: 1,
E: 1,
I: 1,
O: 1,
U: 1,
L: 1,
N: 1,
R: 1,
S: 1,
T: 1,
D: 2,
G: 2,
B: 3,
C: 3,
M: 3,
P: 3,
F: 4,
H: 4,
V: 4,
W: 4,
Y: 4,
K: 5,
J: 8,
X: 8,
Q: 10,
Z: 10,
};
word = word.toUpperCase();
let totalScore = 0;

for (let i = 0; i < word.length; i++) {

Choose a reason for hiding this comment

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

Prefer for / of loop instead since we don't need i to access each letter in word

totalScore += LETTERSCORES[word[i]];
}
//Adding 8 bonus points for letters with length 7 to 10
const BONUS_POINTS = 8;
if (word.length >= 7 && word.length <= 10) {
totalScore += BONUS_POINTS;
}

return totalScore;
};

export const highestScoreFrom = (words) => {
// Implement this method for wave 4
const wordScores = {};
let maxWord = '';
let maxScore = 0;
for (const word of words) {
wordScores[word] = scoreWord(word);
}
for (const [word, score] of Object.entries(wordScores)) {

if (score > maxScore) {
maxWord = word;
maxScore = score;
} else if (score === maxScore) {
//logic for words with score tied
if (word.length === 10 && maxWord.length !== 10) maxWord = word;
else if (word.length < maxWord.length && maxWord.length !== 10)
maxWord = word;
}
}

return { score: maxScore, word: maxWord };
};
12 changes: 8 additions & 4 deletions test/adagrams.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ describe("Adagrams", () => {
describe("drawLetters", () => {
it("draws ten letters from the letter pool", () => {
const drawn = drawLetters();

expect(drawn).toHaveLength(10);
});

Expand Down Expand Up @@ -120,7 +119,10 @@ describe("Adagrams", () => {
});

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

it("adds an extra 8 points if word is 7 or more characters long", () => {
Expand All @@ -133,7 +135,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 +147,9 @@ describe("Adagrams", () => {
const words = ["XXX", "XXXX", "X", "XX"];
const correct = { word: "XXXX", score: scoreWord("XXXX") };

throw "Complete test by adding an assertion";
// 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