Skip to content

Commit

Permalink
changed the way trees get printed
Browse files Browse the repository at this point in the history
now trees are much nicer, this commit breaks the drawer API which is not anymore a 2d slice of bytes, insted it's a 2d slice of runes
  • Loading branch information
m1gwings committed Aug 28, 2020
1 parent eb0e092 commit a040c43
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 42 deletions.
34 changes: 14 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type Tree struct {
}
```

**drawer** is a very simple "ascii-canvas" on which you can draw bytes representing ascii characters or another whole canvas specifying the coordinates of the upper-left corner.
**drawer** is a very simple "unicode-canvas" on which you can draw runes representing unicode characters or another whole canvas specifying the coordinates of the upper-left corner.

---
If you run the following in the root directory:
Expand All @@ -28,30 +28,24 @@ you will get a binary that prints random trees to give you an idea.
```
./treedrawer
76
|
15
/ \
/ \
/ \
/ \
28 12
/ \ |
94 63 39
14
37
╭────┴────╮
97 29
│ ╭──┴──╮
12 47 24
```

With the **-l** flag you can specify the maximum number of layers of the random tree
```
./treedrawer -l 3
14
/ \
/ \
/ \
/ \
45 84
/ \ / \
38 72 77 32
71
60
╭──┴──╮
45 51
```
# API
## Building the tree
Expand All @@ -76,7 +70,7 @@ Tree type satisfies the Stringer interface, you can easily use fmt package to ge
fmt.Println(t)
2
/ \
╭─┴─╮
5 3
```
## Retreiving values from the tree
Expand Down
22 changes: 11 additions & 11 deletions drawer/drawer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,37 @@ package drawer

import "fmt"

// Drawer is a canvas on which you can draw ascii bytes.
// Drawer is a canvas on which you can draw unicode runes.
type Drawer struct {
canvas [][]byte
canvas [][]rune
}

// NewDrawer returns a new Drawer with width w and height h.
func NewDrawer(w, h int) *Drawer {
d := new(Drawer)
d.canvas = make([][]byte, h)
d.canvas = make([][]rune, h)
for i := range d.canvas {
d.canvas[i] = make([]byte, w)
d.canvas[i] = make([]rune, w)
}
return d
}

// NewDrawerFromString return a new Drawer which contains the string s.
func NewDrawerFromString(s string) *Drawer {
d := new(Drawer)
d.canvas = make([][]byte, 1)
d.canvas[0] = []byte(s)
d.canvas = make([][]rune, 1)
d.canvas[0] = []rune(s)
return d
}

// DrawByte draws a byte in position x, y in the drawer canvas.
// DrawRune draws a rune in position x, y in the drawer canvas.
// Returns an error if the x, y position in input is outside the canvas.
func (d *Drawer) DrawByte(b byte, x, y int) error {
func (d *Drawer) DrawRune(r rune, x, y int) error {
w, h := d.Dimens()
if x >= w || y >= h {
return fmt.Errorf("position (%d, %d) is outside the canvas of dimension (%d, %d)", x, y, w, h)
}
d.canvas[y][x] = b
d.canvas[y][x] = r
return nil
}

Expand All @@ -45,8 +45,8 @@ func (d *Drawer) DrawDrawer(e *Drawer, x, y int) error {
return fmt.Errorf("canvas e of dimension (%d, %d) drawn in position (%d, %d) overflows canvas d of dimension (%d, %d)", eW, eH, x, y, w, h)
}
for i, row := range e.canvas {
for j, b := range row {
d.canvas[i+y][j+x] = b
for j, r := range row {
d.canvas[i+y][j+x] = r
}
}
return nil
Expand Down
32 changes: 21 additions & 11 deletions tree/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func stringify(t *Tree) *drawer.Drawer {
if err != nil {
log.Fatal(fmt.Errorf("error while drawing val with one child: %v", err))
}
err = d.DrawByte('|', w/2, 1)
err = d.DrawRune('│', w/2, 1)
if err != nil {
log.Fatal(fmt.Errorf("error while drawing | with one child: %v", err))
}
Expand All @@ -142,29 +142,39 @@ func stringify(t *Tree) *drawer.Drawer {
maxChildW := int(math.Max(float64(dLeftW), float64(dRightW)))
w := maxChildW*2 + 1
maxChildH := int(math.Max(float64(dLeftH), float64(dRightH)))
slashEndI := maxChildW/2 + 1
edgeH := maxChildW - slashEndI
h := maxChildH + edgeH + 1
h := maxChildH + 2
d := drawer.NewDrawer(w, h)
err := d.DrawDrawer(dVal, (w-dValW)/2, 0)
if err != nil {
log.Fatal(fmt.Errorf("error while drawing val with two children: %v", err))
}
for i := 0; i < edgeH; i++ {
err = d.DrawByte('/', w/2-1-i, i+1)
err = d.DrawRune('┴', w/2, 1)
if err != nil {
log.Fatal(fmt.Errorf("error while drawing ┴ rune with two childern: %v", err))
}
for i := 1; i <= maxChildW/2; i++ {
err = d.DrawRune('─', w/2-i, 1)
if err != nil {
log.Fatal(fmt.Errorf("error while drawing / with two children: %v", err))
log.Fatal(fmt.Errorf("error while drawing ─ rune with two childern with negative i: %v", err))
}
err = d.DrawByte('\\', w/2+1+i, i+1)
err = d.DrawRune('─', w/2+i, 1)
if err != nil {
log.Fatal(fmt.Errorf("error while drawing \\ with two children: %v", err))
log.Fatal(fmt.Errorf("error while drawing ─ rune with two childern with positive i: %v", err))
}
}
d.DrawDrawer(dLeft, (maxChildW-dLeftW)/2, edgeH+1)
err = d.DrawRune('╭', w/2-maxChildW/2-1, 1)
if err != nil {
log.Fatal(fmt.Errorf("error while drawing ╭ rune with two children: %v", err))
}
err = d.DrawRune('╮', w/2+maxChildW/2+1, 1)
if err != nil {
log.Fatal(fmt.Errorf("error while drawing ╮ rune with two children: %v", err))
}
err = d.DrawDrawer(dLeft, (maxChildW-dLeftW)/2, 2)
if err != nil {
log.Fatal(fmt.Errorf("error while drawing left child: %v", err))
}
d.DrawDrawer(dRight, maxChildW+1+(maxChildW-dRightW)/2, edgeH+1)
err = d.DrawDrawer(dRight, maxChildW+1+(maxChildW-dRightW)/2, 2)
if err != nil {
log.Fatal(fmt.Errorf("error while drawing right child: %v", err))
}
Expand Down

0 comments on commit a040c43

Please sign in to comment.