-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TA 2016/17 JS OOP Homework
- Loading branch information
Showing
4 changed files
with
361 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"curly":true, | ||
"undef":true, | ||
"unused":true, | ||
"esversion":6, | ||
"strict":true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"name": "task", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "task-1.js", | ||
"directories": { | ||
"test": "tests" | ||
}, | ||
"scripts": { | ||
"test": "mocha --compilers js:babel-core -R spec tests" | ||
}, | ||
"author": "", | ||
"license": "ISC", | ||
"dependencies": { | ||
"chai": "^3.5.0", | ||
"mocha": "^3.0.2" | ||
}, | ||
"devDependencies": { | ||
"babel-core": "^6.14.0", | ||
"babel-preset-es2015": "^6.14.0", | ||
"babel-register": "^6.14.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
'use strict'; | ||
class listNode { | ||
constructor(value) { | ||
this._value = value; | ||
this._next = {}; | ||
} | ||
} | ||
|
||
class LinkedList { | ||
constructor() { | ||
this._head = null; | ||
this._length = 0; | ||
} | ||
|
||
get first() { | ||
return this._head._value; | ||
} | ||
|
||
get last() { | ||
let current = this._head, | ||
index = 0; | ||
while (++index < this._length) { | ||
current = current.next; | ||
} | ||
if (current.next === undefined) { | ||
return current._value; | ||
} else { | ||
return null; | ||
} | ||
} | ||
|
||
get length() { | ||
return this._length; | ||
} | ||
|
||
* | ||
[Symbol.iterator]() { | ||
let current = this._head, | ||
index = 0, | ||
output = []; | ||
while (++index <= this._length) { | ||
output.push(current._value); | ||
current = current.next; | ||
} | ||
yield* output; | ||
} | ||
|
||
append(...values) { | ||
values.map((value) => { | ||
let node = new listNode(value), | ||
current; | ||
|
||
if (this._head === null) { | ||
this._head = node; | ||
} else { | ||
current = this._head; | ||
while (current.next) { | ||
current = current.next; | ||
} | ||
current.next = node; | ||
} | ||
this._length++; | ||
}); | ||
return this; | ||
} | ||
|
||
at(...index) { | ||
let current = this._head, | ||
currentIndex = 0, | ||
previous; | ||
if (index[0] === 0) { | ||
previous = this._head; | ||
} | ||
while (currentIndex++ <= index[0]) { | ||
previous = current; | ||
current = current.next; | ||
} | ||
if (index.length > 1) { | ||
previous._value = index[1]; | ||
} | ||
|
||
return previous._value; | ||
} | ||
|
||
insert(index, ...values) { | ||
let current = this._head, | ||
currentIndex = 0, | ||
detachedHead; | ||
if (index === 0) { | ||
this.prepend(...values); | ||
} else { | ||
while (++currentIndex < index) { | ||
current = current.next; | ||
} | ||
|
||
detachedHead = current.next; | ||
current.next = null; | ||
this.append(...values); | ||
current = this._head; | ||
|
||
while (current.next) { | ||
current = current.next; | ||
} | ||
if (current.next === undefined) { | ||
|
||
current.next = detachedHead; | ||
} | ||
} | ||
|
||
return this; | ||
} | ||
|
||
prepend(...values) { | ||
let previousHead = this._head, | ||
previousLength = this._length; | ||
this._head = null; | ||
this._length = 0; | ||
this.append(...values); | ||
let current = this._head, | ||
index = 0; | ||
while (++index < this._length) { | ||
current = current.next; | ||
} | ||
if (current.next === undefined) { | ||
current.next = previousHead; | ||
} else { | ||
current = null; | ||
} | ||
this._length += previousLength; | ||
return this; | ||
} | ||
|
||
removeAt(index) { | ||
if (index > -1 && index < this._length) { | ||
let current = this._head, | ||
currentIndex = 0, | ||
previous; | ||
if (index === 0) { | ||
this._head = current.next; | ||
this._length--; | ||
return current._value; | ||
} else { | ||
while (currentIndex < index) { | ||
previous = current; | ||
current = current.next; | ||
currentIndex++; | ||
} | ||
|
||
previous.next = current.next; | ||
this._length--; | ||
return current._value; | ||
} | ||
} else { | ||
return null; | ||
} | ||
} | ||
|
||
toArray() { | ||
let array = []; | ||
for (let item of this) { | ||
array.push(item); | ||
} | ||
return array; | ||
} | ||
|
||
toString() { | ||
return this.toArray().join(' -> '); | ||
} | ||
} | ||
|
||
module.exports = LinkedList; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
'use strict'; | ||
|
||
const chai = require('chai'), | ||
expect = chai.expect, | ||
LinkedList = require('../task/task-1'); | ||
|
||
describe('Linked list: ', () => { | ||
it('should have append and toString correctly', () => { | ||
|
||
const list = new LinkedList(), | ||
values = [1, 2, false, 3, 4]; | ||
|
||
list.append(...values); | ||
|
||
expect(list.first).to.equal(values[0]); | ||
expect(list.last).to.equal(values[values.length - 1]); | ||
expect(list.length).to.equal(values.length); | ||
expect(list.toString()).to.equal(values.join(' -> ')); | ||
}); | ||
|
||
it('append should implement chaining and toString should work correctly', () => { | ||
const values = [1, 2, 3, 4, 5, 6], | ||
list = new LinkedList() | ||
.append(1, 2) | ||
.append(3, 4) | ||
.append(5) | ||
.append(6); | ||
|
||
|
||
expect(list.first).to.equal(values[0]); | ||
expect(list.last).to.equal(values[values.length - 1]); | ||
expect(list.length).to.equal(values.length); | ||
expect(list.toString()).to.equal(values.join(' -> ')); | ||
}); | ||
|
||
it('should implement prepend correctly, enable chaining and toString should work correctly', () => { | ||
|
||
const values = [0, 1, 2, 3, 4, 5], | ||
list = new LinkedList() | ||
.append(3, 4) | ||
.prepend(1, 2) | ||
.prepend(0) | ||
.append(5); | ||
|
||
|
||
expect(list.first).to.equal(values[0]); | ||
expect(list.last).to.equal(values[values.length - 1]); | ||
expect(list.length).to.equal(values.length); | ||
expect(list.toString()).to.equal(values.join(' -> ')); | ||
}); | ||
|
||
it('should insert correctly', () => { | ||
const values = [1, 2, 6, 7, 8], | ||
list = new LinkedList().append(...values).insert(2, 3, 4).insert(4, 5); | ||
|
||
expect(list.first).to.equal(1); | ||
expect(list.length).to.equal(8); | ||
expect(list.toString()).to.equal([1, 2, 3, 4, 5, 6, 7, 8].join(' -> ')); | ||
}); | ||
|
||
it('should insert correctly', () => { | ||
const list = new LinkedList().append(1, 2).insert(0, 3, 4); | ||
|
||
list.insert(list.length - 1, 'kremikovci'); | ||
|
||
expect(list.first).to.equal(3); | ||
expect(list.last).to.equal(2); | ||
expect(list.length).to.equal(5); | ||
expect(list.toString()).to.equal([3, 4, 1, 'kremikovci', 2].join(' -> ')); | ||
|
||
}); | ||
|
||
it('should have correct for-of', () => { | ||
|
||
const values = [5, 6, 38], | ||
list = new LinkedList().append(...values); | ||
|
||
for (const val of list) { | ||
expect(values.indexOf(val)).to.not.equal(-1); | ||
} | ||
}); | ||
|
||
it('should have correct for-of', () => { | ||
|
||
const values = [5, 6, 3, 'gosho', true, null, 'ivan', { message: 'Hello' }], | ||
list = new LinkedList() | ||
.append(...values.slice(4)) | ||
.prepend(...values.slice(0, 4)); | ||
|
||
for (const val of list) { | ||
expect(val).to.equal(values.shift()); | ||
} | ||
}); | ||
|
||
it('should have correct removeAt', () => { | ||
const theObj = { value: 'val', message: 'hello' }; | ||
const values = ['test', true, null, 1, 2, 'testtest', theObj, 'gg'], | ||
list = new LinkedList().append(...values), | ||
removed1 = list.removeAt(1), | ||
removed2 = list.removeAt(1), | ||
removed3 = list.removeAt(0), | ||
removed4 = list.removeAt(list.length - 1); | ||
|
||
expect(list.first).to.equal(1); | ||
expect(list.last).to.equal(theObj); | ||
expect(list.length).to.equal(values.length - 4); | ||
expect([removed1, removed2, removed3, removed4].join()).to.equal([true, null, 'test', 'gg'].join()); | ||
}); | ||
|
||
it('should have correct indexing with at(index)', () => { | ||
const values = 'babel src --presets es2015 --out-dir ./build -s -w'.split(' '), | ||
list = new LinkedList().append(...values), | ||
listLength = list.length; | ||
|
||
for (let i = 0, length = values.length; i < length; i += 1) { | ||
expect(list.at(i)).to.equal(values[i]); | ||
} | ||
|
||
expect(list.first).to.equal(values[0]); | ||
expect(list.last).to.equal(values[values.length - 1]); | ||
expect(list.length).to.equal(listLength); | ||
}); | ||
|
||
it('at(0) should return the same as .first', () => { | ||
const list = new LinkedList().append(1, 2, 3, 5); | ||
|
||
expect(list.at(0)).to.equal(list.first); | ||
}); | ||
|
||
it('at(list.length - 1) should return the same as .last', () => { | ||
const list = new LinkedList().append(1, 2, 3, 5); | ||
|
||
expect(list.at(list.length - 1)).to.equal(list.last); | ||
}); | ||
|
||
it('should have correct indexing with at(index, value)', () => { | ||
const values = 'babel src --presets es2015 --out-dir ./build -s -w'.split(' '), | ||
list = new LinkedList().append(...values), | ||
listLength = list.length; | ||
|
||
for (let i = 0, length = values.length; i < length; i += 1) { | ||
list.at(i, i); | ||
expect(list.at(i)).to.equal(i); | ||
} | ||
|
||
expect(list.first).to.equal(0); | ||
expect(list.last).to.equal(values.length - 1); | ||
expect(list.length).to.equal(listLength); | ||
}); | ||
|
||
it('should have correct toArray', () => { | ||
|
||
const values = ['test', true, null, 1, 2, 'testtest', { value: 'val', message: 'hello' }], | ||
array = new LinkedList().append(...values).toArray(); | ||
|
||
expect(array instanceof Array).to.be.true; | ||
expect(array.length).to.equal(values.length); | ||
expect(JSON.stringify(array)).to.equal(JSON.stringify(values)); | ||
}); | ||
}); |