Skip to content
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

C19 Kunzite - Amber Shay #90

Open
wants to merge 4 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
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
"babel-core": "^7.0.0-bridge.0",
"babel-jest": "^24.8.0",
"babel-plugin-module-resolver": "^3.2.0",
"eslint": "^8.41.0",
"eslint-plugin-jest": "^27.2.1",
"jest": "^24.8.0",
"regenerator-runtime": "^0.12.1"
},
Expand Down
109 changes: 109 additions & 0 deletions src/adagrams.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,124 @@
// letter bank with letter frequency
const letterPool = {
'A': 9, 'N': 6, 'B': 2, 'O': 8, 'C': 2, 'P': 2, 'D': 4, 'Q': 1, 'E': 12, 'R': 6, 'F': 2, 'S': 4, 'G': 3, 'T': 6,
'H': 2, 'U': 4, 'I': 9, 'V': 2, 'J': 1, 'W': 2, 'K': 1, 'X': 1, 'L': 4, 'M': 2, 'Z': 1
};

// letter bank with letter value
const letterValue = {
'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

// new copy of letterPool that won't be changed, using spread syntax
let letterPoolCopy = {...letterPool};
let letters = [];

while (letters.length < 10) {
let letterKeys = Object.keys(letterPoolCopy);
let letterKey = letterKeys[Math.floor(Math.random() * letterKeys.length)];
if (letterPoolCopy[letterKey] !== 0) {
letterPoolCopy[letterKey] -= 1;
letters.push(letterKey);
};
};

return letters;
};

export const usesAvailableLetters = (input, lettersInHand) => {
// Implement this method for wave 2

let lettersInHandCopy = [...lettersInHand];
let letterBankCase = lettersInHandCopy.map(letter => letter.toUpperCase());

for (let letter of input.toUpperCase()) {
let index = letterBankCase.indexOf(letter);
if (index !== -1) {
letterBankCase.splice(index, 1);
} else {
return false;
};
};
return true;
};

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

let currentScore = 0;

// Cannot get this to work to save my life
// if (word.length === 0){
// return currentScore;
// return 0;
if (word === "") {
return currentScore;
// return 0;
};

for (let letter of word.toUpperCase()) {
for (let [key, val] of Object.entries(letterValue)) {
if (val.includes(letter)) {
currentScore += Number(key);
};
};
};
if (word.length > 6 && word.length <= 10) {
currentScore += 8;
};
return currentScore;
};

export const highestScoreFrom = (words) => {
// Implement this method for wave 4

// *** pseudocode ***

// initialize a variable, highest_score, to 0
// initialize a variable, winning_word, to an empty string
// for each word in the words array, pass the word as an argument to scoreWord
// if the score is greater highest_score:
// if word.length === 10: assign score as highest_score and word as winning_word
// elif word.length < 10 && winning_word.length === 10: assign score as highest_score and word as winning_word
// elif the score === highest_score:
// if word.length === 10 && winning_word.length !== 10: assign score as highest_score and word as winning_word
// elif winning_word.length !== 10 && word.length < 10 && word.length < winning_word.length: assign score as highest_score and word as winning_word
// return { word: winning_word, score: highest_score }

let highestScore = 0;
let winningWord = "";

words.forEach(word => {
let score = scoreWord(word);

if (score > highestScore) {
if (word.length === 10) {
highestScore = score;
winningWord = word;
} else if (word.length < 10 && winningWord.length !== 10) {
highestScore = score;
winningWord = word;
};
} else if (score === highestScore) {
if (word.length === 10 && winningWord.length !== 10) {
highestScore = score;
winningWord = word;
} else if (winningWord.length !== 10) {
if (word.length ===10 || word.length < winningWord.length) {
highestScore = score;
winningWord = word;
};
};
};
});
return { word: winningWord, score: highestScore };
};
102 changes: 53 additions & 49 deletions test/adagrams.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
usesAvailableLetters,
scoreWord,
highestScoreFrom,
} from "adagrams";
} from 'adagrams';

const LETTER_POOL = {
A: 9,
Expand Down Expand Up @@ -34,15 +34,15 @@ const LETTER_POOL = {
Z: 1,
};

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 = 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 = drawLetters();

expect(Array.isArray(drawn)).toBe(true);
Expand All @@ -51,79 +51,82 @@ describe("Adagrams", () => {
});
});

it("does not draw a letter too many times", () => {
it('does not draw a letter too many times', () => {
for (let i = 0; i < 1000; i++) {
const drawn = drawLetters();
const letter_freq = {};
const letterFreq = {};
for (let letter of drawn) {
if (letter in letter_freq) {
letter_freq[letter] += 1;
if (letter in letterFreq) {
letterFreq[letter] += 1;
} else {
letter_freq[letter] = 1;
letterFreq[letter] = 1;
}
}

for (let letter of drawn) {
expect(letter_freq[letter]).toBeLessThanOrEqual(LETTER_POOL[letter]);
expect(letterFreq[letter]).toBeLessThanOrEqual(LETTER_POOL[letter]);
}
}
});
});

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 = 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 = 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 = usesAvailableLetters(word, drawn);
expect(isValid).toBe(false);
});
});

describe("scoreWord", () => {
describe('scoreWord', () => {
const expectScores = (wordScores) => {
Object.entries(wordScores).forEach(([word, score]) => {
expect(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", () => {
throw "Complete test";
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", () => {
it('adds an extra 8 points if word is 7 or more characters long', () => {
expectScores({
XXXXXXX: 64,
XXXXXXXX: 72,
Expand All @@ -133,22 +136,23 @@ describe("Adagrams", () => {
});
});

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: 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: scoreWord('XXXX') };

expect(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: scoreWord("XXXX") };
it('accurately finds best scoring word even if not sorted', () => {
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';
});

describe("in case of tied score", () => {
describe('in case of tied score', () => {
const expectTie = (words) => {
const scores = words.map((word) => scoreWord(word));
const highScore = scores.reduce((h, s) => (h < s ? s : h), 0);
Expand All @@ -158,36 +162,36 @@ describe("Adagrams", () => {
expect(tiedWords.length).toBeGreaterThan(1);
};

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

expect(highestScoreFrom(words)).toEqual(correct);
expect(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: scoreWord("WWW") };
it('selects the word with fewer letters when neither are 10 letters', () => {
const words = ['MMMM', 'WWW'];
const correct = { word: 'WWW', score: scoreWord('WWW') };
expectTie(words);

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

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

Expand Down
Loading