Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions javascript/code-challenges/graphs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Graphs
<!-- Short summary or background information -->

## Challenge
Implement your own Graph. The graph should be represented as an adjacency list.
The Graph class should have the following methods: `addVertex`, `addEdge`, `getVertices`,
`getNeighbors`, `getSize`

## Approach & Efficiency
| Method | Time Complexity |
| ---- | ---- |
| `addVertex` | O(1) |
| `addEdge` | O(1) |
| `getVertices` | O(n) |
| `getNeighbors` | O(n) |
| `getSize` | O(n)|

## Methods

`addVertex`

- Adds a new vertex to the graph and returns the added vertex.

`addEdge`

- Adds an edge between two vertices and returns nothing.

`getVertices`

- Returns all the vertices in the graph.

`getNeighbors`

- Returns all the vertices connected to a give vertex.

`getSize`

- Returns the total number of vertices in the graph

### Run Solution

```sh
# Install dependencies
npm install

# run jest tests for undirected-graph.js
npm test undirected-graph.test.js
```
### Sources

[Spread Syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax)

[JavaScript Algorithms and Data Structures Masterclass - Colt Steele](https://www.udemy.com/course/js-algorithms-and-data-structures-masterclass/)

46 changes: 46 additions & 0 deletions javascript/code-challenges/graphs/undirected-graph.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
class UndirectedGraph {
constructor(){
this.adjacencyList = {}
}
addVertex(vertex) {
if(!this.adjacencyList[vertex]) {
this.adjacencyList[vertex] = []
return vertex
}
}
removeVertex(vertex) {
while(this.adjacencyList[vertex].length){
const adjacentVertex = this.adjacencyList[vertex].pop()
this.removeEdge(vertex, adjacentVertex)
}

delete this.adjacencyList[vertex]
}
addEdge(vertex1, vertex2) {
// Push values
this.adjacencyList[vertex1].push(vertex2)
this.adjacencyList[vertex2].push(vertex1)
// Remove duplicates
this.adjacencyList[vertex1] = [...new Set(this.adjacencyList[vertex1])]
this.adjacencyList[vertex2] = [...new Set(this.adjacencyList[vertex2])]
}
removeEdge(vertex1, vertex2) {
this.adjacencyList[vertex1] = this.adjacencyList[vertex1].filter(
edge => edge !== vertex2
)
this.adjacencyList[vertex2] = this.adjacencyList[vertex2].filter(
edge => edge !== vertex1
)
}
getVertices() {
return Object.keys(this.adjacencyList)
}
getNeighbors(vertex) {
return this.adjacencyList[vertex]
}
getSize() {
return Object.keys(this.adjacencyList).length
}
}

module.exports = UndirectedGraph
61 changes: 61 additions & 0 deletions javascript/code-challenges/graphs/undirected-graph.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const { describe, it } = require('eslint/lib/rule-tester/rule-tester')
const UndirectedGraph = require('./undirected-graph')

let testGraph


describe('Given Graphs', () => {
describe('When happy path', () => {
beforeEach(() => {
testGraph = new UndirectedGraph()

// Add vertices before adding edge
testGraph.addVertex('Seattle')
testGraph.addVertex('Tokyo')
})

it('Vertex can be successfully added to the graph', () => {
testGraph.addVertex('NYC')
expect(testGraph.adjacencyList['NYC']).toEqual([])
expect(testGraph.adjacencyList['Seattle']).toEqual([])
expect(testGraph.adjacencyList['Tokyo']).toEqual([])
})

it('An edge can be successfully added to the graph', () => {
testGraph.addEdge('Seattle', 'Tokyo')
expect(testGraph.adjacencyList['Seattle']).toEqual(['Tokyo'])
expect(testGraph.adjacencyList['Tokyo']).toEqual(['Seattle'])
})

it('A collection of all vertices can be properly retrieved from the graph', () => {
expect(testGraph.getVertices() === ['Seattle', 'Tokyo'])
})

it('All appropriate neighbors can be retrieved from the graph', () => {
testGraph.addEdge('Seattle', 'Tokyo')
expect(testGraph.getNeighbors('Seattle')).toEqual(['Tokyo'])
expect(testGraph.getNeighbors('Tokyo')).toEqual(['Seattle'])
})

// TODO handle weighted edges
it.todo('Neighbors are returned with the weight between vertices included')

it('The proper size is returned, representing the number of vertices in the graph', () => {
expect(testGraph.getSize()).toEqual(2)
})
})

describe('When edge case', () => {
it('A graph with only one vertex and edge can be properly returned', () => {
// How would a graph with one vertex have an edge?
let testGraph = new UndirectedGraph()
testGraph.addVertex('Seattle')
expect(testGraph.getVertices()).toEqual(['Seattle'])
})

it('An empty graph properly returns size', () => {
let testGraph = new UndirectedGraph()
expect(testGraph.getSize()).toEqual(0)
})
})
})