-
-
Notifications
You must be signed in to change notification settings - Fork 637
Add ozans playlist concept exercise #1093
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
Merged
SleeplessByte
merged 20 commits into
exercism:main
from
kristinaborn:add-ozans-playlist-concept-exercise
Apr 26, 2021
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
afe213a
Add exercise and concept files
kristinaborn cfc5742
Add tests
kristinaborn 5ec4e7c
Rewrite instructions to better represent the use case
kristinaborn b0623c7
Refactor
kristinaborn d779765
Improve introduction
kristinaborn d2bab8a
Add hints
kristinaborn d55f1d4
Try to avoid confusion by using 'track' instead of 'song'
kristinaborn 68f2ebb
Improve hint
kristinaborn 7e703b2
Clean up design.md
kristinaborn 6225b5a
Add introduction
kristinaborn 7198996
Add example for the listArtists task
kristinaborn 416126e
Add about.md
kristinaborn 42ff414
Format links file properly
kristinaborn 53015e1
[CI] Sync exercises
github-actions[bot] a3c2338
Edit prerequisites and add exercise to root-level config file
kristinaborn 156e652
Sync all files
kristinaborn 07dbef8
Add uuid
kristinaborn b366bf3
Update exercises/concept/ozans-playlist/.docs/instructions.md
SleeplessByte 17f3268
Mark tests as unskipped
SleeplessByte 9732e43
[CI] Format code
github-actions[bot] File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"blurb": "Store a collection of unique values", | ||
"authors": ["kristinaborn"], | ||
"contributors": [] | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
# About | ||
|
||
kristinaborn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
In JavaScript, a set is a list-like data structure that can only contain unique primitives and/or object references. | ||
|
||
Sets must be created using the set constructor; they can be initialized with values by passing an array to the constructor. | ||
|
||
```javascript | ||
const emptySet = new Set(); | ||
const setWithInitialValues = new Set(['hello', 'world']); | ||
``` | ||
|
||
## Adding and removing elements | ||
|
||
A value cannot be added to a set if it is [strictly equal][mdn-strict-equality] to any of the set's elements. | ||
|
||
```javascript | ||
const set = new Set(); | ||
set.add(10); | ||
set.add(10); // 10 is strictly equal to 10, so it can't be added again | ||
set.size; | ||
//=> 1; | ||
|
||
set.has(10); | ||
//=> true | ||
set.delete(10); | ||
//=> true; 10 was removed | ||
set.delete(10); | ||
//=> false; 10 is not in the set, so nothing happened | ||
|
||
const obj = { color: 'magenta' }; | ||
const eerilySimilarObj = { color: 'magenta' }; | ||
|
||
set.add(obj); | ||
set.add(eerilySimilarObj); // obj and eerilySimilarObj reference different objects, so they can both be added | ||
set.size; | ||
//=> 2 | ||
|
||
set.clear(); | ||
set.size; | ||
//=> 0 | ||
``` | ||
|
||
## Converting between sets and arrays | ||
|
||
Arrays are converted to sets using the set constructor. Sets can be converted to arrays using either [spread syntax][mdn-spread-syntax] or `Array.from()`. | ||
|
||
```javascript | ||
const arrayWithDuplicates = [7, 3, 3, 9, 3]; | ||
const arrayWithoutDuplicates = [...new Set(arrayWithDuplicates)]; // [7, 3, 9] | ||
const anotherArrayWithoutDuplicates = Array.from(new Set(arrayWithDuplicates)); // [7, 3, 9] | ||
``` | ||
|
||
## Iteration | ||
|
||
A set is a [keyed collection][mdn-keyed-collections], which means its elements are indexed by a key and can be iterated in insertion order. Because the _key_ and _value_ of a set element are the same, `Set.keys()` and `Set.values()` are interchangeable. | ||
|
||
```javascript | ||
const apples = ['Granny Smith', 'Honey Crisp', 'Royal Gala']; | ||
const appleSet = new Set(apples); | ||
|
||
for (let apple of appleSet.keys()) { | ||
console.log(apple); | ||
} | ||
// 'Granny Smith' | ||
// 'Honey Crisp' | ||
// 'Royal Gala' | ||
|
||
for (let apple of appleSet.values()) { | ||
console.log(apple); | ||
} | ||
// 'Granny Smith' | ||
// 'Honey Crisp' | ||
// 'Royal Gala' | ||
|
||
for (let apple of appleSet.entries()) { | ||
console.log(apple); | ||
} | ||
// ['Granny Smith', 'Granny Smith'] | ||
// ['Honey Crisp', 'Honey Crisp'] | ||
// ['Royal Gala', 'Royal Gala'] | ||
``` | ||
|
||
## Lookup performance vs. arrays | ||
|
||
When a set is chosen to store a collection of data (rather than an array), it's generally because the stored values need to be unique. However, since it's possible to enforce uniqueness with arrays too, it may not be obvious why that is. | ||
|
||
The short answer is that sets are optimized for searching, and arrays are not. Array search methods (such as `Array.indexOf()`) have runtimes that increase linearly with the size of the array; that is, the more elements the array contains, the longer it takes to search it. Set search methods, on the other hand, have constant runtimes, meaning they stay the same regardless of the set's size. | ||
|
||
In practice, though, this performance difference is negligible unless the collection contains a huge amount of data. | ||
|
||
[mdn-strict-equality]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#strict_equality_using | ||
[mdn-keyed-collections]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Keyed_collections | ||
[mdn-spread-syntax]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Introduction | ||
|
||
In JavaScript, a [set][mdn-sets] is a list-like structure containing unique values, which can be primitives and/or object references. Unlike an array, a set's elements cannot be accessed by index. | ||
|
||
A value cannot be added to a set if it is [strictly equal][mdn-strict-equality] to any of the set's elements. | ||
|
||
```javascript | ||
const set = new Set(); | ||
const object = { color: 'lime green' }; | ||
const functionallyIdenticalObject = { color: 'lime green' }; | ||
|
||
set.add(object); | ||
set.add('wow'); | ||
set.add(77); | ||
|
||
console.log(set.size); | ||
//=> 3 | ||
|
||
set.add(functionallyIdenticalObject); // added because functionallyIdenticalObject is not strictly equal to object | ||
console.log(set.size); | ||
//=> 4 | ||
|
||
set.add(77); // not added because 77 is strictly equal to 77 | ||
console.log(set.size); | ||
//=> 4 | ||
``` | ||
|
||
[mdn-sets]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set | ||
[mdn-strict-equality]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#strict_equality_using |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[ | ||
{ | ||
"url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set", | ||
"description": "MDN: Sets" | ||
} | ||
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Hints | ||
|
||
## 1. Remove duplicate tracks | ||
|
||
- You can see an example of creating a set from an array in the [MDN docs][mdn-relation-to-arrays]. | ||
- Make sure to convert your set back into an array before returning it. | ||
- Refer back to the [array destructuring concept][concept-array-destructuring] to recap how to use the spread operator. | ||
|
||
## 2. Check whether a track has already been added | ||
|
||
- There is a [built-in method][mdn-set-has] for checking whether an element is in a set. | ||
|
||
## 3. Add a track | ||
|
||
- There is a [built-in method][mdn-set-add] for adding an element to a set. | ||
- Make sure you're not manually calling `Set.has()` to check for the presence of the element before adding it; `Set.add()` takes care of that for you! | ||
|
||
## 4. Delete a track | ||
|
||
- There is a [built-in method][mdn-set-delete] for removing an element from a set. | ||
- Make sure you're not manually calling `Set.has()` to check for the presence of the element before deleting it; `Set.delete()` takes care of that for you! | ||
|
||
## 5. List unique artists | ||
|
||
- There are [a few different ways][mdn-set-iteration] to iterate over a set. | ||
- There is a [built-in method][mdn-string-split] for dividing a string into substrings. | ||
- Refer back to the [array destructuring concept][concept-array-destructuring] to recap how to skip an element when destructuring an array. | ||
|
||
[mdn-relation-to-arrays]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#relation_with_array_objects | ||
[mdn-set-add]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/add | ||
[mdn-set-delete]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/delete | ||
[mdn-set-has]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/has | ||
[mdn-set-iteration]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#iterating_sets | ||
[mdn-string-split]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split | ||
[concept-array-destructuring]: /tracks/javascript/concepts/array-destructuring |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# Instructions | ||
|
||
Ozan is putting together a playlist for an upcoming roadtrip. He doesn't want to hear the same track more than once, but the playlist has gotten so long that he's having trouble remembering which tracks have already been added. | ||
|
||
The API for Ozan's music player only knows how to work with arrays, so he attempts to write some code that uses `Array.indexOf()` to check for the presence of a track before adding it to the playlist. Unfortunately, his program takes much too long to execute. He needs your help! | ||
|
||
Coming to Ozan's aid, you are astonished to find that his playlist contains _half a million_ tracks. Perhaps you know of a different data structure that will allow you to manipulate the playlist more efficiently? | ||
|
||
## 1. Remove duplicate tracks | ||
|
||
Implement the `removeDuplicates` function, which takes a playlist as a _parameter_ and _returns_ a new playlist where all the tracks are unique. | ||
|
||
```javascript | ||
const playlist = [ | ||
'Court and Spark - Joni Mitchell', | ||
'Big Yellow Taxi - Joni Mitchell', | ||
'Court and Spark - Joni Mitchell', | ||
]; | ||
|
||
removeDuplicates(playlist); | ||
//=> ['Court and Spark - Joni Mitchell', 'Big Yellow Taxi - Joni Mitchell'] | ||
``` | ||
|
||
## 2. Check whether a track has already been added | ||
|
||
Implement the `hasTrack` function, which takes a playlist and a track as _parameters_ and _returns_ a boolean that indicates whether the playlist contains the track. | ||
|
||
```javascript | ||
const playlist = [ | ||
'The Fashion Show - Grace Jones', | ||
'Dr. Funkenstein - Parliament', | ||
]; | ||
|
||
hasTrack(playlist, 'Dr. Funkenstein - Parliament'); | ||
//=> true | ||
|
||
hasTrack(playlist, 'Walking in the Rain - Grace Jones'); | ||
//=> false | ||
``` | ||
|
||
## 3. Add a track | ||
|
||
Implement the `addTrack` function, which takes a playlist and a track as _parameters_ and _returns_ a new playlist that includes the track. | ||
|
||
```javascript | ||
const playlist = ['Selma - Bijelo Dugme']; | ||
|
||
addTrack(playlist, 'Atomic Dog - George Clinton'); | ||
//=> ['Selma - Bijelo Dugme', 'Atomic Dog - George Clinton'] | ||
|
||
addTrack(playlist, 'Selma - Bijelo Dugme'); | ||
//=> ['Selma - Bijelo Dugme', 'Atomic Dog - George Clinton'] | ||
``` | ||
|
||
## 4. Delete a track | ||
|
||
Implement the `deleteTrack` function, which takes a playlist and a track as _parameters_ and _returns_ a new playlist that does not include the track. | ||
|
||
```javascript | ||
const playlist = [ | ||
'The Treasure - Fra Lippo Lippi', | ||
'After the Fall - Klaus Nomi', | ||
]; | ||
|
||
deleteTrack(playlist, 'The Treasure - Fra Lippo Lippi'); | ||
//=> ['After the Fall - Klaus Nomi'] | ||
|
||
deleteTrack(playlist, 'I Feel the Magic - Belinda Carlisle'); | ||
//=> ['After the Fall - Klaus Nomi'] | ||
``` | ||
|
||
## 5. List unique artists | ||
|
||
Implement the `listArtists` function, which takes a playlist as a _parameter_ and _returns_ the list of unique artists in the playlist. Note that the names of the tracks are formatted like `<SONG> - <ARTIST>`. | ||
|
||
```javascript | ||
const playlist = [ | ||
'All Mine - Portishead', | ||
'Sight to Behold - Devendra Banhart', | ||
'Sour Times - Portishead', | ||
]; | ||
|
||
listArtists(playlist); | ||
//=> ['Portishead', 'Devendra Banhart'] | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Introduction | ||
|
||
In JavaScript, a [set][mdn-sets] is a list-like structure containing unique values, which can be primitives and/or object references. Unlike an array, a set's elements cannot be accessed by index. | ||
|
||
A value cannot be added to a set if it is [strictly equal][mdn-strict-equality] to any of the set's elements. | ||
|
||
```javascript | ||
const set = new Set(); | ||
const object = { color: 'lime green' }; | ||
const functionallyIdenticalObject = { color: 'lime green' }; | ||
|
||
set.add(object); | ||
set.add('wow'); | ||
set.add(77); | ||
|
||
console.log(set.size); | ||
//=> 3 | ||
|
||
set.add(functionallyIdenticalObject); // added because functionallyIdenticalObject is not strictly equal to object | ||
console.log(set.size); | ||
//=> 4 | ||
|
||
set.add(77); // not added because 77 is strictly equal to 77 | ||
console.log(set.size); | ||
//=> 4 | ||
``` | ||
|
||
[mdn-sets]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set | ||
[mdn-strict-equality]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#strict_equality_using |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"root": true, | ||
"extends": "@exercism/eslint-config-javascript", | ||
"env": { | ||
"jest": true | ||
}, | ||
"overrides": [ | ||
{ | ||
"files": [".meta/proof.ci.js", ".meta/exemplar.js", "*.spec.js"], | ||
"excludedFiles": ["custom.spec.js"], | ||
"extends": "@exercism/eslint-config-javascript/maintainers" | ||
} | ||
] | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
node_modules | ||
yarn-error.log | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"blurb": "Use sets to avoid repeating tracks in a playlist", | ||
"authors": ["kristinaborn"], | ||
"contributors": [], | ||
"files": { | ||
"solution": ["ozans-playlist.js"], | ||
"test": ["ozans-playlist.spec.js"], | ||
"exemplar": [".meta/exemplar.js"] | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# Design | ||
|
||
## Learning objectives | ||
|
||
- Know how to use a set to remove duplicate elements from an array | ||
- Know how to convert between a set and an array | ||
- Know how to check whether a value is in a set | ||
- Know how to add and remove elements from a set | ||
- Know how to iterate over a set | ||
- Understand when a set might be preferable to an array | ||
|
||
## Out of Scope | ||
|
||
- Implementing common set operations like `union` and `difference` | ||
- `WeakSet` | ||
|
||
## Concepts | ||
|
||
The Concepts this exercise unlocks are: | ||
|
||
- `sets` | ||
|
||
## Prerequisites | ||
|
||
- `array-destructuring` because examples use array destructuring | ||
- `comparison` because this is where equality is explained | ||
- `array-loops` because it introduces the for-of loop | ||
- `rest-and-spread-operators` | ||
- `arrays` | ||
|
||
## Analyzer | ||
|
||
This exercise could benefit from the following rules in the [analyzer][analyzer]: | ||
|
||
For all tasks, verify that the student actually used a `Set`. | ||
|
||
1. `addTrack` | ||
|
||
- Verify that there was no redundant `Set.has()` call | ||
|
||
2. `deleteTrack` | ||
|
||
- Verify that there was no redundant `Set.has()` call | ||
|
||
[analyzer]: https://github.com/exercism/javascript-analyzer |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.