From c8b92ec5506c16994f09954e9cfc64a91364f9d9 Mon Sep 17 00:00:00 2001 From: Patrick Pluequett Date: Sun, 4 May 2025 00:04:26 +0200 Subject: [PATCH 1/2] fix bug and add test for deleting last item in a linked list --- specs/arrays/linkedlist.solution.test.js | 258 ++++++++++++----------- 1 file changed, 130 insertions(+), 128 deletions(-) diff --git a/specs/arrays/linkedlist.solution.test.js b/specs/arrays/linkedlist.solution.test.js index f7e03868..2902f186 100644 --- a/specs/arrays/linkedlist.solution.test.js +++ b/specs/arrays/linkedlist.solution.test.js @@ -24,151 +24,153 @@ */ class LinkedList { - constructor() { - this.tail = this.head = null; - this.length = 0; - } - push(value) { - const node = new Node(value); - this.length++; - if (!this.head) { - this.head = node; - } else { - this.tail.next = node; + constructor() { + this.tail = this.head = null; + this.length = 0; } - this.tail = node; - } - pop() { - if (!this.head) return null; - if (this.head === this.tail) { - const node = this.head; - this.head = this.tail = null; - return node.value; + push(value) { + const node = new Node(value); + this.length++; + if (!this.head) { + this.head = node; + } else { + this.tail.next = node; + } + this.tail = node; } - const penultimate = this._find( - null, - (value, nodeValue, i, current) => current.next === this.tail - ); - const ans = penultimate.next.value; - penultimate.next = null; - this.tail = penultimate; - this.length--; - return ans; - } - _find(value, test = this.test) { - let current = this.head; - let i = 0; - while (current) { - if (test(value, current.value, i, current)) { - return current; - } - current = current.next; - i++; + pop() { + if (!this.head) return null; + if (this.head === this.tail) { + const node = this.head; + this.head = this.tail = null; + return node.value; + } + const penultimate = this._find( + null, + (value, nodeValue, i, current) => current.next === this.tail + ); + const ans = penultimate.next.value; + penultimate.next = null; + this.tail = penultimate; + this.length--; + return ans; } - return null; - } - get(index) { - const node = this._find(index, this.testIndex); - if (!node) return null; - return node.value; - } - delete(index) { - if (index === 0) { - const head = this.head; - if (head) { - this.head = head.next; - } else { - this.head = null; - } - this.length--; - return head.value; + _find(value, test = this.test) { + let current = this.head; + let i = 0; + while (current) { + if (test(value, current.value, i, current)) { + return current; + } + current = current.next; + i++; + } + return null; } + get(index) { + const node = this._find(index, this.testIndex); + if (!node) return null; + return node.value; + } + delete(index) { + if (index === 0) { + const head = this.head; + if (head) { + this.head = head.next; + } else { + this.head = null; + } + this.length--; + return head.value; + } - const node = this._find(index - 1, this.testIndex); - const excise = node.next; - if (!excise) return null; - node.next = excise.next; - if (!node.next.next) this.tail = node.next; - this.length--; - return excise.value; - } - test(search, nodeValue) { - return search === nodeValue; - } - testIndex(search, __, i) { - return search === i; - } - serialize() { - const ans = []; - let current = this.head; - if (!current) return ans; - while (current) { - ans.push(current.value); - current = current.next; + const node = this._find(index - 1, this.testIndex); + const excise = node.next; + if (!excise) return null; + node.next = excise.next; + if (!node.next) this.tail = node; + this.length--; + return excise.value; + } + test(search, nodeValue) { + return search === nodeValue; + } + testIndex(search, __, i) { + return search === i; + } + serialize() { + const ans = []; + let current = this.head; + if (!current) return ans; + while (current) { + ans.push(current.value); + current = current.next; + } + return ans; } - return ans; - } } class Node { - constructor(value) { - this.value = value; - this.next = null; - } + constructor(value) { + this.value = value; + this.next = null; + } } // unit tests // do not modify the below code -describe("LinkedList", function () { - const range = (length) => - Array.apply(null, { length: length }).map(Number.call, Number); - const abcRange = (length) => - range(length).map((num) => String.fromCharCode(97 + num)); - let list; +describe('LinkedList', function () { + const range = (length) => + Array.apply(null, { length: length }).map(Number.call, Number); + const abcRange = (length) => + range(length).map((num) => String.fromCharCode(97 + num)); + let list; - beforeEach(() => { - list = new LinkedList(); - }); + beforeEach(() => { + list = new LinkedList(); + }); - test("constructor", () => { - expect(list).toEqual(expect.any(LinkedList)); - }); + test('constructor', () => { + expect(list).toEqual(expect.any(LinkedList)); + }); - test("push", () => { - abcRange(26).map((character) => list.push(character)); - expect(list.length).toEqual(26); - }); + test('push', () => { + abcRange(26).map((character) => list.push(character)); + expect(list.length).toEqual(26); + }); - test("pop", () => { - abcRange(13).map((character) => list.push(character)); - expect(list.length).toEqual(13); - range(10).map(() => list.pop()); - expect(list.length).toEqual(3); - expect(list.pop()).toEqual("c"); - }); + test('pop', () => { + abcRange(13).map((character) => list.push(character)); + expect(list.length).toEqual(13); + range(10).map(() => list.pop()); + expect(list.length).toEqual(3); + expect(list.pop()).toEqual('c'); + }); - test("get", () => { - list.push("first"); - expect(list.get(0)).toEqual("first"); - list.push("second"); - expect(list.get(1)).toEqual("second"); - expect(list.get(0)).toEqual("first"); - abcRange(26).map((character) => list.push(character)); - expect(list.get(27)).toEqual("z"); - expect(list.get(0)).toEqual("first"); - expect(list.get(9)).toEqual("h"); - list.pop(); - expect(list.get(list.length - 1)).toEqual("y"); - }); + test('get', () => { + list.push('first'); + expect(list.get(0)).toEqual('first'); + list.push('second'); + expect(list.get(1)).toEqual('second'); + expect(list.get(0)).toEqual('first'); + abcRange(26).map((character) => list.push(character)); + expect(list.get(27)).toEqual('z'); + expect(list.get(0)).toEqual('first'); + expect(list.get(9)).toEqual('h'); + list.pop(); + expect(list.get(list.length - 1)).toEqual('y'); + }); - test("delete", () => { - abcRange(26).map((character) => list.push(character)); - list.delete(13); - expect(list.length).toEqual(25); - expect(list.get(12)).toEqual("m"); - expect(list.get(13)).toEqual("o"); - list.delete(0); - expect(list.length).toEqual(24); - expect(list.get(0)).toEqual("b"); - }); + test('delete', () => { + abcRange(26).map((character) => list.push(character)); + list.delete(13); + expect(list.length).toEqual(25); + expect(list.get(12)).toEqual('m'); + expect(list.get(13)).toEqual('o'); + list.delete(0); + expect(list.length).toEqual(24); + expect(list.get(0)).toEqual('b'); + list.delete(23); + expect(list.get(22)).toEqual('y'); + }); }); From 33a45f0306c2f7acf13259083ec984c54fd72e36 Mon Sep 17 00:00:00 2001 From: Patrick Pluequett Date: Sun, 4 May 2025 00:16:46 +0200 Subject: [PATCH 2/2] adjust format and add test for deleting node --- specs/arrays/linkedlist.solution.test.js | 261 ++++++++++++----------- 1 file changed, 131 insertions(+), 130 deletions(-) diff --git a/specs/arrays/linkedlist.solution.test.js b/specs/arrays/linkedlist.solution.test.js index 2902f186..00c6507f 100644 --- a/specs/arrays/linkedlist.solution.test.js +++ b/specs/arrays/linkedlist.solution.test.js @@ -24,153 +24,154 @@ */ class LinkedList { - constructor() { - this.tail = this.head = null; - this.length = 0; + constructor() { + this.tail = this.head = null; + this.length = 0; + } + push(value) { + const node = new Node(value); + this.length++; + if (!this.head) { + this.head = node; + } else { + this.tail.next = node; } - push(value) { - const node = new Node(value); - this.length++; - if (!this.head) { - this.head = node; - } else { - this.tail.next = node; - } - this.tail = node; + this.tail = node; + } + pop() { + if (!this.head) return null; + if (this.head === this.tail) { + const node = this.head; + this.head = this.tail = null; + return node.value; } - pop() { - if (!this.head) return null; - if (this.head === this.tail) { - const node = this.head; - this.head = this.tail = null; - return node.value; - } - const penultimate = this._find( - null, - (value, nodeValue, i, current) => current.next === this.tail - ); - const ans = penultimate.next.value; - penultimate.next = null; - this.tail = penultimate; - this.length--; - return ans; + const penultimate = this._find( + null, + (value, nodeValue, i, current) => current.next === this.tail + ); + const ans = penultimate.next.value; + penultimate.next = null; + this.tail = penultimate; + this.length--; + return ans; + } + _find(value, test = this.test) { + let current = this.head; + let i = 0; + while (current) { + if (test(value, current.value, i, current)) { + return current; + } + current = current.next; + i++; } - _find(value, test = this.test) { - let current = this.head; - let i = 0; - while (current) { - if (test(value, current.value, i, current)) { - return current; - } - current = current.next; - i++; - } - return null; + return null; + } + get(index) { + const node = this._find(index, this.testIndex); + if (!node) return null; + return node.value; + } + delete(index) { + if (index === 0) { + const head = this.head; + if (head) { + this.head = head.next; + } else { + this.head = null; + } + this.length--; + return head.value; } - get(index) { - const node = this._find(index, this.testIndex); - if (!node) return null; - return node.value; - } - delete(index) { - if (index === 0) { - const head = this.head; - if (head) { - this.head = head.next; - } else { - this.head = null; - } - this.length--; - return head.value; - } - const node = this._find(index - 1, this.testIndex); - const excise = node.next; - if (!excise) return null; - node.next = excise.next; - if (!node.next) this.tail = node; - this.length--; - return excise.value; - } - test(search, nodeValue) { - return search === nodeValue; - } - testIndex(search, __, i) { - return search === i; - } - serialize() { - const ans = []; - let current = this.head; - if (!current) return ans; - while (current) { - ans.push(current.value); - current = current.next; - } - return ans; + const node = this._find(index - 1, this.testIndex); + const excise = node.next; + if (!excise) return null; + node.next = excise.next; + if (!node.next) this.tail = node; + this.length--; + return excise.value; + } + test(search, nodeValue) { + return search === nodeValue; + } + testIndex(search, __, i) { + return search === i; + } + serialize() { + const ans = []; + let current = this.head; + if (!current) return ans; + while (current) { + ans.push(current.value); + current = current.next; } + return ans; + } } class Node { - constructor(value) { - this.value = value; - this.next = null; - } + constructor(value) { + this.value = value; + this.next = null; + } } // unit tests // do not modify the below code -describe('LinkedList', function () { - const range = (length) => - Array.apply(null, { length: length }).map(Number.call, Number); - const abcRange = (length) => - range(length).map((num) => String.fromCharCode(97 + num)); - let list; +describe("LinkedList", function () { + const range = (length) => + Array.apply(null, { length: length }).map(Number.call, Number); + const abcRange = (length) => + range(length).map((num) => String.fromCharCode(97 + num)); + let list; - beforeEach(() => { - list = new LinkedList(); - }); + beforeEach(() => { + list = new LinkedList(); + }); - test('constructor', () => { - expect(list).toEqual(expect.any(LinkedList)); - }); + test("constructor", () => { + expect(list).toEqual(expect.any(LinkedList)); + }); - test('push', () => { - abcRange(26).map((character) => list.push(character)); - expect(list.length).toEqual(26); - }); + test("push", () => { + abcRange(26).map((character) => list.push(character)); + expect(list.length).toEqual(26); + }); - test('pop', () => { - abcRange(13).map((character) => list.push(character)); - expect(list.length).toEqual(13); - range(10).map(() => list.pop()); - expect(list.length).toEqual(3); - expect(list.pop()).toEqual('c'); - }); + test("pop", () => { + abcRange(13).map((character) => list.push(character)); + expect(list.length).toEqual(13); + range(10).map(() => list.pop()); + expect(list.length).toEqual(3); + expect(list.pop()).toEqual("c"); + }); - test('get', () => { - list.push('first'); - expect(list.get(0)).toEqual('first'); - list.push('second'); - expect(list.get(1)).toEqual('second'); - expect(list.get(0)).toEqual('first'); - abcRange(26).map((character) => list.push(character)); - expect(list.get(27)).toEqual('z'); - expect(list.get(0)).toEqual('first'); - expect(list.get(9)).toEqual('h'); - list.pop(); - expect(list.get(list.length - 1)).toEqual('y'); - }); + test("get", () => { + list.push("first"); + expect(list.get(0)).toEqual("first"); + list.push("second"); + expect(list.get(1)).toEqual("second"); + expect(list.get(0)).toEqual("first"); + abcRange(26).map((character) => list.push(character)); + expect(list.get(27)).toEqual("z"); + expect(list.get(0)).toEqual("first"); + expect(list.get(9)).toEqual("h"); + list.pop(); + expect(list.get(list.length - 1)).toEqual("y"); + }); - test('delete', () => { - abcRange(26).map((character) => list.push(character)); - list.delete(13); - expect(list.length).toEqual(25); - expect(list.get(12)).toEqual('m'); - expect(list.get(13)).toEqual('o'); - list.delete(0); - expect(list.length).toEqual(24); - expect(list.get(0)).toEqual('b'); - list.delete(23); - expect(list.get(22)).toEqual('y'); - }); + test("delete", () => { + abcRange(26).map((character) => list.push(character)); + list.delete(13); + expect(list.length).toEqual(25); + expect(list.get(12)).toEqual("m"); + expect(list.get(13)).toEqual("o"); + list.delete(0); + expect(list.length).toEqual(24); + expect(list.get(0)).toEqual("b"); + list.delete(23); + expect(list.get(22)).toEqual("y"); + list.delete(23); + }); });