From dd4646d1594f1909660af0d48aad4fefe1e5e55c Mon Sep 17 00:00:00 2001 From: harris-ahmad <24100315@lums.edu.pk> Date: Sun, 28 Jul 2024 21:12:13 +0500 Subject: [PATCH 01/21] all insertions funcs added --- go/LinkedList/doubly/LinkedList.go | 68 ++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 go/LinkedList/doubly/LinkedList.go diff --git a/go/LinkedList/doubly/LinkedList.go b/go/LinkedList/doubly/LinkedList.go new file mode 100644 index 0000000..2dd7163 --- /dev/null +++ b/go/LinkedList/doubly/LinkedList.go @@ -0,0 +1,68 @@ +package singly + +type Node struct { + data interface{} + next *Node + prev *Node +} + +type LinkedList struct { + head *Node + tail *Node + length int +} + +func NewNode(data interface{}) *Node { + return &Node{data: data} +} + +func NewLinkedList() *LinkedList { + return &LinkedList{ + head: nil, + tail: nil, + length: 0, + } +} + +func (dll *LinkedList) Prepend(data interface{}) { + newNode := NewNode(data) + if dll.head == nil { + dll.head = newNode + dll.tail = newNode + } else { + newNode.next = dll.head + dll.head.prev = newNode + dll.head = newNode + } +} + +func (dll *LinkedList) Append(data interface{}) { + newNode := NewNode(data) + if dll.head == nil { + dll.head = newNode + dll.tail = newNode + } else { + newNode.prev = dll.tail + dll.tail.next = newNode + dll.tail = newNode + } +} + +func (dll *LinkedList) InsertBetween(data interface{}, after interface{}) { + current := dll.head + for current != nil && current.data != after { + current = current.next + } + if current != nil { + newNode := NewNode(data) + newNode.next = current.next + newNode.prev = current + if current.next != nil { + current.prev.next = newNode + } + current.next = newNode + if newNode.next == nil { + dll.tail = newNode + } + } +} From 66a1e2a083998068f649a1ea196c63d569388024 Mon Sep 17 00:00:00 2001 From: harris-ahmad <24100315@lums.edu.pk> Date: Sun, 28 Jul 2024 21:17:08 +0500 Subject: [PATCH 02/21] deletion funcs added --- go/LinkedList/doubly/LinkedList.go | 57 ++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/go/LinkedList/doubly/LinkedList.go b/go/LinkedList/doubly/LinkedList.go index 2dd7163..4bd6e92 100644 --- a/go/LinkedList/doubly/LinkedList.go +++ b/go/LinkedList/doubly/LinkedList.go @@ -1,4 +1,4 @@ -package singly +package doubly type Node struct { data interface{} @@ -6,7 +6,7 @@ type Node struct { prev *Node } -type LinkedList struct { +type DoublyLinkedList struct { head *Node tail *Node length int @@ -16,15 +16,15 @@ func NewNode(data interface{}) *Node { return &Node{data: data} } -func NewLinkedList() *LinkedList { - return &LinkedList{ +func NewDoublyLinkedList() *DoublyLinkedList { + return &DoublyLinkedList{ head: nil, tail: nil, length: 0, } } -func (dll *LinkedList) Prepend(data interface{}) { +func (dll *DoublyLinkedList) Prepend(data interface{}) { newNode := NewNode(data) if dll.head == nil { dll.head = newNode @@ -36,7 +36,7 @@ func (dll *LinkedList) Prepend(data interface{}) { } } -func (dll *LinkedList) Append(data interface{}) { +func (dll *DoublyLinkedList) Append(data interface{}) { newNode := NewNode(data) if dll.head == nil { dll.head = newNode @@ -48,7 +48,7 @@ func (dll *LinkedList) Append(data interface{}) { } } -func (dll *LinkedList) InsertBetween(data interface{}, after interface{}) { +func (dll *DoublyLinkedList) InsertBetween(data interface{}, after interface{}) { current := dll.head for current != nil && current.data != after { current = current.next @@ -66,3 +66,46 @@ func (dll *LinkedList) InsertBetween(data interface{}, after interface{}) { } } } + +func (dll *DoublyLinkedList) DeleteHead() { + if dll.head != nil { + if dll.head.next != nil { + dll.head = dll.head.next + dll.head.prev = nil + } else { + dll.head = nil + dll.tail = nil + } + } +} + +func (dll *DoublyLinkedList) DeleteTail() { + if dll.tail != nil { + if dll.tail.prev != nil { + dll.tail = dll.tail.prev + dll.tail.next = nil + } else { + dll.head = nil + dll.tail = nil + } + } +} + +func (dll *DoublyLinkedList) DeleteAny(data interface{}) { + current := dll.head + for current != nil && current.data != data { + current = current.next + } + if current != nil { + if current.prev != nil { + current.prev.next = current.next + } else { + dll.head = current.next + } + if current.next != nil { + current.next.prev = current.prev + } else { + dll.tail = current.prev + } + } +} From e64b4fe15b35993589236e2ad6d65fef20a80d7c Mon Sep 17 00:00:00 2001 From: Harris Ahmad <24100315@lums.edu.pk> Date: Tue, 30 Jul 2024 04:06:10 +0500 Subject: [PATCH 03/21] Create CODE_OF_CONDUCT.md --- CODE_OF_CONDUCT.md | 128 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..05b309a --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +harris.ahmad55@gmail.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. From d3f3be194a076fa2eac1d67e8a0fdf7d4ad00146 Mon Sep 17 00:00:00 2001 From: harris-ahmad <24100315@lums.edu.pk> Date: Tue, 30 Jul 2024 04:08:19 +0500 Subject: [PATCH 04/21] complete --- go/LinkedList/doubly/LinkedList.go | 116 ++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/go/LinkedList/doubly/LinkedList.go b/go/LinkedList/doubly/LinkedList.go index 4bd6e92..61dcfd0 100644 --- a/go/LinkedList/doubly/LinkedList.go +++ b/go/LinkedList/doubly/LinkedList.go @@ -1,4 +1,6 @@ -package doubly +package main + +import "fmt" type Node struct { data interface{} @@ -109,3 +111,115 @@ func (dll *DoublyLinkedList) DeleteAny(data interface{}) { } } } + +func (dll *DoublyLinkedList) Size() int { + count := 0 + current := dll.head + for current != nil { + count++ + current = current.next + } + return count +} + +func (dll *DoublyLinkedList) Reverse() { + current := dll.head + var prev *Node + dll.tail = current + for current != nil { + prev = current.prev + current.prev = current.next + current.next = prev + if current.prev == nil { + dll.head = current + } + current = current.prev + } +} + +func (dll *DoublyLinkedList) Find(data interface{}) *Node { + current := dll.head + for current != nil { + if current.data == data { + return current + } + current = current.next + } + return nil +} + +func (dll *DoublyLinkedList) Clear() { + dll.head = nil + dll.tail = nil +} + +func (dll *DoublyLinkedList) PrintList() { + current := dll.head + for current != nil { + fmt.Print(current.data, " ") + current = current.next + } + fmt.Println() +} + +func main() { + dll := DoublyLinkedList{} + + // Test appending and prepending + fmt.Println("Testing append and prepend:") + dll.Append(1) + dll.Append(2) + dll.Append(3) + dll.Prepend(0) + dll.PrintList() // Expected Output: 0 1 2 3 + + // Test inserting between nodes + fmt.Println("Testing insert between:") + dll.InsertBetween(1.5, 1) + dll.PrintList() // Expected Output: 0 1 1.5 2 3 + + // Test deleting head + fmt.Println("Testing delete head:") + dll.DeleteHead() + dll.PrintList() // Expected Output: 1 1.5 2 3 + + // Test deleting tail + fmt.Println("Testing delete tail:") + dll.DeleteTail() + dll.PrintList() // Expected Output: 1 1.5 2 + + // Test deleting any node + fmt.Println("Testing delete any:") + dll.DeleteAny(1.5) + dll.PrintList() // Expected Output: 1 2 + + // Test reversing the list + fmt.Println("Testing reverse list:") + dll.Reverse() + dll.PrintList() // Expected Output: 2 1 + + // Test finding a node + fmt.Println("Testing find:") + node := dll.Find(1) + if node != nil { + fmt.Println(node.data) // Expected Output: 1 + } else { + fmt.Println("Node not found") + } + + // Test clearing the list + fmt.Println("Testing clear:") + dll.Clear() + dll.PrintList() // Expected Output: (empty list) + + // Test reading a list + fmt.Println("Testing read list:") + dll.Append(10) + dll.Append(20) + dll.Append(30) + dll.PrintList() // Expected Output: 10 20 30 + + // Test size of the list + fmt.Println("Testing size:") + fmt.Println(dll.Size()) // Expected Output: 3 +} From 4373fab7f7147ac7e56fa644a7eca7eb96ab944d Mon Sep 17 00:00:00 2001 From: harris-ahmad <24100315@lums.edu.pk> Date: Tue, 30 Jul 2024 04:10:24 +0500 Subject: [PATCH 05/21] code for .Find fixed --- go/LinkedList/doubly/LinkedList.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/go/LinkedList/doubly/LinkedList.go b/go/LinkedList/doubly/LinkedList.go index 61dcfd0..02e60ef 100644 --- a/go/LinkedList/doubly/LinkedList.go +++ b/go/LinkedList/doubly/LinkedList.go @@ -198,6 +198,9 @@ func main() { dll.Reverse() dll.PrintList() // Expected Output: 2 1 + dll.Clear() + dll.Append(1) + // Test finding a node fmt.Println("Testing find:") node := dll.Find(1) From af339c931e4e14b70a44f2a9eb935ad384e2134a Mon Sep 17 00:00:00 2001 From: harris-ahmad <24100315@lums.edu.pk> Date: Tue, 30 Jul 2024 04:11:31 +0500 Subject: [PATCH 06/21] workflow files removed --- .github/workflows/cpp-tests.yml | 26 --------------------- .github/workflows/go-tests.yml | 32 -------------------------- .github/workflows/nodejs-tests.yml | 36 ------------------------------ .github/workflows/python-tests.yml | 25 --------------------- 4 files changed, 119 deletions(-) delete mode 100644 .github/workflows/cpp-tests.yml delete mode 100644 .github/workflows/go-tests.yml delete mode 100644 .github/workflows/nodejs-tests.yml delete mode 100644 .github/workflows/python-tests.yml diff --git a/.github/workflows/cpp-tests.yml b/.github/workflows/cpp-tests.yml deleted file mode 100644 index e30208c..0000000 --- a/.github/workflows/cpp-tests.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: C++ Tests - -on: - # push: - # branches: - # - main - pull_request: - branches: - - main - -jobs: - test: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Install Dependencies - run: sudo apt-get install -y g++ - - - name: Run Tests - run: | - cd cpp/LinkedList/singly - g++ -std=c++14 list_test.cc -o list_test - ./list_test diff --git a/.github/workflows/go-tests.yml b/.github/workflows/go-tests.yml deleted file mode 100644 index be6f70b..0000000 --- a/.github/workflows/go-tests.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Go Tests - -on: - # push: - # branches: - # - main - pull_request: - branches: - - main - -jobs: - test: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Set up Go - uses: actions/setup-go@v2 - with: - go-version: '^1.16' - - - name: Set up dependencies - run: | - cd go/LinkedList/singly - go mod tidy - - - name: Run tests - run: | - cd go/LinkedList/singly - go test -v . diff --git a/.github/workflows/nodejs-tests.yml b/.github/workflows/nodejs-tests.yml deleted file mode 100644 index e355216..0000000 --- a/.github/workflows/nodejs-tests.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Node.js Tests - -on: - # push: - # branches: - # - main - pull_request: - branches: - - main - -jobs: - test: - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [16.x, 18.x] - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Set up Node.js - uses: actions/setup-node@v2 - with: - node-version: ${{ matrix.node-version }} - - - name: Install dependencies - run: | - cd js/LinkedList/singly - npm install - - - name: Run tests - run: | - cd js/LinkedList/singly - npm test diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml deleted file mode 100644 index 5fbcc6c..0000000 --- a/.github/workflows/python-tests.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Python Tests - -on: - # push: - # branches: - # - main - pull_request: - branches: - - main - -jobs: - test: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.12.3' - - - name: Run tests - run: python -m unittest discover -s python/LinkedList/singly -p 'list_test.py' From a64b904f6c5b912697fb53f3a8379a936a0ca295 Mon Sep 17 00:00:00 2001 From: harris-ahmad <24100315@lums.edu.pk> Date: Tue, 30 Jul 2024 04:22:16 +0500 Subject: [PATCH 07/21] basic insertion funcs added --- js/LinkedList/doubly/list.js | 68 ++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 js/LinkedList/doubly/list.js diff --git a/js/LinkedList/doubly/list.js b/js/LinkedList/doubly/list.js new file mode 100644 index 0000000..bdd0030 --- /dev/null +++ b/js/LinkedList/doubly/list.js @@ -0,0 +1,68 @@ +class Node { + constructor(data) { + this.data = data; + this.next = null; + this.prev = null; + } +} + +class LinkedList { + constructor() { + this.head = null; + this.tail = null; + this.length = 0; + } + + getHead() { + return this.head; + } + + getTail() { + return this.tail; + } + + prepend(data) { + const newNode = new Node(data); + if (!this.head) { + this.head = newNode; + this.tail = newNode; + } else { + this.head.prev = newNode; + newNode.next = this.head; + this.head = newNode; + } + } + + append(data) { + const newNode = new Node(data); + if (!this.head) { + this.head = newNode; + this.tail = newNode; + } else { + this.tail.next = newNode; + newNode.prev = this.tail; + this.tail = newNode; + } + } + + print() { + let curr = this.head; + let result = [] + while (curr) { + result.push(curr.data.toString()); + curr = curr.next; + } + console.log(result.join(" <-> ")); + } +} + +function main() { + var dll = new LinkedList(); + dll.prepend(1); + dll.prepend(2); + dll.append(3); + + dll.print(); +} + +main() \ No newline at end of file From c6f79b58c7936bfaa61c640bb1be45f9b47df53a Mon Sep 17 00:00:00 2001 From: harris-ahmad <24100315@lums.edu.pk> Date: Tue, 30 Jul 2024 04:24:14 +0500 Subject: [PATCH 08/21] node_modules removed --- js/LinkedList/singly/list_test.mjs | 131 ---- js/LinkedList/singly/package-lock.json | 850 ------------------------- js/LinkedList/singly/package.json | 9 - 3 files changed, 990 deletions(-) delete mode 100644 js/LinkedList/singly/list_test.mjs delete mode 100644 js/LinkedList/singly/package-lock.json delete mode 100644 js/LinkedList/singly/package.json diff --git a/js/LinkedList/singly/list_test.mjs b/js/LinkedList/singly/list_test.mjs deleted file mode 100644 index 9bb6b8b..0000000 --- a/js/LinkedList/singly/list_test.mjs +++ /dev/null @@ -1,131 +0,0 @@ -import { expect } from 'chai'; -import LinkedList from "./list.mjs"; - -describe('LinkedList', () => { - let list; - - beforeEach(() => { - list = new LinkedList(); - }); - - describe('getHead', () => { - it('should return null for an empty list', () => { - expect(list.getHead()).to.be.null; - }); - - it('should return the head node of the list', () => { - list.prepend({ id: 1, value: 'first' }); - expect(list.getHead().data).to.deep.equal({ id: 1, value: 'first' }); - }); - }); - - describe('getTail', () => { - it('should return null for an empty list', () => { - expect(list.getTail()).to.be.null; - }); - - it('should return the tail node of the list', () => { - list.append({ id: 1, value: 'first' }); - expect(list.getTail().data).to.deep.equal({ id: 1, value: 'first' }); - }); - }); - - describe('prepend', () => { - it('should add a node to the beginning of the list', () => { - list.prepend({ id: 1, value: 'first' }); - expect(list.getHead().data).to.deep.equal({ id: 1, value: 'first' }); - expect(list.size()).to.equal(1); - }); - - it('should correctly update the head and tail for the first node', () => { - list.prepend({ id: 1, value: 'first' }); - expect(list.getHead().data).to.deep.equal({ id: 1, value: 'first' }); - expect(list.getTail().data).to.deep.equal({ id: 1, value: 'first' }); - }); - }); - - describe('append', () => { - it('should add a node to the end of the list', () => { - list.append({ id: 1, value: 'first' }); - expect(list.getTail().data).to.deep.equal({ id: 1, value: 'first' }); - expect(list.size()).to.equal(1); - }); - - it('should correctly update the tail when appending nodes', () => { - list.append({ id: 1, value: 'first' }); - list.append({ id: 2, value: 'second' }); - expect(list.getTail().data).to.deep.equal({ id: 2, value: 'second' }); - }); - }); - - describe('insertBetween', () => { - it('should insert a node between two nodes', () => { - list.append({ id: 1, value: 'first' }); - list.append({ id: 3, value: 'third' }); - list.insertBetween({ id: 2, value: 'second' }, { id: 3, value: 'third' }, { id: 1, value: 'first' }); - expect(list.find(2).data).to.deep.equal({ id: 2, value: 'second' }); - }); - }); - - describe('deleteHead', () => { - it('should delete the head node of the list', () => { - list.append({ id: 1, value: 'first' }); - list.deleteHead(); - expect(list.getHead()).to.be.null; - }); - }); - - describe('deleteTail', () => { - it('should delete the tail node of the list', () => { - list.append({ id: 1, value: 'first' }); - list.deleteTail(); - expect(list.getTail()).to.be.null; - }); - }); - - describe('deleteAny', () => { - it('should delete any node matching the target data', () => { - list.append({ id: 1, value: 'first' }); - list.append({ id: 2, value: 'second' }); - list.deleteAny({ id: 1 }); - expect(list.find(1)).to.be.null; - }); - }); - - describe('size', () => { - it('should return the correct size of the list', () => { - list.append({ id: 1, value: 'first' }); - list.append({ id: 2, value: 'second' }); - expect(list.size()).to.equal(2); - }); - }); - - describe('reverseList', () => { - it('should reverse the linked list', () => { - list.append({ id: 1, value: 'first' }); - list.append({ id: 2, value: 'second' }); - list.reverseList(); - expect(list.getHead().data).to.deep.equal({ id: 2, value: 'second' }); - }); - }); - - describe('find', () => { - it('should find a node by its id', () => { - list.append({ id: 1, value: 'first' }); - expect(list.find(1).data).to.deep.equal({ id: 1, value: 'first' }); - }); - - it('should return null if the node is not found', () => { - expect(list.find(999)).to.be.null; - }); - }); - - describe('clear', () => { - it('should clear the list and remove all nodes', () => { - list.append({ id: 1, value: 'first' }); - list.clear(); - expect(list.getHead()).to.be.null; - expect(list.size()).to.equal(0); - }); - }); -}); diff --git a/js/LinkedList/singly/package-lock.json b/js/LinkedList/singly/package-lock.json deleted file mode 100644 index ab74f1f..0000000 --- a/js/LinkedList/singly/package-lock.json +++ /dev/null @@ -1,850 +0,0 @@ -{ - "name": "singly", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "dependencies": { - "chai": "^5.1.1", - "mocha": "^10.6.0" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chai": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", - "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "engines": { - "node": ">= 16" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "engines": { - "node": ">=6" - } - }, - "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "bin": { - "flat": "cli.js" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "engines": { - "node": "*" - } - }, - "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/loupe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz", - "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", - "dependencies": { - "get-func-name": "^2.0.1" - } - }, - "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.6.0.tgz", - "integrity": "sha512-hxjt4+EEB0SA0ZDygSS015t65lJw/I2yRCS3Ae+SJ5FrbzrXgfYwJr96f0OvIXdj7h4lv/vLCrH3rkiuizFSvw==", - "dependencies": { - "ansi-colors": "^4.1.3", - "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", - "debug": "^4.3.5", - "diff": "^5.2.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^8.1.0", - "he": "^1.2.0", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", - "ms": "^2.1.3", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", - "engines": { - "node": ">= 14.16" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==" - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/js/LinkedList/singly/package.json b/js/LinkedList/singly/package.json deleted file mode 100644 index 0b45b18..0000000 --- a/js/LinkedList/singly/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "scripts": { - "test": "mocha list_test.mjs" - }, - "dependencies": { - "chai": "^5.1.1", - "mocha": "^10.6.0" - } -} From cc30957b3df9c3e5e191af430e3b89274352d8d4 Mon Sep 17 00:00:00 2001 From: harris-ahmad <24100315@lums.edu.pk> Date: Mon, 5 Aug 2024 01:09:51 +0500 Subject: [PATCH 09/21] insertBetween function added --- js/LinkedList/doubly/list.js | 47 +++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/js/LinkedList/doubly/list.js b/js/LinkedList/doubly/list.js index bdd0030..4576b14 100644 --- a/js/LinkedList/doubly/list.js +++ b/js/LinkedList/doubly/list.js @@ -11,6 +11,7 @@ class LinkedList { this.head = null; this.tail = null; this.length = 0; + this.nodeMap = new Map(); } getHead() { @@ -31,6 +32,8 @@ class LinkedList { newNode.next = this.head; this.head = newNode; } + this.nodeMap.set(data.id, newNode) + this.length++; } append(data) { @@ -43,6 +46,41 @@ class LinkedList { newNode.prev = this.tail; this.tail = newNode; } + this.nodeMap.set(data.id, newNode); + this.length++; + } + + insertBetween(data, before, after) { + const newNode = new Node(data); + let curr = this.head; + + // finding the node with the `after` data + while (curr && curr.data.id !== after.id) { + curr = curr.next; + } + + if (curr) { + // finding the node with the `before` data + let nextNode = curr.next; + while (nextNode && nextNode.data.id !== before.id) { + curr = nextNode; + nextNode = nextNode.next; + } + + // if the `before` node is found, insert the new node + if (nextNode && nextNode.data.id === before.id) { + newNode.next = nextNode; + newNode.prev = curr; + curr.next = newNode; + nextNode.prev = newNode; + this.nodeMap.set(data.id, newNode); + this.length++; + } else { + throw Error("Before node not found"); + } + } else { + throw Error("After node not found"); + } } print() { @@ -56,13 +94,4 @@ class LinkedList { } } -function main() { - var dll = new LinkedList(); - dll.prepend(1); - dll.prepend(2); - dll.append(3); - - dll.print(); -} - main() \ No newline at end of file From 94fda91e8a4e085edc78dae4a99ae7c9af9de7fd Mon Sep 17 00:00:00 2001 From: harris-ahmad <24100315@lums.edu.pk> Date: Mon, 5 Aug 2024 01:12:03 +0500 Subject: [PATCH 10/21] deleteHead added --- js/LinkedList/doubly/list.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/js/LinkedList/doubly/list.js b/js/LinkedList/doubly/list.js index 4576b14..6e34ef0 100644 --- a/js/LinkedList/doubly/list.js +++ b/js/LinkedList/doubly/list.js @@ -83,6 +83,21 @@ class LinkedList { } } + deleteHead() { + if (!this.head) { + throw Error("List is empty!"); + } else { + this.nodeMap.delete(this.head.data.id); + this.head = this.head.next; + if (this.head) { + this.head.prev = null; + } else { + this.tail = null; + } + this.length--; + } + } + print() { let curr = this.head; let result = [] From 3fedf571a7442a19a67fe59c4079af2a1046f27b Mon Sep 17 00:00:00 2001 From: harris-ahmad <24100315@lums.edu.pk> Date: Thu, 15 Aug 2024 05:22:11 +0500 Subject: [PATCH 11/21] doubly linked list in js done --- js/LinkedList/doubly/list.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/LinkedList/doubly/list.js b/js/LinkedList/doubly/list.js index 6e34ef0..48ec394 100644 --- a/js/LinkedList/doubly/list.js +++ b/js/LinkedList/doubly/list.js @@ -15,10 +15,12 @@ class LinkedList { } getHead() { + if (!this.head) throw Error("List is empty!"); return this.head; } getTail() { + if (!this.head) throw Error("List is empty!"); return this.tail; } @@ -107,6 +109,4 @@ class LinkedList { } console.log(result.join(" <-> ")); } -} - -main() \ No newline at end of file +} \ No newline at end of file From dd448427d07ab6359c70bc7d79c5cd11734f6fdf Mon Sep 17 00:00:00 2001 From: harris-ahmad <24100315@lums.edu.pk> Date: Thu, 15 Aug 2024 05:22:57 +0500 Subject: [PATCH 12/21] filename changed --- js/LinkedList/singly/list.js | 253 +++++++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 js/LinkedList/singly/list.js diff --git a/js/LinkedList/singly/list.js b/js/LinkedList/singly/list.js new file mode 100644 index 0000000..0a71e72 --- /dev/null +++ b/js/LinkedList/singly/list.js @@ -0,0 +1,253 @@ +/** + * Node class representing a single node in a doubly linked list. + */ +class Node { + /** + * Create a Node. + * @param {*} data - The data to be stored in the node. + */ + constructor(data) { + this.data = data; + this.next = null; + this.prev = null; // Added for doubly linked list + } +} + +/** +* DoublyLinkedList class representing a doubly linked list. +*/ +class DoublyLinkedList { + /** + * Create an empty DoublyLinkedList. + */ + constructor() { + this.head = null; + this.tail = null; + this.length = 0; + this.nodeMap = new Map(); // HashMap for O(1) lookups + } + + /** + * Get the head node of the list. + * @return {Node|null} The head node or null if the list is empty. + */ + getHead() { + return this.head; + } + + /** + * Get the tail node of the list. + * @return {Node|null} The tail node or null if the list is empty. + */ + getTail() { + return this.tail; + } + + /** + * Prepend a node to the beginning of the list. + * @param {*} data - The data to be stored in the new node. + */ + prepend(data) { + const newNode = new Node(data); + if (!this.head) { + this.head = newNode; + this.tail = newNode; + } else { + newNode.next = this.head; + this.head.prev = newNode; + this.head = newNode; + } + this.nodeMap.set(data.id, newNode); + this.length++; + } + + /** + * Append a node to the end of the list. + * @param {*} data - The data to be stored in the new node. + */ + append(data) { + const newNode = new Node(data); + if (!this.head) { + this.head = newNode; + this.tail = newNode; + } else { + this.tail.next = newNode; + newNode.prev = this.tail; + this.tail = newNode; + } + this.nodeMap.set(data.id, newNode); + this.length++; + } + + /** + * Insert a node between two existing nodes in the list. + * @param {*} data - The data to be stored in the new node. + * @param {*} before - The data of the node before which to insert the new node. + * @param {*} after - The data of the node after which to insert the new node. + */ + insertBetween(data, before, after) { + const newNode = new Node(data); + let curr = this.head; + + console.log('Inserting node:', data, 'between nodes:', after, 'and', before); + + // Find the node with the `after` data + while (curr && curr.data.id !== after.id) { + curr = curr.next; + } + + // Ensure we found the `after` node + if (curr) { + console.log('Found node after:', curr.data); + + // Find the node with the `before` data + let nextNode = curr.next; + while (nextNode && nextNode.data.id !== before.id) { + curr = nextNode; + nextNode = nextNode.next; + } + + // Insert the new node if `before` node is found + if (nextNode && nextNode.data.id === before.id) { + console.log('Found node before:', nextNode.data); + newNode.next = nextNode; + newNode.prev = curr; + curr.next = newNode; + nextNode.prev = newNode; + this.nodeMap.set(data.id, newNode); + this.length++; + } else { + console.error('Before node not found'); + } + } else { + console.error('After node not found'); + } + } + + /** + * Delete the head node of the list. + */ + deleteHead() { + if (this.head) { + this.nodeMap.delete(this.head.data.id); + if (this.head.next) { + this.head = this.head.next; + this.head.prev = null; + } else { + this.head = null; + this.tail = null; + } + this.length--; + } + } + + /** + * Delete the tail node of the list. + */ + deleteTail() { + if (!this.head) { + return; + } + if (!this.head.next) { + this.nodeMap.delete(this.head.data.id); + this.head = null; + this.tail = null; + } else { + this.nodeMap.delete(this.tail.data.id); + this.tail = this.tail.prev; + this.tail.next = null; + } + this.length--; + } + + /** + * Delete any node from the list that matches the given target data. + * @param {*} target - The target data to match for deletion. + */ + deleteAny(target) { + if (!this.head) { + return; + } + + if (this.head.data.id === target.id) { + this.deleteHead(); + } else if (this.tail.data.id === target.id) { + this.deleteTail(); + } else { + let curr = this.head; + + while (curr && curr.data.id !== target.id) { + curr = curr.next; + } + + if (curr) { + curr.prev.next = curr.next; + curr.next.prev = curr.prev; + this.nodeMap.delete(curr.data.id); + this.length--; + } + } + } + + /** + * Get the size of the list. + * @return {number} The number of nodes in the list. + */ + size() { + return this.length; + } + + /** + * Reverse the linked list in place. + */ + reverseList() { + let curr = this.head; + let prev = null; + + this.tail = this.head; + + while (curr) { + const next = curr.next; + curr.next = prev; + curr.prev = next; + prev = curr; + curr = next; + } + + this.head = prev; + } + + /** + * Find a node by its id. + * @param {number} id - The id of the node to find. + * @return {Node|null} The node with the given id or null if not found. + */ + find(id) { + return this.nodeMap.get(id) || null; + } + + /** + * Clear the list, removing all nodes. + */ + clear() { + this.head = null; + this.tail = null; + this.length = 0; + this.nodeMap.clear(); + } + + /** + * Print the list data in a readable format. + */ + print() { + let curr = this.head; + const result = []; + while (curr) { + result.push(curr.data.toString()); + curr = curr.next; + } + console.log(result.join(" <-> ")); + } +} + +export default DoublyLinkedList; From aff41c46b1ee690a1e24b198114dbe8cbe8bdbda Mon Sep 17 00:00:00 2001 From: harris-ahmad <24100315@lums.edu.pk> Date: Thu, 15 Aug 2024 05:23:25 +0500 Subject: [PATCH 13/21] list.mjs removed --- js/LinkedList/singly/list.mjs | 255 ---------------------------------- 1 file changed, 255 deletions(-) delete mode 100644 js/LinkedList/singly/list.mjs diff --git a/js/LinkedList/singly/list.mjs b/js/LinkedList/singly/list.mjs deleted file mode 100644 index 7ff2ff8..0000000 --- a/js/LinkedList/singly/list.mjs +++ /dev/null @@ -1,255 +0,0 @@ -/** - * Node class representing a single node in a singly linked list. - */ -class Node { - /** - * Create a Node. - * @param {*} data - The data to be stored in the node. - */ - constructor(data) { - this.data = data; - this.next = null; - } -} - -/** -* LinkedList class representing a singly linked list. -*/ -class LinkedList { - /** - * Create an empty LinkedList. - */ - constructor() { - this.head = null; - this.tail = null; - this.length = 0; - this.nodeMap = new Map(); // HashMap for O(1) lookups - } - - /** - * Get the head node of the list. - * @return {Node|null} The head node or null if the list is empty. - */ - getHead() { - return this.head; - } - - /** - * Get the tail node of the list. - * @return {Node|null} The tail node or null if the list is empty. - */ - getTail() { - return this.tail; - } - - /** - * Prepend a node to the beginning of the list. - * @param {*} data - The data to be stored in the new node. - */ - prepend(data) { - const newNode = new Node(data); - if (!this.head) { - this.head = newNode; - this.tail = newNode; - } else { - newNode.next = this.head; - this.head = newNode; - } - this.nodeMap.set(data.id, newNode); - this.length++; - } - - /** - * Append a node to the end of the list. - * @param {*} data - The data to be stored in the new node. - */ - append(data) { - const newNode = new Node(data); - if (!this.head) { - this.head = newNode; - this.tail = newNode; - } else { - this.tail.next = newNode; - this.tail = newNode; - } - this.nodeMap.set(data.id, newNode); - this.length++; - } - - /** - * Insert a node between two existing nodes in the list. - * @param {*} data - The data to be stored in the new node. - * @param {*} before - The data of the node before which to insert the new node. - * @param {*} after - The data of the node after which to insert the new node. - */ - insertBetween(data, before, after) { - const newNode = new Node(data); - let curr = this.head; - - console.log('Inserting node:', data, 'between nodes:', after, 'and', before); - - // Find the node with the `after` data - while (curr && curr.data.id !== after.id) { - curr = curr.next; - } - - // Ensure we found the `after` node - if (curr) { - console.log('Found node after:', curr.data); - - // Find the node with the `before` data - let nextNode = curr.next; - while (nextNode && nextNode.data.id !== before.id) { - curr = nextNode; - nextNode = nextNode.next; - } - - // Insert the new node if `before` node is found - if (nextNode && nextNode.data.id === before.id) { - console.log('Found node before:', nextNode.data); - newNode.next = nextNode; - curr.next = newNode; - this.nodeMap.set(data.id, newNode); - this.length++; - } else { - console.error('Before node not found'); - } - } else { - console.error('After node not found'); - } - } - - /** - * Delete the head node of the list. - */ - deleteHead() { - if (this.head) { - this.nodeMap.delete(this.head.data.id); - this.head = this.head.next; - if (!this.head) { - this.tail = null; - } - this.length--; - } - } - - /** - * Delete the tail node of the list. - */ - deleteTail() { - if (!this.head) { - return; - } - if (!this.head.next) { - this.nodeMap.delete(this.head.data.id); - this.head = null; - this.tail = null; - } else { - let prevNode = this.head; - while (prevNode.next && prevNode.next.next) { - prevNode = prevNode.next; - } - this.nodeMap.delete(prevNode.next.data.id); - prevNode.next = null; - this.tail = prevNode; - } - this.length--; - } - - /** - * Delete any node from the list that matches the given target data. - * @param {*} target - The target data to match for deletion. - */ - deleteAny(target) { - if (!this.head) { - return; - } - - if (this.head.data.id === target.id) { - this.nodeMap.delete(this.head.data.id); - this.head = this.head.next; - if (!this.head) { - this.tail = null; - } - this.length--; - } else { - let prevNode = this.head; - let curr = this.head.next; - - while (curr && curr.data.id !== target.id) { - prevNode = curr; - curr = curr.next; - } - - if (curr) { - prevNode.next = curr.next; - if (!curr.next) { - this.tail = prevNode; - } - this.nodeMap.delete(curr.data.id); - this.length--; - } - } - } - - /** - * Get the size of the list. - * @return {number} The number of nodes in the list. - */ - size() { - return this.length; - } - - /** - * Reverse the linked list in place. - */ - reverseList() { - let prev = null; - let curr = this.head; - let next = null; - - this.tail = this.head; - - while (curr) { - next = curr.next; - curr.next = prev; - prev = curr; - curr = next; - } - this.head = prev; - } - - /** - * Find a node by its id. - * @param {number} id - The id of the node to find. - * @return {Node|null} The node with the given id or null if not found. - */ - find(id) { - return this.nodeMap.get(id) || null; - } - - /** - * Clear the list, removing all nodes. - */ - clear() { - this.head = null; - this.tail = null; - this.length = 0; - this.nodeMap.clear(); - } - - /** - * Print the list data in a readable format. - */ - print() { - let curr = this.head; - const result = []; - while (curr) { - result.push(curr.data.toString()); - curr = curr.next; - } - console.log(result.join(" -> ")); - } -} - -export default LinkedList; \ No newline at end of file From b8a2116071f3fe282fef2cc72b557f9472405aac Mon Sep 17 00:00:00 2001 From: harris-ahmad <24100315@lums.edu.pk> Date: Thu, 15 Aug 2024 05:41:44 +0500 Subject: [PATCH 14/21] base code set --- c/LinkedList/doubly/list.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 c/LinkedList/doubly/list.c diff --git a/c/LinkedList/doubly/list.c b/c/LinkedList/doubly/list.c new file mode 100644 index 0000000..3990516 --- /dev/null +++ b/c/LinkedList/doubly/list.c @@ -0,0 +1,32 @@ +#include +#include + +// Node structure +typedef struct Node { + int data; + struct Node* next; + struct Node* prev; +} Node; + +// Doubly Linked List structure +typedef struct DoublyLinkedList { + Node* head; + Node* tail; +} DoublyLinkedList; + +// Function to create a new node +Node* createNode(int data) { + Node* newNode = (Node*)malloc(sizeof(Node)); + newNode->data = data; + newNode->next = NULL; + newNode->prev = NULL; + return newNode; +} + +// Function to initialize an empty list +DoublyLinkedList* createList() { + DoublyLinkedList* list = (DoublyLinkedList*)malloc(sizeof(DoublyLinkedList)); + list->head = NULL; + list->tail = NULL; + return list; +} \ No newline at end of file From 66b5d407436c80d24643a67869d46ca92ab09bac Mon Sep 17 00:00:00 2001 From: harris-ahmad <24100315@lums.edu.pk> Date: Thu, 15 Aug 2024 05:46:33 +0500 Subject: [PATCH 15/21] doubly list done --- c/LinkedList/doubly/list.c | 255 +++++++++++++++++++++++++++++++++++-- 1 file changed, 241 insertions(+), 14 deletions(-) diff --git a/c/LinkedList/doubly/list.c b/c/LinkedList/doubly/list.c index 3990516..b531f79 100644 --- a/c/LinkedList/doubly/list.c +++ b/c/LinkedList/doubly/list.c @@ -1,32 +1,259 @@ #include #include -// Node structure typedef struct Node { - int data; - struct Node* next; - struct Node* prev; + void *data; + struct Node *next; + struct Node *prev; + int ref_count; } Node; -// Doubly Linked List structure typedef struct DoublyLinkedList { - Node* head; - Node* tail; + Node *head; + Node *tail; } DoublyLinkedList; -// Function to create a new node -Node* createNode(int data) { - Node* newNode = (Node*)malloc(sizeof(Node)); +void incrementRefCount(Node *node) { + if (node) { + node->ref_count++; + } +} + +void decrementRefCount(Node *node) { + if (node) { + node->ref_count--; + if (node->ref_count <= 0) { + free(node); + } + } +} + +Node *createNode(void *data) { + Node *newNode = (Node *)malloc(sizeof(Node)); newNode->data = data; newNode->next = NULL; newNode->prev = NULL; + newNode->ref_count = 1; return newNode; } -// Function to initialize an empty list -DoublyLinkedList* createList() { - DoublyLinkedList* list = (DoublyLinkedList*)malloc(sizeof(DoublyLinkedList)); +DoublyLinkedList *createDoublyLinkedList() { + DoublyLinkedList *list = (DoublyLinkedList *)malloc(sizeof(DoublyLinkedList)); list->head = NULL; list->tail = NULL; return list; -} \ No newline at end of file +} + +Node *getHead(DoublyLinkedList *list) { + return list->head; +} + +Node *getTail(DoublyLinkedList *list) { + return list->tail; +} + +void prepend(DoublyLinkedList *list, void *data) { + Node *newNode = createNode(data); + if (!list->head) { + list->head = newNode; + list->tail = newNode; + } else { + newNode->next = list->head; + list->head->prev = newNode; + list->head = newNode; + } +} + +void append(DoublyLinkedList *list, void *data) { + Node *newNode = createNode(data); + if (!list->head) { + list->head = newNode; + list->tail = newNode; + } else { + newNode->prev = list->tail; + list->tail->next = newNode; + list->tail = newNode; + } +} + +void insertBetween(DoublyLinkedList *list, void *data, void *after) { + Node *newNode = createNode(data); + Node *curr = list->head; + + while (curr && curr->data != after) { + curr = curr->next; + } + + if (curr) { + newNode->next = curr->next; + newNode->prev = curr; + if (curr->next) { + curr->next->prev = newNode; + } else { + list->tail = newNode; + } + curr->next = newNode; + } +} + +void deleteHead(DoublyLinkedList *list) { + if (list->head) { + Node *temp = list->head; + list->head = list->head->next; + if (list->head) { + list->head->prev = NULL; + } else { + list->tail = NULL; + } + decrementRefCount(temp); + } +} + +void deleteTail(DoublyLinkedList *list) { + if (!list->tail) { + return; + } + if (list->tail == list->head) { + decrementRefCount(list->tail); + list->head = NULL; + list->tail = NULL; + } else { + Node *temp = list->tail; + list->tail = list->tail->prev; + list->tail->next = NULL; + decrementRefCount(temp); + } +} + +void deleteAny(DoublyLinkedList *list, void *target) { + Node *curr = list->head; + + while (curr && curr->data != target) { + curr = curr->next; + } + + if (curr) { + if (curr->prev) { + curr->prev->next = curr->next; + } else { + list->head = curr->next; + } + + if (curr->next) { + curr->next->prev = curr->prev; + } else { + list->tail = curr->prev; + } + + decrementRefCount(curr); + } +} + +int size(DoublyLinkedList *list) { + int count = 0; + Node *curr = list->head; + while (curr) { + count++; + curr = curr->next; + } + return count; +} + +void reverseList(DoublyLinkedList *list) { + Node *curr = list->head; + Node *temp = NULL; + + while (curr) { + temp = curr->prev; + curr->prev = curr->next; + curr->next = temp; + curr = curr->prev; + } + + if (temp) { + list->head = temp->prev; + } +} + +Node *find(DoublyLinkedList *list, void *data) { + Node *curr = list->head; + while (curr) { + if (curr->data == data) { + return curr; + } + curr = curr->next; + } + return NULL; +} + +void clear(DoublyLinkedList *list) { + Node *curr = list->head; + Node *next; + while (curr) { + next = curr->next; + decrementRefCount(curr); + curr = next; + } + list->head = NULL; + list->tail = NULL; +} + +void printListForward(DoublyLinkedList *list) { + Node *curr = list->head; + while (curr) { + printf("%p ", curr->data); + curr = curr->next; + } + printf("\n"); +} + +void printListBackward(DoublyLinkedList *list) { + Node *curr = list->tail; + while (curr) { + printf("%p ", curr->data); + curr = curr->prev; + } + printf("\n"); +} + +int main() { + DoublyLinkedList *list = createDoublyLinkedList(); + + int a = 1, b = 2, c = 3, d = 4; + append(list, &a); + append(list, &b); + prepend(list, &c); + insertBetween(list, &d, &a); + + printf("List printed forward: "); + printListForward(list); + + printf("List printed backward: "); + printListBackward(list); + + deleteHead(list); + printf("List after deleting head: "); + printListForward(list); + + deleteTail(list); + printf("List after deleting tail: "); + printListForward(list); + + deleteAny(list, &b); + printf("List after deleting element b: "); + printListForward(list); + + printf("List size: %d\n", size(list)); + + reverseList(list); + printf("List after reversing: "); + printListForward(list); + + clear(list); + printf("List after clearing: "); + printListForward(list); + + free(list); + + return 0; +} From 619cc80c744663728321ba4552820cf5411aba6d Mon Sep 17 00:00:00 2001 From: harris-ahmad <24100315@lums.edu.pk> Date: Thu, 15 Aug 2024 05:49:18 +0500 Subject: [PATCH 16/21] added gitignore for c --- c/.gitignore | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 c/.gitignore diff --git a/c/.gitignore b/c/.gitignore new file mode 100644 index 0000000..6d5206b --- /dev/null +++ b/c/.gitignore @@ -0,0 +1,52 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf \ No newline at end of file From 0841db7242d5ccc44e62669ea37be2c57e56688a Mon Sep 17 00:00:00 2001 From: Harris Ahmad <24100315@lums.edu.pk> Date: Sun, 15 Sep 2024 04:01:48 +0500 Subject: [PATCH 17/21] Update README.md removed features --- README.md | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/README.md b/README.md index bbf7f48..bcdb026 100644 --- a/README.md +++ b/README.md @@ -16,21 +16,6 @@ Welcome to the ultimate repository for data structures implemented across multip This repository aims to provide a comprehensive collection of data structures implemented in C++, Go, JavaScript, and Python. Each implementation will include practical applications to demonstrate their usage in real-world scenarios. -## Features - -- **C++ Implementations**: - - ➖ Singly Linked List - - 📄 Code file (`list.h`) - -- **Go Implementations**: - - ➖ Singly Linked List (`LinkedList.go`) - -- **JavaScript Implementations**: - - ➖ Singly Linked List (`list.js`) - -- **Python Implementations**: - - ➖ Singly Linked List (`list.py`) - ## Getting Started To get started with any of the data structures, navigate to the respective directory and follow the instructions provided in the comments or documentation within the code. From 69d21b1ee7c9bc81aa4ce89383c9dd51633605dd Mon Sep 17 00:00:00 2001 From: Harris Ahmad Date: Tue, 17 Sep 2024 05:49:37 +0500 Subject: [PATCH 18/21] module files added --- go/LinkedList/doubly/LinkedList.go | 67 +--------------------------- go/LinkedList/doubly/go.mod | 3 ++ go/LinkedList/go.mod | 5 +++ go/LinkedList/go.sum | 2 + go/LinkedList/main.go | 71 ++++++++++++++++++++++++++++++ go/LinkedList/singly/go.mod | 3 ++ 6 files changed, 85 insertions(+), 66 deletions(-) create mode 100644 go/LinkedList/doubly/go.mod create mode 100644 go/LinkedList/go.mod create mode 100644 go/LinkedList/go.sum create mode 100644 go/LinkedList/main.go create mode 100644 go/LinkedList/singly/go.mod diff --git a/go/LinkedList/doubly/LinkedList.go b/go/LinkedList/doubly/LinkedList.go index 02e60ef..a2b4634 100644 --- a/go/LinkedList/doubly/LinkedList.go +++ b/go/LinkedList/doubly/LinkedList.go @@ -1,4 +1,4 @@ -package main +package doubly import "fmt" @@ -161,68 +161,3 @@ func (dll *DoublyLinkedList) PrintList() { } fmt.Println() } - -func main() { - dll := DoublyLinkedList{} - - // Test appending and prepending - fmt.Println("Testing append and prepend:") - dll.Append(1) - dll.Append(2) - dll.Append(3) - dll.Prepend(0) - dll.PrintList() // Expected Output: 0 1 2 3 - - // Test inserting between nodes - fmt.Println("Testing insert between:") - dll.InsertBetween(1.5, 1) - dll.PrintList() // Expected Output: 0 1 1.5 2 3 - - // Test deleting head - fmt.Println("Testing delete head:") - dll.DeleteHead() - dll.PrintList() // Expected Output: 1 1.5 2 3 - - // Test deleting tail - fmt.Println("Testing delete tail:") - dll.DeleteTail() - dll.PrintList() // Expected Output: 1 1.5 2 - - // Test deleting any node - fmt.Println("Testing delete any:") - dll.DeleteAny(1.5) - dll.PrintList() // Expected Output: 1 2 - - // Test reversing the list - fmt.Println("Testing reverse list:") - dll.Reverse() - dll.PrintList() // Expected Output: 2 1 - - dll.Clear() - dll.Append(1) - - // Test finding a node - fmt.Println("Testing find:") - node := dll.Find(1) - if node != nil { - fmt.Println(node.data) // Expected Output: 1 - } else { - fmt.Println("Node not found") - } - - // Test clearing the list - fmt.Println("Testing clear:") - dll.Clear() - dll.PrintList() // Expected Output: (empty list) - - // Test reading a list - fmt.Println("Testing read list:") - dll.Append(10) - dll.Append(20) - dll.Append(30) - dll.PrintList() // Expected Output: 10 20 30 - - // Test size of the list - fmt.Println("Testing size:") - fmt.Println(dll.Size()) // Expected Output: 3 -} diff --git a/go/LinkedList/doubly/go.mod b/go/LinkedList/doubly/go.mod new file mode 100644 index 0000000..42517af --- /dev/null +++ b/go/LinkedList/doubly/go.mod @@ -0,0 +1,3 @@ +module github.com/harris-ahmad/DataStructuresAndAlgorithms/go/LinkedList/doubly + +go 1.23.1 \ No newline at end of file diff --git a/go/LinkedList/go.mod b/go/LinkedList/go.mod new file mode 100644 index 0000000..a8a3568 --- /dev/null +++ b/go/LinkedList/go.mod @@ -0,0 +1,5 @@ +module github.com/harris-ahmad/DataStructuresAndAlgorithms/go/LinkedList + +go 1.23.1 + +require github.com/harris-ahmad/DataStructuresAndAlgorithms v0.0.0-20240914230148-0841db7242d5 // indirect diff --git a/go/LinkedList/go.sum b/go/LinkedList/go.sum new file mode 100644 index 0000000..a3d6ca2 --- /dev/null +++ b/go/LinkedList/go.sum @@ -0,0 +1,2 @@ +github.com/harris-ahmad/DataStructuresAndAlgorithms v0.0.0-20240914230148-0841db7242d5 h1:DIL7bNRl4DCg1Cs+8ME5svxZm9DULkrut+lLIiooKkY= +github.com/harris-ahmad/DataStructuresAndAlgorithms v0.0.0-20240914230148-0841db7242d5/go.mod h1:mgLf82bWvrqNIr/aWyGfg1cUwp9bK1wRSZRQGcairyg= diff --git a/go/LinkedList/main.go b/go/LinkedList/main.go new file mode 100644 index 0000000..cde4938 --- /dev/null +++ b/go/LinkedList/main.go @@ -0,0 +1,71 @@ +package main + +import ( + "fmt" + DoublyLinkedList "github.com/harris-ahmad/DataStructuresAndAlgorithms/go/LinkedList/doubly" +) + +func main() { + dll := DoublyLinkedList{} + + // Test appending and prepending + fmt.Println("Testing append and prepend:") + dll.Append(1) + dll.Append(2) + dll.Append(3) + dll.Prepend(0) + dll.PrintList() // Expected Output: 0 1 2 3 + + // Test inserting between nodes + fmt.Println("Testing insert between:") + dll.InsertBetween(1.5, 1) + dll.PrintList() // Expected Output: 0 1 1.5 2 3 + + // Test deleting head + fmt.Println("Testing delete head:") + dll.DeleteHead() + dll.PrintList() // Expected Output: 1 1.5 2 3 + + // Test deleting tail + fmt.Println("Testing delete tail:") + dll.DeleteTail() + dll.PrintList() // Expected Output: 1 1.5 2 + + // Test deleting any node + fmt.Println("Testing delete any:") + dll.DeleteAny(1.5) + dll.PrintList() // Expected Output: 1 2 + + // Test reversing the list + fmt.Println("Testing reverse list:") + dll.Reverse() + dll.PrintList() // Expected Output: 2 1 + + dll.Clear() + dll.Append(1) + + // Test finding a node + fmt.Println("Testing find:") + node := dll.Find(1) + if node != nil { + fmt.Println(node.data) // Expected Output: 1 + } else { + fmt.Println("Node not found") + } + + // Test clearing the list + fmt.Println("Testing clear:") + dll.Clear() + dll.PrintList() // Expected Output: (empty list) + + // Test reading a list + fmt.Println("Testing read list:") + dll.Append(10) + dll.Append(20) + dll.Append(30) + dll.PrintList() // Expected Output: 10 20 30 + + // Test size of the list + fmt.Println("Testing size:") + fmt.Println(dll.Size()) // Expected Output: 3 +} diff --git a/go/LinkedList/singly/go.mod b/go/LinkedList/singly/go.mod new file mode 100644 index 0000000..77369cd --- /dev/null +++ b/go/LinkedList/singly/go.mod @@ -0,0 +1,3 @@ +module github.com/harris-ahmad/DataStructuresAndAlgorithms/go/LinkedList/singly + +go 1.23.1 \ No newline at end of file From 58ce4ea9e34b1d959e0ba4812c1823369b6edcd4 Mon Sep 17 00:00:00 2001 From: Harris Ahmad Date: Tue, 17 Sep 2024 05:55:23 +0500 Subject: [PATCH 19/21] removed mod files --- go/LinkedList/doubly/go.mod | 3 --- go/LinkedList/go.mod | 4 +--- go/LinkedList/go.sum | 2 -- go/LinkedList/singly/go.mod | 3 --- 4 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 go/LinkedList/doubly/go.mod delete mode 100644 go/LinkedList/go.sum delete mode 100644 go/LinkedList/singly/go.mod diff --git a/go/LinkedList/doubly/go.mod b/go/LinkedList/doubly/go.mod deleted file mode 100644 index 42517af..0000000 --- a/go/LinkedList/doubly/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/harris-ahmad/DataStructuresAndAlgorithms/go/LinkedList/doubly - -go 1.23.1 \ No newline at end of file diff --git a/go/LinkedList/go.mod b/go/LinkedList/go.mod index a8a3568..246f412 100644 --- a/go/LinkedList/go.mod +++ b/go/LinkedList/go.mod @@ -1,5 +1,3 @@ module github.com/harris-ahmad/DataStructuresAndAlgorithms/go/LinkedList -go 1.23.1 - -require github.com/harris-ahmad/DataStructuresAndAlgorithms v0.0.0-20240914230148-0841db7242d5 // indirect +go 1.23.1 \ No newline at end of file diff --git a/go/LinkedList/go.sum b/go/LinkedList/go.sum deleted file mode 100644 index a3d6ca2..0000000 --- a/go/LinkedList/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/harris-ahmad/DataStructuresAndAlgorithms v0.0.0-20240914230148-0841db7242d5 h1:DIL7bNRl4DCg1Cs+8ME5svxZm9DULkrut+lLIiooKkY= -github.com/harris-ahmad/DataStructuresAndAlgorithms v0.0.0-20240914230148-0841db7242d5/go.mod h1:mgLf82bWvrqNIr/aWyGfg1cUwp9bK1wRSZRQGcairyg= diff --git a/go/LinkedList/singly/go.mod b/go/LinkedList/singly/go.mod deleted file mode 100644 index 77369cd..0000000 --- a/go/LinkedList/singly/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/harris-ahmad/DataStructuresAndAlgorithms/go/LinkedList/singly - -go 1.23.1 \ No newline at end of file From fa66a762648eed0da134e0cdce6e5a80a00f8d1d Mon Sep 17 00:00:00 2001 From: Harris Ahmad <24100315@lums.edu.pk> Date: Sun, 8 Dec 2024 00:48:54 +0500 Subject: [PATCH 20/21] singly list impl improved (#7) * singly list impl improved * typing added and logic facotred * refactoring complete * filerename to make an importable module * src folder added * tests configured * changes to gitignore * cleanup script added * code simplified * code prettified --------- Co-authored-by: Harris Ahmad --- .gitignore | 3 +- python/LinkedList/singly/list.py | 211 ------------------ python/LinkedList/singly/list_test.py | 126 ----------- python/cleanup.sh | 4 + python/src/__init__.py | 0 python/src/linkedlist/__init__.py | 0 .../linkedlist}/doubly/list.py | 0 python/src/linkedlist/singly/__init__.py | 0 python/src/linkedlist/singly/list.py | 206 +++++++++++++++++ python/src/utils/__init__.py | 0 python/src/utils/logger.py | 46 ++++ python/tests/conftest.py | 18 ++ python/tests/linkedlist/__init__.py | 0 python/tests/linkedlist/singly/__init__.py | 0 python/tests/linkedlist/singly/test_singly.py | 41 ++++ 15 files changed, 317 insertions(+), 338 deletions(-) delete mode 100644 python/LinkedList/singly/list.py delete mode 100644 python/LinkedList/singly/list_test.py create mode 100755 python/cleanup.sh create mode 100644 python/src/__init__.py create mode 100644 python/src/linkedlist/__init__.py rename python/{LinkedList => src/linkedlist}/doubly/list.py (100%) create mode 100644 python/src/linkedlist/singly/__init__.py create mode 100644 python/src/linkedlist/singly/list.py create mode 100644 python/src/utils/__init__.py create mode 100644 python/src/utils/logger.py create mode 100644 python/tests/conftest.py create mode 100644 python/tests/linkedlist/__init__.py create mode 100644 python/tests/linkedlist/singly/__init__.py create mode 100644 python/tests/linkedlist/singly/test_singly.py diff --git a/.gitignore b/.gitignore index 600d2d3..0ad56a9 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.vscode \ No newline at end of file +.vscode +.venv/ diff --git a/python/LinkedList/singly/list.py b/python/LinkedList/singly/list.py deleted file mode 100644 index f5c20a7..0000000 --- a/python/LinkedList/singly/list.py +++ /dev/null @@ -1,211 +0,0 @@ -class Node: - """ - Node class representing a single node in a singly linked list. - """ - - def __init__(self, data): - """ - Create a Node. - - :param data: The data to be stored in the node. - """ - self.data = data - self.next = None - - -class LinkedList: - """ - LinkedList class representing a singly linked list. - """ - - def __init__(self): - """ - Create an empty LinkedList. - """ - self.head = None - self.tail = None - self.length = 0 - self.node_map = {} # Dictionary for O(1) lookups - - def get_head(self): - """ - Get the head node of the list. - - :return: The head node or None if the list is empty. - """ - return self.head - - def get_tail(self): - """ - Get the tail node of the list. - - :return: The tail node or None if the list is empty. - """ - return self.tail - - def prepend(self, data): - """ - Prepend a node to the beginning of the list. - - :param data: The data to be stored in the new node. - """ - new_node = Node(data) - if not self.head: - self.head = new_node - self.tail = new_node - else: - new_node.next = self.head - self.head = new_node - self.node_map[data.id] = new_node - self.length += 1 - - def append(self, data): - """ - Append a node to the end of the list. - - :param data: The data to be stored in the new node. - """ - new_node = Node(data) - if not self.head: - self.head = new_node - self.tail = new_node - else: - self.tail.next = new_node - self.tail = new_node - self.node_map[data.id] = new_node - self.length += 1 - - def insert_between(self, data, before, after): - """ - Insert a node between two existing nodes in the list. - - :param data: The data to be stored in the new node. - :param before: The data of the node before which to - insert the new node. - :param after: The data of the node after which to insert the new node. - """ - new_node = Node(data) - curr = self.head - - while curr and curr.data != after: - curr = curr.next - - if curr and curr.next and curr.next.data == before: - new_node.next = curr.next - curr.next = new_node - self.node_map[data.id] = new_node - self.length += 1 - - def delete_head(self): - """ - Delete the head node of the list. - """ - if self.head: - self.node_map.pop(self.head.data.id, None) - self.head = self.head.next - if not self.head: - self.tail = None - self.length -= 1 - - def delete_tail(self): - """ - Delete the tail node of the list. - """ - if not self.head: - return - if not self.head.next: - self.node_map.pop(self.head.data.id, None) - self.head = None - self.tail = None - else: - prev_node = self.head - while prev_node.next and prev_node.next.next: - prev_node = prev_node.next - self.node_map.pop(prev_node.next.data.id, None) - prev_node.next = None - self.tail = prev_node - self.length -= 1 - - def delete_any(self, target): - """ - Delete any node from the list that matches the given target data. - - :param target: The target data to match for deletion. - """ - if not self.head: - return - - if self.head.data.id == target.id: - self.node_map.pop(self.head.data.id, None) - self.head = self.head.next - if not self.head: - self.tail = None - self.length -= 1 - else: - prev_node = self.head - curr = self.head.next - - while curr and curr.data.id != target.id: - prev_node = curr - curr = curr.next - - if curr: - prev_node.next = curr.next - if not curr.next: - self.tail = prev_node - self.node_map.pop(curr.data.id, None) - self.length -= 1 - - def size(self): - """ - Get the size of the list. - - :return: The number of nodes in the list. - """ - return self.length - - def reverse_list(self): - """ - Reverse the linked list in place. - """ - prev = None - curr = self.head - next_node = None - - self.tail = self.head - - while curr: - next_node = curr.next - curr.next = prev - prev = curr - curr = next_node - self.head = prev - - def find(self, id): - """ - Find a node in the list by its id. - - :param id: The id of the node to find. - :return: The node with the given id or None if not found. - """ - return self.node_map.get(id, None) - - def clear(self): - """ - Clear the list. - """ - self.head = None - self.tail = None - self.length = 0 - self.node_map = {} - - def print_list(self): - """ - Print the list data in a readable format. - """ - curr = self.head - result = [] - while curr: - result.append(str(curr.data)) - curr = curr.next - print(" -> ".join(result)) diff --git a/python/LinkedList/singly/list_test.py b/python/LinkedList/singly/list_test.py deleted file mode 100644 index be6821f..0000000 --- a/python/LinkedList/singly/list_test.py +++ /dev/null @@ -1,126 +0,0 @@ -import unittest -from list import LinkedList - - -class TestLinkedList(unittest.TestCase): - - class TestData: - def __init__(self, id, value): - self.id = id - self.value = value - - def __str__(self): - return f"({self.id}: {self.value})" - - def setUp(self): - self.linked_list = LinkedList() - - def test_prepend(self): - data1 = self.TestData(1, "data1") - data2 = self.TestData(2, "data2") - self.linked_list.prepend(data1) - self.linked_list.prepend(data2) - self.assertEqual(self.linked_list.get_head().data, data2) - self.assertEqual(self.linked_list.get_tail().data, data1) - self.assertEqual(self.linked_list.size(), 2) - - def test_append(self): - data1 = self.TestData(1, "data1") - data2 = self.TestData(2, "data2") - self.linked_list.append(data1) - self.linked_list.append(data2) - self.assertEqual(self.linked_list.get_head().data, data1) - self.assertEqual(self.linked_list.get_tail().data, data2) - self.assertEqual(self.linked_list.size(), 2) - - def test_insert_between(self): - data1 = self.TestData(1, "data1") - data2 = self.TestData(2, "data2") - data3 = self.TestData(3, "data3") - self.linked_list.append(data1) - self.linked_list.append(data3) - self.linked_list.insert_between(data2, before=data3, after=data1) - self.assertEqual(self.linked_list.size(), 3) - self.assertEqual(self.linked_list.get_head().next.data, data2) - self.assertEqual(self.linked_list.get_head().next.next.data, data3) - - def test_delete_head(self): - data1 = self.TestData(1, "data1") - data2 = self.TestData(2, "data2") - self.linked_list.append(data1) - self.linked_list.append(data2) - self.linked_list.delete_head() - self.assertEqual(self.linked_list.get_head().data, data2) - self.assertEqual(self.linked_list.size(), 1) - self.linked_list.delete_head() - self.assertIsNone(self.linked_list.get_head()) - self.assertIsNone(self.linked_list.get_tail()) - self.assertEqual(self.linked_list.size(), 0) - - def test_delete_tail(self): - data1 = self.TestData(1, "data1") - data2 = self.TestData(2, "data2") - self.linked_list.append(data1) - self.linked_list.append(data2) - self.linked_list.delete_tail() - self.assertEqual(self.linked_list.get_tail().data, data1) - self.assertEqual(self.linked_list.size(), 1) - self.linked_list.delete_tail() - self.assertIsNone(self.linked_list.get_tail()) - self.assertIsNone(self.linked_list.get_head()) - self.assertEqual(self.linked_list.size(), 0) - - def test_delete_any(self): - data1 = self.TestData(1, "data1") - data2 = self.TestData(2, "data2") - data3 = self.TestData(3, "data3") - self.linked_list.append(data1) - self.linked_list.append(data2) - self.linked_list.append(data3) - self.linked_list.delete_any(data2) - self.assertEqual(self.linked_list.size(), 2) - self.assertEqual(self.linked_list.get_head().next.data, data3) - self.linked_list.delete_any(data1) - self.assertEqual(self.linked_list.size(), 1) - self.assertEqual(self.linked_list.get_head().data, data3) - self.linked_list.delete_any(data3) - self.assertEqual(self.linked_list.size(), 0) - self.assertIsNone(self.linked_list.get_head()) - self.assertIsNone(self.linked_list.get_tail()) - - def test_reverse_list(self): - data1 = self.TestData(1, "data1") - data2 = self.TestData(2, "data2") - data3 = self.TestData(3, "data3") - self.linked_list.append(data1) - self.linked_list.append(data2) - self.linked_list.append(data3) - self.linked_list.reverse_list() - self.assertEqual(self.linked_list.get_head().data, data3) - self.assertEqual(self.linked_list.get_head().next.data, data2) - self.assertEqual(self.linked_list.get_head().next.next.data, data1) - self.assertEqual(self.linked_list.get_tail().data, data1) - - def test_find(self): - data1 = self.TestData(1, "data1") - data2 = self.TestData(2, "data2") - self.linked_list.append(data1) - self.linked_list.append(data2) - self.assertEqual(self.linked_list.find(1), self.linked_list.get_head()) - self.assertEqual(self.linked_list.find(2), self.linked_list.get_tail()) - self.assertIsNone(self.linked_list.find(3)) - - def test_clear(self): - data1 = self.TestData(1, "data1") - data2 = self.TestData(2, "data2") - self.linked_list.append(data1) - self.linked_list.append(data2) - self.linked_list.clear() - self.assertIsNone(self.linked_list.get_head()) - self.assertIsNone(self.linked_list.get_tail()) - self.assertEqual(self.linked_list.size(), 0) - self.assertEqual(self.linked_list.node_map, {}) - - -if __name__ == "__main__": - unittest.main() diff --git a/python/cleanup.sh b/python/cleanup.sh new file mode 100755 index 0000000..9399f1a --- /dev/null +++ b/python/cleanup.sh @@ -0,0 +1,4 @@ +# !/bin/bash + +find . -type d -name "__pycache__" -exec rm -r {} + +find . -type d -name ".pytest_cache" -exec rm -r {} + \ No newline at end of file diff --git a/python/src/__init__.py b/python/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/src/linkedlist/__init__.py b/python/src/linkedlist/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/LinkedList/doubly/list.py b/python/src/linkedlist/doubly/list.py similarity index 100% rename from python/LinkedList/doubly/list.py rename to python/src/linkedlist/doubly/list.py diff --git a/python/src/linkedlist/singly/__init__.py b/python/src/linkedlist/singly/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/src/linkedlist/singly/list.py b/python/src/linkedlist/singly/list.py new file mode 100644 index 0000000..59accef --- /dev/null +++ b/python/src/linkedlist/singly/list.py @@ -0,0 +1,206 @@ +import os +from typing import Dict, Optional, Any + +from utils.logger import Logger + +class Node: + def __init__(self, data: Any): + self.data = data + self.next: Optional["Node"] = None + self._id = os.urandom(16).hex() + + def __repr__(self) -> str: + return f"Node({self._id}: {self.data})" + +class LinkedList: + def __init__(self): + self.head: Optional[Node] = None + self.tail: Optional[Node] = None + self.length: int = 0 + # dictionary to store nodes by their IDs for faster lookup and deletion + self.node_map: Dict[str, Node] = {} + + def get_head(self) -> Optional[Node]: + """Get the head node of the list.""" + return self.head + + def get_tail(self) -> Optional[Node]: + """Get the tail node of the list.""" + return self.tail + + def prepend(self, data: Any) -> None: + """Prepend a node to the start of the list.""" + + new_node = Node(data) + new_node.next = self.head + self.head = new_node + + if not self.tail: + self.tail = new_node + + self.node_map[new_node._id] = new_node.data + self.length += 1 + Logger.info(f"Prepend node: {data}") + + def append(self, data): + """Append a node to the end of the list.""" + + new_node = Node(data) + if not self.head: + self.head = new_node + self.tail = new_node + else: + assert self.tail is not None, "Tail node is not set" + + self.tail.next = new_node + self.tail = new_node + + self.node_map[new_node._id] = new_node.data + self.length += 1 + Logger.info(f"Append node: {data}") + + def insert_between(self, data, before, after): + """ + Insert a node between two existing nodes in the list. + + :param data: The data to be stored in the new node. + :param before: The data of the node before which to + insert the new node. + :param after: The data of the node after which to insert the new node. + """ + if not self.head: + raise Exception("List is empty, nothing to insert") + + new_node = Node(data) + curr = self.head + + while curr and curr.data != after: + curr = curr.next + + if curr and curr.next and curr.next.data == before: + new_node.next = curr.next + curr.next = new_node + self.node_map[new_node._id] = new_node.data + self.length += 1 + + def delete_head(self): + """Delete the head node of the list.""" + + if not self.head: + raise Exception("List is empty, nothing to delete") + self.node_map.pop(self.head._id, None) + self.head = self.head.next + if not self.head: + self.tail = None + self.length -= 1 + + def delete_tail(self): + """ + Delete the tail node of the list. + """ + if not self.head: + raise Exception("List is empty, nothing to delete") + + if not self.head.next or self.head == self.tail: + self.node_map.pop(self.head._id, None) + self.head = self.tail = None + else: + prev_node = self.head + while prev_node.next != self.tail: + prev_node = prev_node.next + self.node_map.pop(self.tail._id, None) + self.tail = prev_node + self.tail.next = None + + self.length -= 1 + + def delete_any(self, target: Node): + """Delete any node from the list that matches the given target data.""" + if not isinstance(target, Node): + raise ValueError("Target must be a Node instance") + + if target._id not in self.node_map: + raise Exception(f"Node with ID {target._id} not found in the list") + + if self.head._id == target._id: + self.delete_head() + return + else: + prev_node: Node = self.head + curr: Node = self.head.next + + while curr and curr._id != target._id: + prev_node = curr + curr = curr.next + + if curr: + prev_node.next = curr.next + if not curr.next: + self.tail = prev_node + self.node_map.pop(curr._id, None) + self.length -= 1 + else: + raise Exception(f"Node with ID {target._id} not found in the list") + + def size(self): + """Get the number of nodes in the list.""" + + return self.length + + def reverse_list(self): + """ + Reverse the linked list in place. + """ + + prev = None + curr = self.head + next_node = None + + self.tail = self.head + + while curr: + next_node = curr.next + curr.next = prev + prev = curr + curr = next_node + + self.head = prev + + def find(self, node: Node) -> Optional[Node]: + """ + Find a node in the list by its id. + + :param id: The id of the node to find. + :return: The node with the given id or None if not found. + """ + return self.node_map.get(node._id, None) + + def clear(self): + """ + Clear the list. + """ + self.head = None + self.tail = None + self.length = 0 + self.node_map.clear() + + def __len__(self) -> int: + return self.length + + def __iter__(self): + current = self.head + while current: + yield current + current = current.next + + def __repr__(self) -> str: + nodes = [str(node) for node in self] + return " -> ".join(nodes) + + def print_list(self): + """ + Print the list data in a readable format. Since we have a + custom __iter__ and __repr__ methods, this method is not necessary. Simply + use a print statement to print the list data. + """ + print(self) \ No newline at end of file diff --git a/python/src/utils/__init__.py b/python/src/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/src/utils/logger.py b/python/src/utils/logger.py new file mode 100644 index 0000000..1d06171 --- /dev/null +++ b/python/src/utils/logger.py @@ -0,0 +1,46 @@ +import sys +import time +from datetime import datetime +from colorama import init, Fore, Style + +init(autoreset=True) + +class Logger: + LEVELS = { + "INFO": Fore.CYAN, + "DEBUG": Fore.BLUE, + "WARNING": Fore.YELLOW, + "ERROR": Fore.RED, + "SUCCESS": Fore.GREEN, + } + + @staticmethod + def log(level: str, message: str): + if level not in Logger.LEVELS: + raise ValueError(f"Invalid log level: {level}") + + timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + formatted_mssg = ( + f"{Style.BRIGHT}[{timestamp}] {Logger.LEVELS[level]}[{level}] {Style.RESET_ALL}{message}" + ) + print(formatted_mssg, file=sys.stdout) + + @staticmethod + def info(message: str): + Logger.log("INFO", message) + + @staticmethod + def debug(message: str): + Logger.log("DEBUG", message) + + @staticmethod + def warning(message: str): + Logger.log("WARNING", message) + + @staticmethod + def error(message: str): + Logger.log("ERROR", message) + + @staticmethod + def success(message: str): + Logger.log("SUCCESS", message) \ No newline at end of file diff --git a/python/tests/conftest.py b/python/tests/conftest.py new file mode 100644 index 0000000..c149a93 --- /dev/null +++ b/python/tests/conftest.py @@ -0,0 +1,18 @@ +import os +import sys +import subprocess +from src.utils.logger import Logger + +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../src"))) + +def pytest_sessionfinish(session, exitstatus): + cleanup_script = os.path.abspath(os.path.join(os.path.dirname(__file__), "../cleanup.sh")) + if os.path.exists(cleanup_script): + Logger.log("INFO", f"Running cleanup script: {cleanup_script}") + try: + subprocess.run(["bash", cleanup_script], check=True) + Logger.log("INFO", "Cleanup script completed successfully") + except subprocess.CalledProcessError as e: + Logger.error(f"Error running cleanup script: {e}") + else: + Logger.error(f"Cleanup script not found: {cleanup_script}") \ No newline at end of file diff --git a/python/tests/linkedlist/__init__.py b/python/tests/linkedlist/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/tests/linkedlist/singly/__init__.py b/python/tests/linkedlist/singly/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/tests/linkedlist/singly/test_singly.py b/python/tests/linkedlist/singly/test_singly.py new file mode 100644 index 0000000..2294a79 --- /dev/null +++ b/python/tests/linkedlist/singly/test_singly.py @@ -0,0 +1,41 @@ +from src.linkedlist.singly.list import LinkedList + +import pytest + +NUM_ELEMENTS = 100_000 + + +@pytest.fixture +def linked_list_append_fixture() -> LinkedList: + ll = LinkedList() + + for i in range(NUM_ELEMENTS): + ll.append(f"node({i})") + + return ll + + +@pytest.fixture +def linked_list_prepend_fixture() -> LinkedList: + ll = LinkedList() + + for i in range(NUM_ELEMENTS): + ll.prepend(f"node({i})") + + return ll + + +def test_append(linked_list_append_fixture): + ll = linked_list_append_fixture + + assert len(ll) == NUM_ELEMENTS + assert ll.get_tail().data == f"node({NUM_ELEMENTS-1})" + assert ll.get_head().data == "node(0)" + + +def test_prepend(linked_list_prepend_fixture): + ll = linked_list_prepend_fixture + + assert len(ll) == NUM_ELEMENTS + assert ll.get_tail().data == f"node({NUM_ELEMENTS-1})" + assert ll.get_head().data == f"node({NUM_ELEMENTS-99999})" \ No newline at end of file From 52400872fb43eae7f22669a41eb23b2c2acc8c9f Mon Sep 17 00:00:00 2001 From: Harris Ahmad Date: Sun, 8 Dec 2024 00:54:53 +0500 Subject: [PATCH 21/21] tests fixed --- python/tests/linkedlist/singly/test_singly.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/tests/linkedlist/singly/test_singly.py b/python/tests/linkedlist/singly/test_singly.py index 2294a79..4cfd784 100644 --- a/python/tests/linkedlist/singly/test_singly.py +++ b/python/tests/linkedlist/singly/test_singly.py @@ -37,5 +37,5 @@ def test_prepend(linked_list_prepend_fixture): ll = linked_list_prepend_fixture assert len(ll) == NUM_ELEMENTS - assert ll.get_tail().data == f"node({NUM_ELEMENTS-1})" - assert ll.get_head().data == f"node({NUM_ELEMENTS-99999})" \ No newline at end of file + assert ll.get_tail().data == f"node({0})" + assert ll.get_head().data == f"node({NUM_ELEMENTS-1})" \ No newline at end of file