spiral 문제를 스칼라로 구현한다면...

2015-09-15 11:37

어제 deview의 여파인지 오늘은 일도 하기 싫다. 최근에 간단한 문제를 풀면서 스칼라 연습도 하고 있는데 최근 programming in scala 책에 나오는 spiral 문제를 풀었다.

요구사항은 다음과 같다. 앗. 깨진다. 좀 더 확실한 그림을 보고 싶다면 spiral 문제를 보면 된다.

---------+
         |
 +-----+ |
 |     | |
 | +-+ | |
 | | + | |
 | |   | |
 | +---+ |
 |       |
 +-------+

위와 같은 spiral 문제를 어떻게 구현하면 좋을까? 책에서는 이 예를 상속 관련 주제로 활용했는데 나는 그냥 내 멋대로 구현해 봤다. 첨부하는 코드에 지적질 하고 싶은 분들은 마음껏 지적질을...

일단 각 방향을 담당하는 Direction과 이 Direction을 구현하는 클래스들..

trait Direction {
  def symbol(): String
  def next(): Direction
  def difference(): (Int, Int)
}
 
case class West() extends Direction {
  override def symbol() = "-"
  override def next() = new North
  override def difference() = (0, -1)
}
 
case class South() extends Direction {
  override def symbol(): String = "|"
  override def next(): Direction = new West
  override def difference() = (1, 0)
}
 
case class East() extends Direction {
  override def symbol(): String = "-"
  override def next(): Direction = new South
  override def difference() = (0, 1)
}
 
case class North() extends Direction {
  override def symbol(): String = "|"
  override def next(): Direction = new East
  override def difference() = (-1, 0)
}

다음은 위 Direction을 활용해 spiral 문제 구현하는 코드. 나의 접근 방식은 한번에 sprial을 구현하지 않고 단계를 나눠 구현했다. 성능은 고려하지 않고 일단 문제를 푸는데 집중했다.

  • spiral 로직을 구현하면서 1차원 Array에 모든 문자열을 생성함. 즉, 나선형 구조를 1차원 구조로 쭈욱 풀어냈다고 생각하면 됨. 즉, 길이가 4라면 "---+|||+--++"와 같은 형태로 데이터 생성
  • 앞에서 생성한 1차원 구조를 출력을 위해 matrix 구조로 변경함.
  • 2차원 matrix를 출력함.

위와 같이 3단계로 나뉘어 구현되어 있다.

class Spiral {
  def draw(row: Array[String]): Unit = {
    row.foreach({
      case null => print(" ")
      case s => print(s)
    })
    println("")
  }
 
  def drawSpiral(matrix: Array[Array[String]]) {
    matrix.foreach(row => draw(row))
  }
 
  def spiral(stream: List[String], matrix: Array[Array[String]], position: (Int, Int), direction: Direction): Array[Array[String]] = {
    stream match {
      case Nil => matrix
      case head :: Nil => {
        matrix(position._1)(position._2) = head
        matrix
      }
      case "+" :: tail => {
        matrix(position._1)(position._2) = "+"
        val nextDirection = direction.next()
        spiral(tail, matrix, position + nextDirection.difference(), nextDirection)
      }
      case head :: tail => {
        matrix(position._1)(position._2) = head
        spiral(tail, matrix, position + direction.difference(), direction)
      }
    }
  }
 
  def createSprialArray(spiral: List[String], length: Int, direction: Direction): List[String] = {
    if (length == 0) spiral
    else {
      val newSpiral = spiral ::: goDirection(length, direction)
      createSprialArray(newSpiral, length - 1, direction.next())
    }
  }
 
  def goDirection(length: Int, direction:Direction) = {
    (1 to length).map({
      case i if (i == length) => "+"
      case _ => direction.symbol()
    }).toList
  }
 
  implicit class TuppleAdd(t: (Int, Int)) {
    def +(p: (Int, Int)) = (p._1 + t._1, p._2 + t._2)
  }
}

0개의 의견 from FB

0개의 의견 from SLiPP

의견 추가하기

연관태그

← 목록으로