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
30 changes: 30 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,33 @@
/.idea/*
*.iml
/target/*
### Maven template
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar

### Gradle template
.gradle
**/build/
!src/**/build/

# Ignore Gradle GUI config
gradle-app.setting

# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar

# Cache of project
.gradletasknamecache

# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
# gradle/wrapper/gradle-wrapper.properties

101 changes: 80 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,74 @@
# tree_printer

A Java class for printing binary trees as ASCII text

It hasn't been optimized for run time efficiency, but since we're talking about printing in ASCII, I figured it's not going to be used on very large trees. It does have some nice features though.
It hasn't been optimized for run time efficiency, but since we're talking about printing in ASCII, I figured it's not going to be used on very large trees. It does have some nice features though.

1. It makes efficient use of space in that a large subtree extends under a smaller one as much as possible.
2. It's generic, working for any binary tree data objects, as long as you can provide functions (lambda functions will do) to get a nodes label as a String, and to get the left and right sub-nodes.
3. There's a parameter to set the minimum horizontal space between node labels.
4. Node labels are strings of arbitrary length.
5. In addition to a method for printing a single tree, there's a method for printing a list of trees horizontally across the page (with a parameter for page width), using as many rows as necessary.
6. There's an option to print trees with diagonal branches (diagonal unicode box drawing characters) or with horizontal branches (using unicode box drawing characters). The latter is more compact and makes tree levels more visually clear.
7. It supports basic ANSI escape sequences for colored output to terminal.
8. It works.

Some [demo/test programs](src/test/java) are included.

1. It makes efficient use of space in that a large subtree extends under a smaller one as much as possible.
2. It's generic, working for any binary tree data objects, as long as you can provide functions (lambda functions will do) to get a nodes label as a String, and to get the left and right sub-nodes.
3. There's a parameter to set the minimum horizontal space between node labels.
4. Node labels are strings of arbitrary length.
5. In addition to a method for printing a single tree, there's a method for printing a list of trees horizontally across the page (with a parameter for page width), using as many rows as necessary.
6. There's an option to print trees with diagonal branches (using slash and backslash characters) or with horizontal branches (using ascii box drawing characters). The latter is more compact and makes tree levels more visually clear.
7. It works.
## Usage

Some demo/test programs are included.
### Gradle:

The TreePrinter object has two methods for printing binary trees as ASCII text. PrintTree prints a single tree. PrintTrees prints a list of trees horizontally across the page, in multiple rows if necessary.
Use `sourceControl` block in your `settings.gradle.kts`

The TreePrinter object has a few settable parameters affecting how it prints trees. A positive integer parameter 'hspace' specifies the minimum number of horizontal spaces between any two node labels in the tree. A boolean parameter 'squareBranches' determines whether the tree is drawn with horizontal branches (using ascii box drawing characters) or diagonal branches (using slash and backslash characters). The boolean 'lrAgnostic' parameter only affects trees drawn with the ascii box drawing characters. Its effect is is that tree nodes with only a single subtree are drawn with a straight down vertical branch, providing no indication of whether it is a left or right subtree.
```kotlin
// in settings.gradle.kts:
sourceControl {
// without the `uri(...)` if you use Groovy
gitRepository(
uri("https://github.com/billvanyo/tree_printer.git")
) {
producesModule(
"tech.vanyo:tree_printer:1.1"
)
}
}
```

A few test/demo programs are included. For instance, the program EnumTrees can be used to print an enumeration of all binary trees of a given size. All trees of size 5, labeled with number words (one, two, etc) is printed as:
and add the dependency in your buildscript `build.gradle.kts` dependencies block:

```kotlin
dependencies {
implementation(
"tech.vanyo:tree_printer:1.1"
)
}
```
mvn compile
mvn exec:java -Dexec.mainClass="EnumTrees"

## Details

The TreePrinter object has two methods for printing binary trees as ASCII text. `printTree(tree)` prints a single tree.
`printTrees(trees, lineWidth)` prints a list of trees horizontally across the page, in multiple rows if necessary.

The TreePrinter object has a few settable parameters affecting how it prints trees:

- A positive integer parameter `labelGap` specifies the minimum number of horizontal spaces between any two node labels in the tree.
- `colGap` and `rowGap` specifies spacing between trees when using `printTrees(trees, lineWidth)`
- A boolean parameter `squareBranches` determines whether the tree is drawn with horizontal branches (using ascii box drawing characters) or diagonal branches (using slash and backslash characters).
- The boolean `lrAgnostic` parameter only affects trees drawn with square style. Its effect is that tree nodes with only a single subtree are drawn with a straight down vertical branch, providing no indication of whether it is a left or right subtree.
- `usePlaceholder` replaces empty labels with placeholders

## Examples

A few test/demo programs are included. For instance, the program EnumTrees can be used to print an enumeration of all binary trees of a given size. All trees of size 5, labeled with number words (one, two, etc) is printed as:

```bash
# use gradlew.bat on windows
./gradlew :testLogging --tests *EnumTrees
```

This produces output like:

```
one one one one one one one one one
\ \ \ \ \ \ \ \ \
Expand Down Expand Up @@ -81,14 +126,21 @@ one four two four one one two three three
\ / one three \ /
three two two one
```
RandomTree can be used to print a single randomly generated tree. The following is an example of the same tree
printed 4 different ways, with horizontal spacing of 1 and of 3, and with diagonal and horizontal branches. To
run this from the command line using maven type:

[RandomTree](src/test/java/RandomTree.java) can be used to print a single randomly generated tree. The following is an example of
the
same
tree
printed 4 different ways, with horizontal spacing of 1 and of 3, and with diagonal and horizontal branches. To
run this from the command line using maven type:

```
mvn compile
mvn exec:java -Dexec.mainClass="RandomTree"
# use gradlew.bat on windows
./gradlew :testLogging --tests *RandomTree
```

This produces output like:

```
27
┌─────┴─────┐
Expand Down Expand Up @@ -182,10 +234,17 @@ This produces output like:
14 16

```
There's a demo program that produces a tree diagram of all Collatz sequences
(https://en.wikipedia.org/wiki/Collatz_conjecture) of a given length. This demonstrates an option to print trees

There's a [demo program](src/test/java/CollatzTree.java) that produces a tree diagram of all Collatz sequences
(https://en.wikipedia.org/wiki/Collatz_conjecture) of a given length. This demonstrates an option to print trees
in such a way that if there is only a single subtree, it is treated the same regardless of whether it is a left
or right subtree. This produces output like:

```bash
# use gradlew.bat on windows
./gradlew :testLogging --tests *CollatzTree
```

```
1
Expand Down
43 changes: 43 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import org.gradle.api.tasks.testing.logging.TestLogEvent

plugins {
java
}

repositories {
mavenCentral()
mavenLocal()
}

dependencies {
testImplementation("org.junit.jupiter", "junit-jupiter-api", "5.8.1")
testRuntimeOnly("org.junit.jupiter", "junit-jupiter-engine", "5.1.8")
}

group = "tech.vanyo"
version = "1.1"
description = "Print binary trees in the terminal neatly with minimal overhead. Small dependency."

java {
toolchain {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}

tasks.withType<JavaCompile> {
options.encoding = "UTF-8"
}

tasks.register<Test>("testLogging") {
description = "Run test task with stdout/stderr logged"
group = "verification"
testLogging {
outputs.upToDateWhen { false } // don't cache this task's result
events = setOf(TestLogEvent.PASSED, TestLogEvent.FAILED, TestLogEvent.STANDARD_OUT, TestLogEvent.STARTED)
}
}

tasks.withType<Test>().configureEach {
useJUnitPlatform()
}
Binary file added gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
5 changes: 5 additions & 0 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading