From 295f537c996893437f022606b11b14abc6bcaec6 Mon Sep 17 00:00:00 2001 From: Dario-DC <105294544+Dario-DC@users.noreply.github.com> Date: Wed, 18 Sep 2024 09:37:07 +0200 Subject: [PATCH] feat(curriculum): add Linked list lab (#56046) Co-authored-by: Zaira <33151350+zairahira@users.noreply.github.com> --- client/i18n/locales/english/intro.json | 7 +- .../lab-linked-list-class/index.md | 9 + .../_meta/lab-linked-list-class/meta.json | 11 + .../66dadcf18df3a76104054d95.md | 267 ++++++++++++++++++ 4 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 client/src/pages/learn/front-end-development/lab-linked-list-class/index.md create mode 100644 curriculum/challenges/_meta/lab-linked-list-class/meta.json create mode 100644 curriculum/challenges/english/25-front-end-development/lab-linked-list-class/66dadcf18df3a76104054d95.md diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json index 26f0166b8ae..9a19d1d61f5 100644 --- a/client/i18n/locales/english/intro.json +++ b/client/i18n/locales/english/intro.json @@ -2127,7 +2127,12 @@ "nixz": { "title": "262", "intro": [] }, "zywg": { "title": "263", "intro": [] }, "wraf": { "title": "264", "intro": [] }, - "kwxs": { "title": "265", "intro": [] }, + "lab-linked-list-class": { + "title": "Build a Linked List Class", + "intro": [ + "For this lab, you will build a linked list class using JavaScript." + ] + }, "muyw": { "title": "266", "intro": [] }, "mvzb": { "title": "267", "intro": [] }, "rmpy": { "title": "268", "intro": [] }, diff --git a/client/src/pages/learn/front-end-development/lab-linked-list-class/index.md b/client/src/pages/learn/front-end-development/lab-linked-list-class/index.md new file mode 100644 index 00000000000..c4e67bc20c9 --- /dev/null +++ b/client/src/pages/learn/front-end-development/lab-linked-list-class/index.md @@ -0,0 +1,9 @@ +--- +title: Introduction to the Build a Linked List Class +block: lab-linked-list-class +superBlock: front-end-development +--- + +## Introduction to the Build a Linked List Class + +For this lab, you will build a linked list class using JavaScript. diff --git a/curriculum/challenges/_meta/lab-linked-list-class/meta.json b/curriculum/challenges/_meta/lab-linked-list-class/meta.json new file mode 100644 index 00000000000..58e3f3667a6 --- /dev/null +++ b/curriculum/challenges/_meta/lab-linked-list-class/meta.json @@ -0,0 +1,11 @@ +{ + "name": "Build a Linked List Class", + "isUpcomingChange": true, + "usesMultifileEditor": true, + "blockType": "lab", + "dashedName": "lab-linked-list-class", + "order": 265, + "superBlock": "front-end-development", + "challengeOrder": [{ "id": "66dadcf18df3a76104054d95", "title": "Build a Linked List Class" }], + "helpCategory": "JavaScript" +} diff --git a/curriculum/challenges/english/25-front-end-development/lab-linked-list-class/66dadcf18df3a76104054d95.md b/curriculum/challenges/english/25-front-end-development/lab-linked-list-class/66dadcf18df3a76104054d95.md new file mode 100644 index 00000000000..bc739a7e4e8 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/lab-linked-list-class/66dadcf18df3a76104054d95.md @@ -0,0 +1,267 @@ +--- +id: 66dadcf18df3a76104054d95 +title: Build a Linked List Class +challengeType: 14 +dashedName: build-a-linked-list-class +--- + +# --description-- + +In this lab, you'll build a linked list, which is a linear collection of data elements, called nodes, where each node points to the next node in the linked list. Each node in a linked list contains two key pieces of information: the element itself, and a reference to the next node. + +**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab. + +**User Stories:** + +1. You should create a class named `LinkedList` to represent a linked list data structure. + +1. Each time a new `LinkedList` object is instantiated, its `length` and `head` properties should be set to `0` and `null`, respectively. + +1. The `LinkedList` class should have a property `Node`, which is a class instantiated with an `element` property set to the value passed at the instantiation, and a `next` property set to `null`. + +1. The `LinkedList` class should have a method `isEmpty` that returns `true` if the linked list is empty, and `false` otherwise. + +1. The `LinkedList` class should have a method `add` that creates a `Node` object from its argument and adds it to the linked list. + +1. The `add` method should either set the head to the new node when the node to be added is the first, or set the `next` property of the last node in the linked list to the node to be added. + +1. Each time a new node is added to the list the length of the list should be incremented. + +1. The `LinkedList` class should have a method `remove` that takes a single argument and removes the corresponding node from the list. + +1. Whenever a node is removed from the linked list, the `next` property of the previous node should be set to the following node, and the length of the list should be decremented. + +# --hints-- + +Your `LinkedList` class should instantiate objects with the `length` property set to `0`. + +```js +const test = new LinkedList(); +assert.strictEqual(test.length, 0); +``` + +Your `LinkedList` class should instantiate objects with the `head` property set to `null`. + +```js +const test = new LinkedList(); +assert.strictEqual(test.head, null); +``` + +Your `LinkedList` class should have a property `Node`. + +```js +const test = new LinkedList(); +assert.property(test, "Node"); +``` + +Your `Node` property should be a class that instantiates objects with an `element` property set to the value passed at the instantiation. + +```js +const test = new LinkedList(); +const node = new test.Node("pig"); +assert.strictEqual(node.element, "pig"); +``` + +Your `Node` property should be a class that instantiates objects with a `next` property set to `null`. + +```js +const test = new LinkedList(); +const node = new test.Node("pig"); +assert.strictEqual(node.next, null); +``` + +Your `LinkedList` class should have an `add` method. + +```js +const test = new LinkedList(); +assert.typeOf(test.add, 'function'); +``` + +Your `add` method should assign `head` to the first node object added to the linked list. + +```js +const test = new LinkedList(); +test.add("pig"); +const expected = { element: "pig", next: null } +assert.deepEqual(test.head, expected); +``` + +Your `add` method should set the `next` property of the last node in the linked list to the node to be added. + +```js +const test = new LinkedList(); +test.add("pig"); +test.add("dog") +const expected = { element: "pig", next: {element: "dog", next: null} } +assert.deepEqual(test.head, expected); +``` + +Each time a new node is added to the list the `length` of the list should be incremented. + +```js +const test = new LinkedList(); +test.add("pig"); +assert.strictEqual(test.length, 1); +test.add("dog"); +assert.strictEqual(test.length, 2); +test.add("sheep"); +assert.strictEqual(test.length, 3); +``` + +Your `LinkedList` class should have an `isEmpty` method. + +```js +const test = new LinkedList(); +assert.typeOf(test.isEmpty, 'function'); +``` + +Your `isEmpty` method should return `false` when there is at least one element in the linked list. + +```js +const test = new LinkedList(); +test.add('pig'); +test.add('dog'); +test.add('kitten'); +assert.isFalse(test.isEmpty()); +``` + +Your `isEmpty` method should return `true` when there are no elements in linked list. + +```js +const test = new LinkedList(); +assert.isTrue(test.isEmpty()); +``` + +The previous node in your `LinkedList` class should have a reference to the newest node created. + +```js +const test = new LinkedList(); +test.add("pig"); +test.add("dog") +test.add("sheep"); +assert(test.head.next.element === 'dog' && test.head.next.next.element === "sheep"); +``` + +Your `LinkedList` class should have a `remove` method. + +```js +const test = new LinkedList(); +assert.typeOf(test.remove, 'function'); +``` + +Your `remove` method should reassign `head` to the second node when the first node is removed. + +```js +const test = new LinkedList(); +test.add("pig"); +test.add("dog"); +test.add("sheep"); +test.remove("pig"); +const expected = { element: "dog", next: {element: "sheep", next: null} } +assert.deepEqual(test.head, expected); +``` + +Your `remove` method should decrease the `length` of the linked list by one for every node removed. + +```js +const test = new LinkedList(); +test.add("pig"); +test.add("dog"); +test.add("sheep"); +test.remove("pig"); +assert.strictEqual(test.length, 2); +test.remove("dog"); +assert.strictEqual(test.length, 1); +test.remove("sheep"); +assert.strictEqual(test.length, 0); +``` + +Your `remove` method should reassign the reference of the previous node of the removed node to the removed node's `next` reference. + +```js +const test = new LinkedList(); +test.add("pig"); +test.add("dog"); +test.add("sheep"); +test.add("cat"); +test.remove("sheep"); +const expected = { element: "pig", next: {element: "dog", next: {element: "cat", next: null}} } +assert.deepEqual(test.head, expected); +``` + +Your `remove` method should not change the linked list if the element does not exist in the linked list. + +```js +const test = new LinkedList(); +test.add("pig"); +test.add("dog"); +test.add("sheep"); +test.add("cat"); +test.remove("elephant"); +const expected = { element: "pig", next: {element: "dog", next: {element: "sheep", next: {element: "cat", next: null}}} } +assert.deepEqual(test.head, expected); +``` + +# --seed-- + +## --seed-contents-- + +```js + +``` + +# --solutions-- + +```js +class LinkedList { + constructor() { + this.length = 0; + this.head = null; + } + + Node = class { + constructor(element) { + this.element = element; + this.next = null; + } + } + + isEmpty() { + return this.length === 0; + } + + add(element) { + const node = new this.Node(element) + if (this.isEmpty()) { + this.head = node; + } else { + let currentNode = this.head; + while (currentNode.next !== null) { + currentNode = currentNode.next; + } + currentNode.next = node; + } + this.length++; + } + + remove(element) { + if (this.isEmpty()) { + return + } + let previousNode; + let currentNode = this.head; + while (currentNode.next !== null && currentNode.element !== element) { + previousNode = currentNode; + currentNode = currentNode.next; + } + if (currentNode.next === null && currentNode.element !== element) { + return; + } else if (previousNode) { + previousNode.next = currentNode.next + } else { + this.head = currentNode.next; + } + this.length-- + } +} +```