Created
December 18, 2019 07:41
-
-
Save stayradiated/08128cbaf7388e09aee08b21386cca52 to your computer and use it in GitHub Desktop.
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
interface BinaryTreeNodeJSON<Value> { | |
value: Value, | |
left?: BinaryTreeNodeJSON<Value>, | |
right?: BinaryTreeNodeJSON<Value>, | |
} | |
class BinaryTreeNode<Value> { | |
static from<Value> (json: BinaryTreeNodeJSON<Value>): BinaryTreeNode<Value> { | |
const { value, left, right } = json | |
const leftNode = left != null ? BinaryTreeNode.from(left) : undefined | |
const rightNode = right != null ? BinaryTreeNode.from(right) : undefined | |
return new BinaryTreeNode(value, leftNode, rightNode) | |
} | |
private locked: boolean | |
public readonly value: Value | |
public readonly left?: BinaryTreeNode<Value> | |
public readonly right?: BinaryTreeNode<Value> | |
public parent?: BinaryTreeNode<Value> | |
public constructor ( | |
value: Value, | |
left?: BinaryTreeNode<Value>, | |
right?: BinaryTreeNode<Value>, | |
) { | |
this.value = value | |
this.left = left | |
if (this.left != null) { | |
this.left.setParent(this) | |
} | |
this.right = right | |
if (this.right != null) { | |
this.right.setParent(this) | |
} | |
this.locked = false | |
} | |
public setParent (parent: BinaryTreeNode<Value>) { | |
this.parent = parent | |
} | |
public is_locked () { | |
return this.locked | |
} | |
public everyChild (fn: (node: BinaryTreeNode<Value>) => boolean): boolean { | |
if (this.left != null && (!fn(this.left) || !this.left.everyChild(fn))) { | |
return false | |
} | |
if (this.right != null && (!fn(this.right) || !this.right.everyChild(fn))) { | |
return false | |
} | |
return true | |
} | |
public everyParent (fn: (node: BinaryTreeNode<Value>) => boolean): boolean { | |
if ( | |
this.parent != null && | |
(!fn(this.parent) || !this.parent.everyParent(fn)) | |
) { | |
return false | |
} | |
return true | |
} | |
private everyParentUnlocked () { | |
return this.everyParent((node) => !node.is_locked()) | |
} | |
private everyChildUnlocked () { | |
return this.everyChild((node) => !node.is_locked()) | |
} | |
public lock () { | |
if (!this.everyParentUnlocked() || !this.everyChildUnlocked()) { | |
return false | |
} | |
this.locked = true | |
return true | |
} | |
public unlock () { | |
if (!this.everyParentUnlocked() || !this.everyChildUnlocked()) { | |
return false | |
} | |
this.locked = false | |
return true | |
} | |
public toString (leftpad = 0): string { | |
const padding = new Array(leftpad).fill(' ').join('') | |
const output = [`${this.value}${this.is_locked() ? '🔒' : ''}`] | |
if (this.left != null) { | |
output.push(`${padding} ⤷ ${this.left.toString(leftpad + 3)}`) | |
} | |
if (this.right != null) { | |
output.push(`${padding} ⤷ ${this.right.toString(leftpad + 3)}`) | |
} | |
return output.join('\n') | |
} | |
} | |
const familyTree = BinaryTreeNode.from({ | |
value: 'Emily', | |
left: { | |
value: 'Thomas', | |
left: { | |
value: 'Daniel', | |
left: { value: 'Grace' }, | |
right: { value: 'Matthew' }, | |
}, | |
right: { | |
value: 'Olivia', | |
left: { value: 'Georgia' }, | |
right: { value: 'Liam' }, | |
}, | |
}, | |
right: { | |
value: 'Hannah', | |
left: { | |
value: 'Emma', | |
left: { value: 'Jessica' }, | |
right: { value: 'Joshua' }, | |
}, | |
right: { | |
value: 'Jack', | |
left: { value: 'Sophie' }, | |
right: { value: 'James' }, | |
}, | |
}, | |
}) | |
familyTree.lock() | |
familyTree.left.lock() | |
familyTree.right.lock() | |
console.log(familyTree.toString()) | |
familyTree.unlock() | |
familyTree.left.lock() | |
familyTree.right.lock() | |
familyTree.lock() | |
console.log(familyTree.toString()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment