Skip to content

Instantly share code, notes, and snippets.

@stayradiated
Created December 18, 2019 07:41
Show Gist options
  • Save stayradiated/08128cbaf7388e09aee08b21386cca52 to your computer and use it in GitHub Desktop.
Save stayradiated/08128cbaf7388e09aee08b21386cca52 to your computer and use it in GitHub Desktop.
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