Here is the code:
import java.io.{File, PrintWriter}
import scala.io.Source
object SpiralObj {
object Element {
private class ArrayElement(
val contents: Array[String]
) extends Element
private class LineElement(s: String) extends Element {
val contents = Array(s)
}
private class UniformElement(
ch: Char,
override val width: Int,
override val height: Int
) extends Element {
private val line = ch.toString * width
def contents = Array.fill(height)(line)
}
def elem(contents: Array[String]): Element = {
new ArrayElement(contents)
}
def elem(s: String): Element = {
new ArrayElement(Array(s))
}
def elem(chr: Char, width: Int, height: Int): Element = {
new UniformElement(chr, width, height)
}
}
abstract class Element {
import Element.elem
// contents to be implemented
def contents: Array[String]
def width: Int = contents(0).length
def height: Int = contents.length
def above(that: Element): Element = {
val this1 = this widen that.width
val that1 = that widen this.width
elem(this1.contents ++ that1.contents)
}
def beside(that: Element): Element = {
val this1 = this heighten that.height
val that1 = that heighten this.height
elem(
for ((line1, line2) <- this1.contents zip that1.contents)
yield line1 + line2
)
}
def heighten(h: Int): Element = {
if (h <= height) this
else {
val top = elem(' ', width, (h - height) / 2)
val bottom = elem(' ', width, h - height - top.height)
top above this above bottom
}
}
def widen(w: Int): Element = {
if (w <= width) this
else {
val left = elem(' ', (w - width) / 2, height)
val right = elem(' ', w - width - left.width, height)
left beside this beside right
}
}
override def toString = contents mkString "\n"
}
object Spiral {
import Element._
val space = elem(" ")
val corner = elem("+")
def spiral(nEdges: Int, direction: Int): Element = {
if(nEdges == 0) elem("+")
else {
val sp = spiral(nEdges - 1, (direction + 3) % 4) // or (direction - 1) % 4, but we don't want negative numbers
def verticalBar = elem('|', 1, sp.height)
def horizontalBar = elem('-', sp.width, 1)
if(direction == 0)
(corner beside horizontalBar) above (sp beside space)
else if(direction == 1)
(sp above space) beside (corner above verticalBar)
else if(direction == 2)
(space beside sp) above (horizontalBar beside corner)
else
(verticalBar above corner) beside (space above sp)
}
}
def draw(n: Int): Unit = {
println()
println(spiral(n, n % 4))
}
}
}
object Main {
def main(args: Array[String]) {
import SpiralObj._
println()
Spiral.draw(0)
println()
Spiral.draw(1)
println()
Spiral.draw(2)
println()
Spiral.draw(3)
}
}
Run it:
+
++
|
++
|
--+
|
| ++
| |
+--+
The crital part here is the recursive way of thinking:
I want to draw a 7-node spiral. What should I do if I already have a 6-node spiral?
Also, think about these questions:
- In the
draw
function, what if you usedspiral(n, 1)
instead ofspiral(n, n % 4)
? - In the base case of the recursive function
spiral
, what if you used the predicatenEdges == 1
instead ofnEdges == 0
?
0 comments:
Post a Comment