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

Snow Leopards BG #47

Open
wants to merge 7 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
154 changes: 150 additions & 4 deletions src/adagrams.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,161 @@
//Function: Introduce letter pool and score chart for use
const letterPool = {
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 scoreChart = {
A: 1,
B: 3,
C: 3,
D: 2,
E: 1,
F: 4,
G: 2,
H: 4,
I: 1,
J: 8,
K: 5,
L: 1,
M: 3,
N: 1,
O: 1,
P: 3,
Q: 10,
R: 1,
S: 1,
T: 1,
U: 1,
V: 4,
W: 4,
X: 8,
Y: 4,
Z: 10,
};


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

for (const [key, value] of Object.entries(letterPool)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider using names more descriptive of what the key and value represent, such as letter and count.

for (let i = 0; i < value; i++) {
//add elements with push
availableLetters.push(key);
}
}

for (let i = 0; i < 10; i++) {
let letter = availableLetters[Math.floor(Math.random() * availableLetters.length)];
hand.push(letter);
let index = availableLetters.indexOf(letter);
availableLetters.splice(index, 1);
Copy link
Contributor

Choose a reason for hiding this comment

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

Note that this has the same time costs as remove in python. That is, anything after the data that was removed needs to be shifted to fill the gap in the array, resulting in a O(n) time complexity with respect to the list length. Since we're working with fixed lenths (26 letters a certain number of times each, and a 10 letter hand), we dont need to worry too much about the absolute performance, but in general we want to find approaches that don't perform linear complexity operations within a loop.

}
return hand;
};


export const usesAvailableLetters = (input, lettersInHand) => {
// Implement this method for wave 2
// wave 2
// Has two parameters:
// `input`, the first parameter, describes some input word, and is a string
// - `lettersInHand`, the second parameter, describes an array of drawn letters in a hand. You can expect this to be an array of ten strings, with each string representing a letter
// - Returns either `true` or `false`
// - Returns `true` if every letter in the `input` word is available (in the right quantities) in the `lettersInHand`
// - Returns `false` if not; if there is a letter in `input` that is not present in the `lettersInHand` or has too much of compared to the `lettersInHand`

lettersInHand = [...lettersInHand];
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 Since we're splicing values out of the hand, we need this copy so that we don't destroy the passed in hand.

for (const letter of input) {
if(lettersInHand.includes(letter)) {
let indexLettersInHand = lettersInHand.indexOf(letter);
lettersInHand.splice(indexLettersInHand, 1);
Comment on lines +94 to +96
Copy link
Contributor

Choose a reason for hiding this comment

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

Notice that we can use the result from indexOf itself to tell us whether the value is in the array, since it returns -1 if it is not. So we could wrrite this as

    const indexLettersInHand = lettersInHand.indexOf(letter);
    if (indexLettersInHand !== -1) {
      lettersInHand.splice(indexLettersInHand, 1);

Copy link
Contributor

Choose a reason for hiding this comment

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

This approcah (removing the values from from the hand copy as we use them) is going to be a quadratic O(n^2) approach (since the splice, like a remove, must shift everything else forward as things get removes). We could still think about building a frequency table of letters to determine whether the word can be made with the hand in linear time.

} else {
return false;
}
}
return true;
// const countLettersInHand = (lettersInHand) =>{
// //go through loop and account for each word in letter
// for(let i = 0 ; i < lettersInHand.length; ++i) {
// let wordCounter = 0;
// if
// };
// //use a counter to keep track of letter frequency
// };
};




export const scoreWord = (word) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

// Implement this method for wave 3
// wave 3
let score = 0;
for (let letter of word) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Prefer to use const for the loop control variable (letter).

score += scoreChart[letter.toUpperCase()];
}
//TODO: If the length of the word is > 7 + additional 8 points
if (word.length >= 7) {
score += 8;
}
return score;
};

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

//loop
for (const word of words) {
const score = scoreWord(word);
wordsAndScores[word] = score;
};

const winningWordAndScore = {
word: Object.keys(wordsAndScores)[0],
score: Object.values(wordsAndScores)[0]
};

for (const[key, value] of Object.entries(wordsAndScores)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider using more descriptive names for the key and value (maybe word and score) so we don't have to remember that the key is the word and the value is the score.

//create conditional
if (value > winningWordAndScore['score']) {
winningWordAndScore['word'] = key;
winningWordAndScore ['score'] = value;
};

if (value === winningWordAndScore['score'] && winningWordAndScore['word'].length < 10) {
Copy link
Contributor

Choose a reason for hiding this comment

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

The tie breaker conditions can be an else if, since if the new score beat the old score outright, there's no need to check any of the tie breaking code.

if(key.length === 10) {
winningWordAndScore['word'] = key;
winningWordAndScore['score'] = value;
} else if (key.length < winningWordAndScore['word'].length) {
winningWordAndScore['word'] = key;
winningWordAndScore['score'] = value;
}
}
}
return winningWordAndScore;
};
10 changes: 6 additions & 4 deletions test/adagrams.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ describe("Adagrams", () => {

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 drawn = ["O", "D","G", "X", "X", "X", "X", "X", "X", "X"];
const word = "DOG";

const isValid = usesAvailableLetters(word, drawn);
Expand Down Expand Up @@ -120,7 +120,9 @@ describe("Adagrams", () => {
});

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

Choose a reason for hiding this comment

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

👍

"" : 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,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);
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

});

describe("in case of tied score", () => {
Expand Down