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
151 changes: 150 additions & 1 deletion src/adagrams.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,156 @@
const Adagrams = {
drawLetters() {
// Implement this method for wave 1
let letterPool = (

Choose a reason for hiding this comment

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

This should be a const

Choose a reason for hiding this comment

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

Consider first creating an object that represents letter frequencies and then using this object to build your array.

"A".repeat(9) +
"B".repeat(2) +
"C".repeat(2) +
"D".repeat(4) +
"E".repeat(12) +
"F".repeat(2) +
"G".repeat(3) +
"H".repeat(2) +
"I".repeat(9) +
"J" +
"K" +
"L".repeat(4) +
"M".repeat(2) +
"N".repeat(6) +
"O".repeat(8) +
"P".repeat(2) +
"Q" +
"R".repeat(6) +
"S".repeat(4) +
"T".repeat(6) +
"U".repeat(4) +
"V".repeat(2) +
"W".repeat(2) +
"X" +
"Y".repeat(2) +
"Z"
).split("");
let hand = [];

for (let i = 0; i < 10; i++) {

Choose a reason for hiding this comment

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

You're modifying your letterPool here. Make sure to make a deep copy first. In addition, consider how you could refactor such that you don't shuffle the pool 10 times.

letterPool.sort(() => Math.random() - 0.5);
hand.push(letterPool.pop());
}

return hand;
},

usesAvailableLetters(input, lettersInHand) {
let split = input.toUpperCase().split("");
let copy = lettersInHand.slice(0);

for (let letter in split) {
if (copy.includes(split[letter])) {
copy.splice(copy.indexOf(split[letter]), 1);
} else {
return false;
}
}
return true;
},

scoreWord(word) {
let split = word.toUpperCase().split("");
let points = 0;

for (let letter in split) {
switch (split[letter]) {

Choose a reason for hiding this comment

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

Good approach using a switch/case conditional! You probably could refactor this to use an object (a hash) though.

case "A":
case "E":
case "I":
case "O":
case "U":
case "L":
case "N":
case "R":
case "S":
case "T":
points += 1;
break;
case "D":
case "G":
points += 2;
break;
case "B":
case "C":
case "M":
case "P":
points += 3;
break;
case "F":
case "H":
case "V":
case "W":
case "Y":
points += 4;
break;
case "K":
points += 5;
break;
case "J":
case "X":
points += 8;
break;
case "Q":
case "Z":
points += 10;
break;
}
}

if (split.length >= 7) {
points += 8;
}

return points;
},

highestScoreFrom(words) {
let wordScore = [];

for (let word in words) {
let wordObj = { word: words[word], score: this.scoreWord(words[word]) };

wordScore.push(wordObj);
}

let max = 0;
wordScore.forEach(word => {
if (word.score > max) {
max = word.score;
}
});

let winners = [];
wordScore.forEach(word => {
if (word.score === max) {
winners.push(word);
}
});

let tenChar = [];
winners.forEach(word => {
if (word.word.length === 10) {
tenChar.push(word);
}
});

if (tenChar.length > 0) {
return tenChar[0];
} else {
let minWinners = winners[0];

winners.forEach(word => {
if (word.word.length < minWinners.word.length) {
minWinners = word;
}
});
return minWinners;
}
}
};

// Do not remove this line or your tests will break!
Expand Down
100 changes: 54 additions & 46 deletions test/adagrams.test.js
Original file line number Diff line number Diff line change
@@ -1,136 +1,144 @@
import Adagrams from 'adagrams';
import Adagrams from "adagrams";

describe('Adagrams', () => {
describe('drawLetters', () => {
it('draws ten letters from the letter pool', () => {
describe("Adagrams", () => {
describe("drawLetters", () => {
it("draws ten letters from the letter pool", () => {
const drawn = Adagrams.drawLetters();

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

it('returns an array, and each item is a single-letter string', () => {
it("returns an array, and each item is a single-letter string", () => {
const drawn = Adagrams.drawLetters();

expect(Array.isArray(drawn)).toBe(true);
drawn.forEach((l) => {
drawn.forEach(l => {
expect(l).toMatch(/^[A-Z]$/);
});
});
});

describe('usesAvailableLetters', () => {
it('returns true if the submitted letters are valid against the drawn letters', () => {
const drawn = ['D', 'O', 'G', 'X', 'X', 'X', 'X', 'X', 'X', 'X'];
const word = 'DOG';
describe("usesAvailableLetters", () => {
it("returns true if the submitted letters are valid against the drawn letters", () => {
const drawn = ["D", "O", "G", "X", "X", "X", "X", "X", "X", "X"];
const word = "DOG";

const isValid = Adagrams.usesAvailableLetters(word, drawn);
expect(isValid).toBe(true);
});

it('returns false when word contains letters not in the drawn letters', () => {
const drawn = ['D', 'O', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'];
const word = 'DOG';
it("returns false when word contains letters not in the drawn letters", () => {
const drawn = ["D", "O", "X", "X", "X", "X", "X", "X", "X", "X"];
const word = "DOG";

const isValid = Adagrams.usesAvailableLetters(word, drawn);
expect(isValid).toBe(false);
});

it('returns false when word contains repeated letters more than in the drawn letters', () => {
const drawn = ['D', 'O', 'G', 'X', 'X', 'X', 'X', 'X', 'X', 'X'];
const word = 'GOOD';
it("returns false when word contains repeated letters more than in the drawn letters", () => {
const drawn = ["D", "O", "G", "X", "X", "X", "X", "X", "X", "X"];
const word = "GOOD";

const isValid = Adagrams.usesAvailableLetters(word, drawn);
expect(isValid).toBe(false);

});
});

describe('scoreWord', () => {
const expectScores = (wordScores) => {
describe("scoreWord", () => {
const expectScores = wordScores => {
Object.entries(wordScores).forEach(([word, score]) => {
expect(Adagrams.scoreWord(word)).toBe(score);
});
};

it('returns an accurate numerical score according to the score chart', () => {
it("returns an accurate numerical score according to the score chart", () => {
expectScores({
A: 1,
DOG: 5,
WHIMSY: 17
});
});

it('returns a score regardless of the input case', () => {
it("returns a score regardless of the input case", () => {
expectScores({
a: 1,
dog: 5,
wHiMsY: 17
});
});

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

it('adds an extra 8 points if word is 7 or more characters long', () => {
it("adds an extra 8 points if word is 7 or more characters long", () => {
expectScores({
XXXXXXX: 64,
XXXXXXXX: 72,
XXXXXXXXX: 80,
XXXXXXXXXX: 88,
XXXXXXXXXX: 88
});
});
});

describe.skip('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: Adagrams.scoreWord('XXXX') };
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: Adagrams.scoreWord("XXXX") };

expect(Adagrams.highestScoreFrom(words)).toEqual(correct);
});

it('accurately finds best scoring word even if not sorted', () => {
const words = ['XXX', 'XXXX', 'X', 'XX'];
const correct = { word: 'XXXX', score: Adagrams.scoreWord('XXXX') };
it("accurately finds best scoring word even if not sorted", () => {
const words = ["XXX", "XXXX", "X", "XX"];
const correct = { word: "XXXX", score: Adagrams.scoreWord("XXXX") };

expect(Adagrams.highestScoreFrom(words)).toEqual(correct);
});

describe('in case of tied score', () => {
const expectTie = (words) => {
describe("in case of tied score", () => {
const expectTie = words => {
const scores = words.map(word => Adagrams.scoreWord(word));
const highScore = scores.reduce((h, s) => h < s ? s : h, 0);
const tiedWords = scores.filter((s) => s == highScore);
const highScore = scores.reduce((h, s) => (h < s ? s : h), 0);
const tiedWords = scores.filter(s => s == highScore);

// Expect at least two tied words
expect(tiedWords.length).toBeGreaterThan(1);
};

it('selects the word with 10 letters', () => {
const words = ['AAAAAAAAAA', 'BBBBBB'];
const correct = { word: 'AAAAAAAAAA', score: Adagrams.scoreWord('AAAAAAAAAA') };
it("selects the word with 10 letters", () => {
const words = ["AAAAAAAAAA", "BBBBBB"];
const correct = {
word: "AAAAAAAAAA",
score: Adagrams.scoreWord("AAAAAAAAAA")
};
expectTie(words);

expect(Adagrams.highestScoreFrom(words)).toEqual(correct);
expect(Adagrams.highestScoreFrom(words.reverse())).toEqual(correct);
});

it('selects the word with fewer letters when neither are 10 letters', () => {
const words = ['MMMM', 'WWW'];
const correct = { word: 'WWW', score: Adagrams.scoreWord('WWW') };
it("selects the word with fewer letters when neither are 10 letters", () => {
const words = ["MMMM", "WWW"];
const correct = { word: "WWW", score: Adagrams.scoreWord("WWW") };
expectTie(words);

expect(Adagrams.highestScoreFrom(words)).toEqual(correct);
expect(Adagrams.highestScoreFrom(words.reverse())).toEqual(correct);
});

it('selects the first word when both have same length', () => {
const words = ['AAAAAAAAAA', 'EEEEEEEEEE'];
const first = { word: 'AAAAAAAAAA', score: Adagrams.scoreWord('AAAAAAAAAA') };
const second = { word: 'EEEEEEEEEE', score: Adagrams.scoreWord('EEEEEEEEEE') };
it("selects the first word when both have same length", () => {
const words = ["AAAAAAAAAA", "EEEEEEEEEE"];
const first = {
word: "AAAAAAAAAA",
score: Adagrams.scoreWord("AAAAAAAAAA")
};
const second = {
word: "EEEEEEEEEE",
score: Adagrams.scoreWord("EEEEEEEEEE")
};
expectTie(words);

expect(Adagrams.highestScoreFrom(words)).toEqual(first);
Expand Down