From 021a2565036ca13686e60c5d10d09df93be7c0c5 Mon Sep 17 00:00:00 2001 From: Elle Kosling Date: Sat, 14 Sep 2019 21:25:03 -0700 Subject: [PATCH 1/4] Wrote grouped_anagrams method. --- lib/exercises.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/exercises.js b/lib/exercises.js index 648394e..c263bf4 100644 --- a/lib/exercises.js +++ b/lib/exercises.js @@ -3,7 +3,16 @@ // Time Complexity: ? // Space Complexity: ? function grouped_anagrams(strings) { - throw new Error("Method hasn't been implemented yet!"); + let anagrams = {}; + + strings.forEach(str => { + let tempStr = str.split('').sort().join(''); + anagrams[tempStr] ? anagrams[tempStr].push(str) : anagrams[tempStr] = [str]; + }); + + let matchedAnagrams = Object.values(anagrams); + + return matchedAnagrams; } // This method will return the k most common elements From ffd2d27d291d6a5ff28d2d6aff57d28f38056e45 Mon Sep 17 00:00:00 2001 From: Elle Kosling Date: Sat, 14 Sep 2019 22:00:55 -0700 Subject: [PATCH 2/4] Added time and space complexity notes for anagrams method. Updated tests to match changes from Matt. --- lib/exercises.js | 10 ++++---- test/exercises.test.js | 52 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/lib/exercises.js b/lib/exercises.js index c263bf4..1bed68b 100644 --- a/lib/exercises.js +++ b/lib/exercises.js @@ -1,18 +1,16 @@ // This method will return an array of arrays. // Each subarray will have strings which are anagrams of each other -// Time Complexity: ? -// Space Complexity: ? +// Time Complexity: O(n) where n is the length of the array passed in as the argument "strings" because each item in the array is visited once +// Space Complexity: O(1) (***Chris, is this right? It takes 2 times the space of 'strings' which reduces to 1. Or is it O(n) because the space taken is is 2 x n where n is the length of the 'strings' array?***) function grouped_anagrams(strings) { let anagrams = {}; strings.forEach(str => { - let tempStr = str.split('').sort().join(''); + let tempStr = str.split('').sort().join(''); // alphabetize str anagrams[tempStr] ? anagrams[tempStr].push(str) : anagrams[tempStr] = [str]; }); - let matchedAnagrams = Object.values(anagrams); - - return matchedAnagrams; + return Object.values(anagrams); } // This method will return the k most common elements diff --git a/test/exercises.test.js b/test/exercises.test.js index 93461ab..14a49c8 100644 --- a/test/exercises.test.js +++ b/test/exercises.test.js @@ -138,6 +138,48 @@ describe("exercises", function() { }); describe.skip("valid sudoku", function() { + it("is not valid if a row has duplicate values", function() { + // Arrange + const table = [ + ["5","3",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".","5","5",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."] + ]; + + // Act + const valid = valid_sudoku(table); + + // Assert + expect(valid).to.be.false; + }); + + it("is not valid if a column has duplicate values", function() { + // Arrange + const table = [ + ["5",".",".",".",".",".",".",".","."], + ["2",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".","4",".",".",".","."], + [".",".",".",".","4",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."] + ]; + + // Act + const valid = valid_sudoku(table); + + // Assert + expect(valid).to.be.false; + }); + it("works for the table given in the README", function() { // Arrange const table = [ @@ -156,7 +198,7 @@ describe("exercises", function() { const valid = valid_sudoku(table); // Assert - expect(valid).toEqual(true); + expect(valid).to.be.true; }); it("fails for the table given in the README", function() { @@ -177,7 +219,7 @@ describe("exercises", function() { const valid = valid_sudoku(table); // Assert - expect(valid).toEqual(false); + expect(valid).to.be.false; }); it("fails for a duplicate number in a sub-box", function() { @@ -198,7 +240,7 @@ describe("exercises", function() { const valid = valid_sudoku(table); // Assert - expect(valid).toEqual(false); + expect(valid).to.be.false; }); it("fails for a duplicate number in a bottom right sub-box", function() { @@ -219,7 +261,7 @@ describe("exercises", function() { const valid = valid_sudoku(table); // Assert - expect(valid).toEqual(false); + expect(valid).to.be.false; }); }); -}); +}); \ No newline at end of file From f563ff9ba5766e5b5c172ce40e849b207b1cfac6 Mon Sep 17 00:00:00 2001 From: Elle Kosling Date: Sat, 14 Sep 2019 22:24:42 -0700 Subject: [PATCH 3/4] Changed snake case to camel case for JS convention. --- lib/exercises.js | 22 ++++++++++++------ test/exercises.test.js | 52 +++++++++++++++++++++--------------------- 2 files changed, 41 insertions(+), 33 deletions(-) diff --git a/lib/exercises.js b/lib/exercises.js index 1bed68b..d67ae62 100644 --- a/lib/exercises.js +++ b/lib/exercises.js @@ -2,7 +2,7 @@ // Each subarray will have strings which are anagrams of each other // Time Complexity: O(n) where n is the length of the array passed in as the argument "strings" because each item in the array is visited once // Space Complexity: O(1) (***Chris, is this right? It takes 2 times the space of 'strings' which reduces to 1. Or is it O(n) because the space taken is is 2 x n where n is the length of the 'strings' array?***) -function grouped_anagrams(strings) { +function groupedAnagrams(strings) { let anagrams = {}; strings.forEach(str => { @@ -17,8 +17,16 @@ function grouped_anagrams(strings) { // in the case of a tie it will select the first occuring element. // Time Complexity: ? // Space Complexity: ? -function top_k_frequent_elements(list, k) { - throw new Error("Method hasn't been implemented yet!"); +function topKFrequentElements(list, k) { + if (list.length < k){ + return list; + } + + let elementCounts = {}; + + // iterate through each item in list (array) + // if the item is a key in elementCounts + } @@ -29,12 +37,12 @@ function top_k_frequent_elements(list, k) { // row, column or 3x3 subgrid // Time Complexity: ? // Space Complexity: ? -function valid_sudoku(table) { +function validSudoku(table) { throw new Error("Method hasn't been implemented yet!"); } module.exports = { - grouped_anagrams, - top_k_frequent_elements, - valid_sudoku + groupedAnagrams, + topKFrequentElements, + validSudoku }; diff --git a/test/exercises.test.js b/test/exercises.test.js index 14a49c8..c767941 100644 --- a/test/exercises.test.js +++ b/test/exercises.test.js @@ -1,18 +1,18 @@ const expect = require('chai').expect; const { - grouped_anagrams, - top_k_frequent_elements, - valid_sudoku + groupedAnagrams, + topKFrequentElements, + validSudoku } = require('../lib/exercises'); describe("exercises", function() { - describe("grouped_anagrams", function() { + describe("groupedAnagrams", function() { it("will return [] for an empty array", function() { // Arrange const list = []; // Act-Assert - expect(grouped_anagrams(list)).to.eql([]); + expect(groupedAnagrams(list)).to.eql([]); }); it("will work for the README example", function() { @@ -20,8 +20,8 @@ describe("exercises", function() { const list = ["eat", "tea", "tan", "ate", "nat", "bat"]; // Act - const answer = grouped_anagrams(list); - const expected_answer = [ + const answer = groupedAnagrams(list); + const expectedAnswer = [ ["ate","eat","tea"], ["nat","tan"], ["bat"] @@ -30,7 +30,7 @@ describe("exercises", function() { // Assert expect(answer.length).to.be.greaterThan(0); answer.forEach((array, index) => { - expect(array.sort()).to.eql(expected_answer[index]); + expect(array.sort()).to.eql(expectedAnswer[index]); }); }); @@ -39,9 +39,9 @@ describe("exercises", function() { const list = ["eat", "ear", "tar", "pop", "pan", "pap"]; // Act - const answer = grouped_anagrams(list); + const answer = groupedAnagrams(list); - const expected_answer = [ + const expectedAnswer = [ ["eat"], ["ear"], ["tar"], @@ -53,7 +53,7 @@ describe("exercises", function() { // Assert expect(answer.length).to.be.greaterThan(0); answer.forEach((array) => { - expect(expected_answer).to.deep.include(array.sort()); + expect(expectedAnswer).to.deep.include(array.sort()); }); }); @@ -62,27 +62,27 @@ describe("exercises", function() { const list = ["eat", "tae", "tea", "eta", "aet", "ate"] // Act - const answer = grouped_anagrams(list); - const expected_answer = [ + const answer = groupedAnagrams(list); + const expectedAnswer = [ [ "aet", "ate", "eat", "eta", "tae", "tea"] ]; // Assert expect(answer.length).to.be.greaterThan(0); answer.forEach((array) => { - expect(expected_answer).to.deep.include(array.sort()); + expect(expectedAnswer).to.deep.include(array.sort()); }); }); }); - describe.skip("top_k_frequent_elements", function() { + describe("topKFrequentElements", function() { it("works with example 1", function() { // Arrange const list = [1,1,1,2,2,3]; const k = 2; // Act - const answer = top_k_frequent_elements(list, k); + const answer = topKFrequentElements(list, k); // Assert expect(answer.sort()).to.eql([1,2]); @@ -94,7 +94,7 @@ describe("exercises", function() { const k = 1; // Act - const answer = top_k_frequent_elements(list, k); + const answer = topKFrequentElements(list, k); // Assert expect(answer.sort()).to.eql([1]); @@ -106,7 +106,7 @@ describe("exercises", function() { const k = 1; // Act - const answer = top_k_frequent_elements(list, k); + const answer = topKFrequentElements(list, k); // Assert expect(answer.sort()).to.eql([]); @@ -118,7 +118,7 @@ describe("exercises", function() { const k = 3; // Act - const answer = top_k_frequent_elements(list, k); + const answer = topKFrequentElements(list, k); // Assert expect(answer.sort()).to.eql([1, 2, 3]); @@ -130,7 +130,7 @@ describe("exercises", function() { const k = 1; // Act - const answer = top_k_frequent_elements(list, k); + const answer = topKFrequentElements(list, k); // Assert expect(answer.sort()).to.eql([1]); @@ -153,7 +153,7 @@ describe("exercises", function() { ]; // Act - const valid = valid_sudoku(table); + const valid = validSudoku(table); // Assert expect(valid).to.be.false; @@ -174,7 +174,7 @@ describe("exercises", function() { ]; // Act - const valid = valid_sudoku(table); + const valid = validSudoku(table); // Assert expect(valid).to.be.false; @@ -195,7 +195,7 @@ describe("exercises", function() { ]; // Act - const valid = valid_sudoku(table); + const valid = validSudoku(table); // Assert expect(valid).to.be.true; @@ -216,7 +216,7 @@ describe("exercises", function() { ]; // Act - const valid = valid_sudoku(table); + const valid = validSudoku(table); // Assert expect(valid).to.be.false; @@ -237,7 +237,7 @@ describe("exercises", function() { ]; // Act - const valid = valid_sudoku(table); + const valid = validSudoku(table); // Assert expect(valid).to.be.false; @@ -258,7 +258,7 @@ describe("exercises", function() { ]; // Act - const valid = valid_sudoku(table); + const valid = validSudoku(table); // Assert expect(valid).to.be.false; From b6e3d22b99a4248183095ef44091a2102ed4fdff Mon Sep 17 00:00:00 2001 From: Elle Kosling Date: Sun, 15 Sep 2019 09:59:31 -0700 Subject: [PATCH 4/4] QUESTIONS IN THIS COMMIT. Wrote pseudocode for k_top_elements. Pontificated about Big-O notation and the most efficient solution. --- lib/exercises.js | 45 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/lib/exercises.js b/lib/exercises.js index d67ae62..c591e3f 100644 --- a/lib/exercises.js +++ b/lib/exercises.js @@ -13,25 +13,58 @@ function groupedAnagrams(strings) { return Object.values(anagrams); } -// This method will return the k most common elements -// in the case of a tie it will select the first occuring element. +// This method will return the k most common elements. +// In the case of a tie it will select the first occuring element. // Time Complexity: ? // Space Complexity: ? + +// Clarifying questions: +// 1) What happens if there are < k elements in the list array? +// 2) How big are list and k likely to be? (Optimize for list or for k)? +// 3) Are the elements in list likely to be anything that can't be used as a key? (Will they always be numbers/strings/something that can be coorced into a string? Will they ever be null or undefined?) function topKFrequentElements(list, k) { if (list.length < k){ return list; - } + } // this code might not be necessary once the function is complete let elementCounts = {}; // iterate through each item in list (array) - // if the item is a key in elementCounts + // if the item is a key in elementCounts, add 1 to is value + // if it's not a key already, add it as a key with value 1 + +// find highest count in arrary +const maxCount = elementCounts.values.max; +let solutions = []; + +obj = { name: 'Bobo' } +obj.somethingElse = obj.name +delete obj.name + +// OPTION 1 +// k.times { // *** O(k) --> O(1) ? +// loop through the list array // *** O(n*k) +// if the item's matching value === maxCount, add the key to solutions array +// update the maxCount to the next item in the array +// } + + +// OPTION 2 +// const eleCountsInverted = a new object switching keys and values // *** O(n) ? +// now counts are keys, values are the items from the list array +let highestCountsArray = Object.keys(eleCountsInverted); // O(1) ? +// k.times { + // loop through highestCountsArray // *** O(k) --> O(1) ? + // add the values associated with these keys to the solutions array +// } + + // return an array with the first k keys with highest values in any order + return solutions; } -// This method will return the true if the table is still -// a valid sudoku table. +// This method will return true if the table is a valid sudoku table. // Each element can either be a ".", or a digit 1-9 // The same digit cannot appear twice or more in the same // row, column or 3x3 subgrid