-
-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
478 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
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,41 @@ | ||
# Instructions | ||
|
||
Reparent a tree on a selected node. | ||
|
||
A [tree][wiki-tree] is a special type of [graph][wiki-graph] where all nodes are connected but there are no cycles. | ||
That means, there is exactly one path to get from one node to another for any pair of nodes. | ||
|
||
This exercise is all about re-orientating a tree to see things from a different point of view. | ||
For example family trees are usually presented from the ancestor's perspective: | ||
|
||
```text | ||
+------0------+ | ||
| | | | ||
+-1-+ +-2-+ +-3-+ | ||
| | | | | | | ||
4 5 6 7 8 9 | ||
``` | ||
|
||
But there is no inherent direction in a tree. | ||
The same information can be presented from the perspective of any other node in the tree, by pulling it up to the root and dragging its relationships along with it. | ||
So the same tree from 6's perspective would look like: | ||
|
||
```text | ||
6 | ||
| | ||
+-----2-----+ | ||
| | | ||
7 +-----0-----+ | ||
| | | ||
+-1-+ +-3-+ | ||
| | | | | ||
4 5 8 9 | ||
``` | ||
|
||
This lets us more simply describe the paths between two nodes. | ||
So for example the path from 6-9 (which in the first tree goes up to the root and then down to a different leaf node) can be seen to follow the path 6-2-0-3-9. | ||
|
||
This exercise involves taking an input tree and re-orientating it from the point of view of one of the nodes. | ||
|
||
[wiki-graph]: https://en.wikipedia.org/wiki/Tree_(graph_theory) | ||
[wiki-tree]: https://en.wikipedia.org/wiki/Graph_(discrete_mathematics) |
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,115 @@ | ||
<# | ||
.SYNOPSIS | ||
Given a tree, reorientate it based on a selected node. | ||
.DESCRIPTION | ||
A tree is a special type of graph where all nodes are connected but there are no cycles. | ||
That means, there is exactly one path to get from one node to another for any pair of nodes. | ||
Implement a class to represent the Tree along with these methods: | ||
- FromPov: accept a value of a node, return a new Tree object orientated based on that node. | ||
Throw error if the value/node does't exist in the tree. | ||
- Path: accept the source and destination values of two nodes, return an array of string represent the path from source to destination. | ||
Throw error if the path doesn't exist. | ||
- Equals: equality method to compare trees for the test suite. | ||
.EXAMPLE | ||
Read instructions for visual example. | ||
#> | ||
|
||
Class Tree { | ||
[string] $Value | ||
[Tree[]] $Children | ||
[hashtable] hidden $Graph = @{} | ||
|
||
Tree([string] $value) { | ||
$this.Value = $value | ||
$this.Children = @() | ||
} | ||
|
||
Tree([string] $value, [Tree[]] $Children) { | ||
$this.Value = $value | ||
$this.Children = $Children | ||
} | ||
|
||
[void] hidden CreateGraph($tree, $parent) { | ||
<# | ||
.DESCRIPTION | ||
Helper function, creating a hashtable representing the graph for the original tree. | ||
#> | ||
$this.Graph[$tree.Value] = @{ | ||
Parent = $parent | ||
Children = @($tree.Children | ForEach-Object {$_.Value}) | ||
} | ||
foreach ($child in $tree.Children) { | ||
$this.CreateGraph($child, $tree.Value) | ||
} | ||
} | ||
|
||
[void] hidden PovGraph([string]$root) { | ||
<# | ||
.DESCRIPTION | ||
Helper function, representing the graph for the tree with a new root. | ||
#> | ||
if ($this.Graph.Count -eq 0) {$this.CreateGraph($this, $null)} | ||
if (-not $this.Graph.ContainsKey($root)) {Throw "Tree could not be reoriented"} | ||
if ($null -eq $this.Graph[$root].Parent) {return} | ||
|
||
$curParent = $this.Graph[$root].Parent | ||
$this.Graph[$root].Parent = $null | ||
$this.Graph[$root].Children += @($curParent) | ||
|
||
while ($null -ne $curParent) { | ||
$tempParent = $this.Graph[$curParent].Parent | ||
$this.Graph[$curParent].Parent = $root | ||
$this.Graph[$curParent].Children = ($this.Graph[$curParent].Children -ne $root) + ($null -eq $tempParent ? @() : @($tempParent) ) | ||
$root = $curParent | ||
$curParent = $tempParent | ||
} | ||
} | ||
|
||
[Tree] FromPov([string] $node) { | ||
if ($this.Graph.Count -eq 0) {$this.PovGraph($node)} | ||
|
||
return [Tree]::new( | ||
$node, | ||
@( $this.Graph[$node].Children | ForEach-Object {$this.FromPov($_)}) | ||
) | ||
} | ||
|
||
[string[]] Path([string] $from, [string] $to) { | ||
if ($this.Graph.Count -eq 0) {$this.CreateGraph($this, $null)} | ||
if (-not $this.Graph.ContainsKey($from) -or -not $this.Graph.ContainsKey($to)) { | ||
Throw "No path found" | ||
} | ||
$this.PovGraph($from) | ||
$path = @() | ||
$parent = $to | ||
while ($parent) { | ||
$path+= $parent | ||
$parent = $this.Graph[$parent].Parent | ||
} | ||
[array]::Reverse($path) | ||
return $path | ||
} | ||
|
||
[bool] Equals($other) { | ||
if($this.Value -ne $other.Value) { | ||
return $false | ||
} | ||
|
||
if($this.Children.Count -ne $other.Children.Count) { | ||
return $false | ||
} | ||
|
||
$sortedOwnChildren = $this.Children | Sort-Object { $_.Value } | ||
$sortedTheirChildren = $other.Children | Sort-Object { $_.Value } | ||
|
||
for ($i = 0; $i -lt $sortedOwnChildren.Count; $i++) { | ||
if ($sortedOwnChildren[$i] -ne $sortedTheirChildren[$i]) { | ||
return $false | ||
} | ||
} | ||
return $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,19 @@ | ||
{ | ||
"authors": [ | ||
"glaxxie" | ||
], | ||
"files": { | ||
"solution": [ | ||
"Pov.ps1" | ||
], | ||
"test": [ | ||
"Pov.tests.ps1" | ||
], | ||
"example": [ | ||
".meta/Pov.example.ps1" | ||
] | ||
}, | ||
"blurb": "Reparent a graph on a selected node.", | ||
"source": "Adaptation of exercise from 4clojure", | ||
"source_url": "https://www.4clojure.com/" | ||
} |
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,55 @@ | ||
# This is an auto-generated file. | ||
# | ||
# Regenerating this file via `configlet sync` will: | ||
# - Recreate every `description` key/value pair | ||
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications | ||
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) | ||
# - Preserve any other key/value pair | ||
# | ||
# As user-added comments (using the # character) will be removed when this file | ||
# is regenerated, comments can be added via a `comment` key. | ||
|
||
[1b3cd134-49ad-4a7d-8376-7087b7e70792] | ||
description = "Reroot a tree so that its root is the specified node. -> Results in the same tree if the input tree is a singleton" | ||
|
||
[0778c745-0636-40de-9edd-25a8f40426f6] | ||
description = "Reroot a tree so that its root is the specified node. -> Can reroot a tree with a parent and one sibling" | ||
|
||
[fdfdef0a-4472-4248-8bcf-19cf33f9c06e] | ||
description = "Reroot a tree so that its root is the specified node. -> Can reroot a tree with a parent and many siblings" | ||
|
||
[cbcf52db-8667-43d8-a766-5d80cb41b4bb] | ||
description = "Reroot a tree so that its root is the specified node. -> Can reroot a tree with new root deeply nested in tree" | ||
|
||
[e27fa4fa-648d-44cd-90af-d64a13d95e06] | ||
description = "Reroot a tree so that its root is the specified node. -> Moves children of the new root to same level as former parent" | ||
|
||
[09236c7f-7c83-42cc-87a1-25afa60454a3] | ||
description = "Reroot a tree so that its root is the specified node. -> Can reroot a complex tree with cousins" | ||
|
||
[f41d5eeb-8973-448f-a3b0-cc1e019a4193] | ||
description = "Reroot a tree so that its root is the specified node. -> Errors if target does not exist in a singleton tree" | ||
|
||
[9dc0a8b3-df02-4267-9a41-693b6aff75e7] | ||
description = "Reroot a tree so that its root is the specified node. -> Errors if target does not exist in a large tree" | ||
|
||
[02d1f1d9-428d-4395-b026-2db35ffa8f0a] | ||
description = "Given two nodes, find the path between them -> Can find path to parent" | ||
|
||
[d0002674-fcfb-4cdc-9efa-bfc54e3c31b5] | ||
description = "Given two nodes, find the path between them -> Can find path to sibling" | ||
|
||
[c9877cd1-0a69-40d4-b362-725763a5c38f] | ||
description = "Given two nodes, find the path between them -> Can find path to cousin" | ||
|
||
[9fb17a82-2c14-4261-baa3-2f3f234ffa03] | ||
description = "Given two nodes, find the path between them -> Can find path not involving root" | ||
|
||
[5124ed49-7845-46ad-bc32-97d5ac7451b2] | ||
description = "Given two nodes, find the path between them -> Can find path from nodes other than x" | ||
|
||
[f52a183c-25cc-4c87-9fc9-0e7f81a5725c] | ||
description = "Given two nodes, find the path between them -> Errors if destination does not exist" | ||
|
||
[f4fe18b9-b4a2-4bd5-a694-e179155c2149] | ||
description = "Given two nodes, find the path between them -> Errors if source does not exist" |
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,36 @@ | ||
<# | ||
.SYNOPSIS | ||
Given a tree, reorientate it based on a selected node. | ||
.DESCRIPTION | ||
A tree is a special type of graph where all nodes are connected but there are no cycles. | ||
That means, there is exactly one path to get from one node to another for any pair of nodes. | ||
Implement a class to represent the Tree along with these methods: | ||
- FromPov: accept a value of a node, return a new Tree object orientated based on that node. | ||
Throw error if the value/node does't exist in the tree. | ||
- Path: accept the source and destination values of two nodes, return an array of string represent the path from source to destination. | ||
Throw error if the path doesn't exist. | ||
- Equals: equality method to compare trees for the test suite. | ||
.EXAMPLE | ||
Read instructions for visual example. | ||
#> | ||
|
||
Class Tree { | ||
Tree([string] $value, [Tree[]] $Children) { | ||
Throw "Please implement this class" | ||
} | ||
|
||
[Tree] FromPov([string] $node) { | ||
Throw "Please implement this function" | ||
} | ||
|
||
[string[]] Path([string] $from, [string] $to) { | ||
Throw "Please implement this function" | ||
} | ||
|
||
[bool] Equals($other) { | ||
Throw "Please implement this function" | ||
} | ||
} |
Oops, something went wrong.