diff --git a/src/adagrams.js b/src/adagrams.js index 54043451..3304be65 100644 --- a/src/adagrams.js +++ b/src/adagrams.js @@ -1,8 +1,144 @@ -const Adagrams = { +class Adagram { + drawLetters() { - // Implement this method for wave 1 - }, -}; + const letterPoolObject = { + 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 + } + + // Add letters to an array + let letterPoolArray = []; + + for (let [letter, frequency] of Object.entries(letterPoolObject)) { + let i = 0; + while (i < frequency) { + letterPoolArray.push(letter); + i++; + } + } + + // Select random 10 letters for hand + let lettersInHand = []; + let j = 0; + while (j < 10) { + lettersInHand.push(letterPoolArray[Math.floor(Math.random() * letterPoolArray.length)]); + j ++; + } + + return lettersInHand; + } + + usesAvailableLetters(input, lettersInHand) { + let allValid = true; + + for (const charIndex in input) { + if (lettersInHand.includes(input[charIndex])) { + const handIndex = lettersInHand.indexOf(input[charIndex]); + lettersInHand.splice(handIndex, 1); + } else { + allValid = false; + } + } + + return allValid; + } + + static scoreWord(word) { + const letterPointValues = { + 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, + } + + let pointCount = 0; + if (word.length > 6 ){ + pointCount += 8; + } + + // Convert word to upper case for comparison + const upcaseWord = word.toUpperCase(); + for (const charIndex in upcaseWord) { + pointCount += letterPointValues[upcaseWord[charIndex]]; + } + + return pointCount; + } + + highestScoreFrom(words) { + let highScoreWords = []; + let highScore = 0; + + words.forEach( function(word) { + const currentWordScore = Adagram.scoreWord(word); + + if (currentWordScore > highScore) { + highScoreWords = [word]; + highScore = currentWordScore; + } else if (currentWordScore === highScore) { + highScoreWords.push(word); + } + }) + + if (highScoreWords.length === 1) { + return {word: highScoreWords[0], score: highScore} + } else { + let sortedWords = highScoreWords.sort( function(a, b){ return (b.length - a.length) }) + + if (sortedWords[0].length == 10){ + return { word: sortedWords[0], score: highScore }; + } else { + return { word: sortedWords[sortedWords.length - 1], score: highScore }; + } + } + } +} // Do not remove this line or your tests will break! -export default Adagrams; +export default Adagram; diff --git a/test/adagrams.test.js b/test/adagrams.test.js index 371027a0..bb80f80a 100644 --- a/test/adagrams.test.js +++ b/test/adagrams.test.js @@ -1,15 +1,21 @@ -import Adagrams from 'adagrams'; +import Adagram from 'adagrams'; describe('Adagrams', () => { + let game; + + beforeEach(() => { + game = new Adagram(); + }); + describe('drawLetters', () => { it('draws ten letters from the letter pool', () => { - const drawn = Adagrams.drawLetters(); + const drawn = game.drawLetters(); expect(drawn).toHaveLength(10); }); it('returns an array, and each item is a single-letter string', () => { - const drawn = Adagrams.drawLetters(); + const drawn = game.drawLetters(); expect(Array.isArray(drawn)).toBe(true); drawn.forEach((l) => { @@ -23,7 +29,7 @@ describe('Adagrams', () => { const drawn = ['D', 'O', 'G', 'X', 'X', 'X', 'X', 'X', 'X', 'X']; const word = 'DOG'; - const isValid = Adagrams.usesAvailableLetters(word, drawn); + const isValid = game.usesAvailableLetters(word, drawn); expect(isValid).toBe(true); }); @@ -31,7 +37,7 @@ describe('Adagrams', () => { const drawn = ['D', 'O', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X']; const word = 'DOG'; - const isValid = Adagrams.usesAvailableLetters(word, drawn); + const isValid = game.usesAvailableLetters(word, drawn); expect(isValid).toBe(false); }); @@ -39,7 +45,7 @@ describe('Adagrams', () => { const drawn = ['D', 'O', 'G', 'X', 'X', 'X', 'X', 'X', 'X', 'X']; const word = 'GOOD'; - const isValid = Adagrams.usesAvailableLetters(word, drawn); + const isValid = game.usesAvailableLetters(word, drawn); expect(isValid).toBe(false); }); @@ -48,7 +54,7 @@ describe('Adagrams', () => { describe('scoreWord', () => { const expectScores = (wordScores) => { Object.entries(wordScores).forEach(([word, score]) => { - expect(Adagrams.scoreWord(word)).toBe(score); + expect(Adagram.scoreWord(word)).toBe(score); }); }; @@ -84,24 +90,24 @@ 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: Adagrams.scoreWord('XXXX') }; + const correct = { word: 'XXXX', score: Adagram.scoreWord('XXXX') }; - expect(Adagrams.highestScoreFrom(words)).toEqual(correct); + expect(game.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') }; + const correct = { word: 'XXXX', score: Adagram.scoreWord('XXXX') }; - expect(Adagrams.highestScoreFrom(words)).toEqual(correct); + expect(game.highestScoreFrom(words)).toEqual(correct); }); describe('in case of tied score', () => { const expectTie = (words) => { - const scores = words.map(word => Adagrams.scoreWord(word)); + const scores = words.map(word => Adagram.scoreWord(word)); const highScore = scores.reduce((h, s) => h < s ? s : h, 0); const tiedWords = scores.filter((s) => s == highScore); @@ -111,30 +117,30 @@ describe('Adagrams', () => { it('selects the word with 10 letters', () => { const words = ['AAAAAAAAAA', 'BBBBBB']; - const correct = { word: 'AAAAAAAAAA', score: Adagrams.scoreWord('AAAAAAAAAA') }; + const correct = { word: 'AAAAAAAAAA', score: Adagram.scoreWord('AAAAAAAAAA') }; expectTie(words); - expect(Adagrams.highestScoreFrom(words)).toEqual(correct); - expect(Adagrams.highestScoreFrom(words.reverse())).toEqual(correct); + expect(game.highestScoreFrom(words)).toEqual(correct); + expect(game.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') }; + const correct = { word: 'WWW', score: Adagram.scoreWord('WWW') }; expectTie(words); - expect(Adagrams.highestScoreFrom(words)).toEqual(correct); - expect(Adagrams.highestScoreFrom(words.reverse())).toEqual(correct); + expect(game.highestScoreFrom(words)).toEqual(correct); + expect(game.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') }; + const first = { word: 'AAAAAAAAAA', score: Adagram.scoreWord('AAAAAAAAAA') }; + const second = { word: 'EEEEEEEEEE', score: Adagram.scoreWord('EEEEEEEEEE') }; expectTie(words); - expect(Adagrams.highestScoreFrom(words)).toEqual(first); - expect(Adagrams.highestScoreFrom(words.reverse())).toEqual(second); + expect(game.highestScoreFrom(words)).toEqual(first); + expect(game.highestScoreFrom(words.reverse())).toEqual(second); }); }); });