diff --git a/concepts/sets/.meta/config.json b/concepts/sets/.meta/config.json new file mode 100644 index 0000000000..332e14c531 --- /dev/null +++ b/concepts/sets/.meta/config.json @@ -0,0 +1,5 @@ +{ + "blurb": "Store a collection of unique values", + "authors": ["kristinaborn"], + "contributors": [] +} diff --git a/concepts/sets/about.md b/concepts/sets/about.md new file mode 100644 index 0000000000..f549817c41 --- /dev/null +++ b/concepts/sets/about.md @@ -0,0 +1,93 @@ +# About + +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 diff --git a/concepts/sets/introduction.md b/concepts/sets/introduction.md new file mode 100644 index 0000000000..e7f8a3c2d8 --- /dev/null +++ b/concepts/sets/introduction.md @@ -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 diff --git a/concepts/sets/links.json b/concepts/sets/links.json new file mode 100644 index 0000000000..ffde2c9233 --- /dev/null +++ b/concepts/sets/links.json @@ -0,0 +1,6 @@ +[ + { + "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set", + "description": "MDN: Sets" + } +] diff --git a/config.json b/config.json index 4e48887aff..85d4aff8c5 100644 --- a/config.json +++ b/config.json @@ -163,6 +163,20 @@ "concepts": ["promises"], "prerequisites": ["arrays", "callbacks", "errors", "recursion"], "status": "beta" + }, + { + "slug": "ozans-playlist", + "name": "Ozan's Playlist", + "uuid": "50dba808-070a-4873-b223-d565381c3b4c", + "concepts": ["sets"], + "prerequisites": [ + "array-destructuring", + "array-loops", + "comparison", + "rest-and-spread-operators", + "arrays" + ], + "status": "beta" } ], "practice": [ diff --git a/exercises/concept/ozans-playlist/.docs/hints.md b/exercises/concept/ozans-playlist/.docs/hints.md new file mode 100644 index 0000000000..362844f679 --- /dev/null +++ b/exercises/concept/ozans-playlist/.docs/hints.md @@ -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 diff --git a/exercises/concept/ozans-playlist/.docs/instructions.md b/exercises/concept/ozans-playlist/.docs/instructions.md new file mode 100644 index 0000000000..49006164c0 --- /dev/null +++ b/exercises/concept/ozans-playlist/.docs/instructions.md @@ -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 ` - `. + +```javascript +const playlist = [ + 'All Mine - Portishead', + 'Sight to Behold - Devendra Banhart', + 'Sour Times - Portishead', +]; + +listArtists(playlist); +//=> ['Portishead', 'Devendra Banhart'] +``` diff --git a/exercises/concept/ozans-playlist/.docs/introduction.md b/exercises/concept/ozans-playlist/.docs/introduction.md new file mode 100644 index 0000000000..e7f8a3c2d8 --- /dev/null +++ b/exercises/concept/ozans-playlist/.docs/introduction.md @@ -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 diff --git a/exercises/concept/ozans-playlist/.eslintrc b/exercises/concept/ozans-playlist/.eslintrc new file mode 100644 index 0000000000..1d4446029c --- /dev/null +++ b/exercises/concept/ozans-playlist/.eslintrc @@ -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" + } + ] +} diff --git a/exercises/concept/ozans-playlist/.gitignore b/exercises/concept/ozans-playlist/.gitignore new file mode 100644 index 0000000000..bdb912f98a --- /dev/null +++ b/exercises/concept/ozans-playlist/.gitignore @@ -0,0 +1,3 @@ +node_modules +yarn-error.log + diff --git a/exercises/concept/ozans-playlist/.meta/config.json b/exercises/concept/ozans-playlist/.meta/config.json new file mode 100644 index 0000000000..e2d42f6233 --- /dev/null +++ b/exercises/concept/ozans-playlist/.meta/config.json @@ -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"] + } +} diff --git a/exercises/concept/ozans-playlist/.meta/design.md b/exercises/concept/ozans-playlist/.meta/design.md new file mode 100644 index 0000000000..bb7fb11578 --- /dev/null +++ b/exercises/concept/ozans-playlist/.meta/design.md @@ -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 diff --git a/exercises/concept/ozans-playlist/.meta/exemplar.js b/exercises/concept/ozans-playlist/.meta/exemplar.js new file mode 100644 index 0000000000..86a71f4613 --- /dev/null +++ b/exercises/concept/ozans-playlist/.meta/exemplar.js @@ -0,0 +1,70 @@ +// @ts-check +// +// The line above enables type checking for this file. Various IDEs interpret +// the @ts-check directive. It will give you helpful autocompletion when +// implementing this exercise. + +/** + * Removes duplicate tracks from a playlist. + * + * @param {string[]} playlist + * @returns {string[]} new playlist with unique tracks + */ +export function removeDuplicates(playlist) { + return [...new Set(playlist)]; +} + +/** + * Checks whether a playlist includes a track. + * + * @param {string[]} playlist + * @param {string} track + * @returns {boolean} whether the track is in the playlist + */ +export function hasTrack(playlist, track) { + return new Set(playlist).has(track); +} + +/** + * Adds a track to a playlist. + * + * @param {string[]} playlist + * @param {string} track + * @returns {string[]} new playlist + */ +export function addTrack(playlist, track) { + return [...new Set(playlist).add(track)]; +} + +/** + * Deletes a track from a playlist. + * + * @param {string[]} playlist + * @param {string} track + * @returns {string[]} new playlist + */ +export function deleteTrack(playlist, track) { + const trackSet = new Set(playlist); + + trackSet.delete(track); + + return [...trackSet]; +} + +/** + * Returns the list of unique artists in a playlist + * + * @param {string[]} playlist + * @returns {string[]} unique artists + */ +export function listArtists(playlist) { + const artists = new Set(); + + for (let track of playlist.values()) { + const [, artist] = track.split(' - '); + + artists.add(artist); + } + + return [...artists]; +} diff --git a/exercises/concept/ozans-playlist/.npmrc b/exercises/concept/ozans-playlist/.npmrc new file mode 100644 index 0000000000..d26df800bb --- /dev/null +++ b/exercises/concept/ozans-playlist/.npmrc @@ -0,0 +1 @@ +audit=false diff --git a/exercises/concept/ozans-playlist/LICENSE b/exercises/concept/ozans-playlist/LICENSE new file mode 100644 index 0000000000..a7527f968f --- /dev/null +++ b/exercises/concept/ozans-playlist/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Exercism + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/exercises/concept/ozans-playlist/babel.config.js b/exercises/concept/ozans-playlist/babel.config.js new file mode 100644 index 0000000000..b9e80f6e56 --- /dev/null +++ b/exercises/concept/ozans-playlist/babel.config.js @@ -0,0 +1,15 @@ +module.exports = { + presets: [ + [ + '@babel/preset-env', + { + targets: { + node: 'current', + }, + useBuiltIns: 'entry', + corejs: '3.10', + }, + ], + ], + plugins: ['@babel/plugin-syntax-bigint'], +}; diff --git a/exercises/concept/ozans-playlist/ozans-playlist.js b/exercises/concept/ozans-playlist/ozans-playlist.js new file mode 100644 index 0000000000..fec164b886 --- /dev/null +++ b/exercises/concept/ozans-playlist/ozans-playlist.js @@ -0,0 +1,58 @@ +// @ts-check +// +// The line above enables type checking for this file. Various IDEs interpret +// the @ts-check directive. It will give you helpful autocompletion when +// implementing this exercise. + +/** + * Removes duplicate tracks from a playlist. + * + * @param {string[]} playlist + * @returns {string[]} new playlist with unique entries + */ +export function removeDuplicates(playlist) { + throw new Error('Please implement the removeDuplicates method'); +} + +/** + * Checks whether a playlist includes a track. + * + * @param {string[]} playlist + * @param {string} track + * @returns {boolean} whether the track is in the playlist + */ +export function hasTrack(playlist, track) { + throw new Error('Please implement the hasTrack method'); +} + +/** + * Adds a track to a playlist. + * + * @param {string[]} playlist + * @param {string} track + * @returns {string[]} new playlist + */ +export function addTrack(playlist, track) { + throw new Error('Please implement the addTrack method'); +} + +/** + * Deletes a track from a playlist. + * + * @param {string[]} playlist + * @param {string} track + * @returns {string[]} new playlist + */ +export function deleteTrack(playlist, track) { + throw new Error('Please implement the deleteTrack method'); +} + +/** + * Lists the unique artists in a playlist. + * + * @param {string[]} playlist + * @returns {string[]} list of artists + */ +export function listArtists(playlist) { + throw new Error('Please implement the listArtists method'); +} diff --git a/exercises/concept/ozans-playlist/ozans-playlist.spec.js b/exercises/concept/ozans-playlist/ozans-playlist.spec.js new file mode 100644 index 0000000000..af8e09aefc --- /dev/null +++ b/exercises/concept/ozans-playlist/ozans-playlist.spec.js @@ -0,0 +1,100 @@ +import { + addTrack, + deleteTrack, + hasTrack, + listArtists, + removeDuplicates, +} from './ozans-playlist'; + +describe("Ozan's playlist", () => { + describe('removeDuplicates', () => { + test('works for an empty playlist', () => { + const playlist = []; + + expect(removeDuplicates(playlist)).toEqual([]); + }); + + test('works for a non-empty playlist', () => { + const TRACK_1 = 'Two Paintings and a Drum - Carl Cox'; + const TRACK_2 = 'Leash Called Love - The Sugarcubes'; + const playlist = [TRACK_1, TRACK_2, TRACK_1]; + const expected = [TRACK_1, TRACK_2]; + + expect(removeDuplicates(playlist)).toEqual(expected); + }); + }); + + describe('hasTrack', () => { + const TRACK_1 = 'Big Science - Laurie Anderson'; + const TRACK_2 = 'Tightrope - Laurie Anderson'; + + test('returns true when the track is in the playlist', () => { + const playlist = [TRACK_1, TRACK_2]; + + expect(hasTrack(playlist, TRACK_1)).toBe(true); + }); + + test('returns false when the track is not in the playlist', () => { + const playlist = [TRACK_2]; + + expect(hasTrack(playlist, TRACK_1)).toBe(false); + }); + }); + + describe('addTrack', () => { + const TRACK_1 = 'Jigsaw Feeling - Siouxsie and the Banshees'; + const TRACK_2 = 'Feeling Good - Nina Simone'; + + test('adds a track that is not already in the playlist', () => { + const playlist = []; + const expected = [TRACK_1]; + + expect(addTrack(playlist, TRACK_1)).toEqual(expected); + }); + + test('does not add a track that is already in the playlist', () => { + const playlist = [TRACK_1, TRACK_2]; + const expected = [TRACK_1, TRACK_2]; + + expect(addTrack(playlist, TRACK_1)).toEqual(expected); + }); + }); + + describe('deleteTrack', () => { + const TRACK_1 = 'Ancestors - Tanya Tagaq'; + const TRACK_2 = 'Take This Hammer - Lead Belly'; + + test('works if the track is present in the playlist', () => { + const playlist = [TRACK_1, TRACK_2]; + const expected = [TRACK_2]; + + expect(deleteTrack(playlist, TRACK_1)).toEqual(expected); + }); + + test('works if the track is not present in the playlist', () => { + const playlist = [TRACK_2]; + const expected = [TRACK_2]; + + expect(deleteTrack(playlist, TRACK_1)).toEqual(expected); + }); + }); + + describe('listArtists', () => { + test('works for an empty playlist', () => { + const playlist = []; + + expect(listArtists(playlist)).toEqual([]); + }); + + test('works for a non-empty playlist', () => { + const playlist = [ + 'Onu Alma Beni Al - Sezen Aksu', + 'Famous Blue Raincoat - Leonard Cohen', + 'Rakkas - Sezen Aksu', + ]; + const expected = ['Sezen Aksu', 'Leonard Cohen']; + + expect(listArtists(playlist)).toEqual(expected); + }); + }); +}); diff --git a/exercises/concept/ozans-playlist/package.json b/exercises/concept/ozans-playlist/package.json new file mode 100644 index 0000000000..529094f4c9 --- /dev/null +++ b/exercises/concept/ozans-playlist/package.json @@ -0,0 +1,32 @@ +{ + "name": "@exercism/javascript-ozans-playlist", + "description": "Exercism concept exercise on sets", + "author": "Kristina Born", + "private": true, + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/exercism/javascript", + "directory": "exercises/concept/ozans-playlist" + }, + "devDependencies": { + "@babel/cli": "^7.13.16", + "@babel/core": "^7.13.16", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/preset-env": "^7.13.15", + "@exercism/eslint-config-javascript": "^0.3.1", + "@types/jest": "^26.0.22", + "@types/node": "^14.14.41", + "babel-eslint": "^10.1.0", + "babel-jest": "^26.6.3", + "core-js": "^3.10.2", + "eslint": "^7.24.0", + "jest": "^26.6.3" + }, + "dependencies": {}, + "scripts": { + "test": "jest --no-cache ./*", + "watch": "jest --no-cache --watch ./*", + "lint": "eslint ." + } +}