Code Challenge My Scala Solution

import scala.collection.mutable
import scala.io.Source

object Solution extends App {

  case class Point(row: Int, col: Int)

  class Elevation(fileName: String) {

    val input = Source.stdin.getLines
    val inputInts = ("""\d+""".r findAllIn input.mkString(" ")).map(_.toInt)

    val _size = inputInts.next
    val elev: Array[Array[Int]] = Array.tabulate(_size, _size)((x: Int, y: Int) => inputInts.next)

    def size: Int = _size

    def mkString(sep: String = "\n"): String = elev.deep.mkString(sep)

    def heights(ps: List[Point]): List[Int] = ps.map(p => elev(p.row)(p.col))
    def height(ps: Point): Int = elev(ps.row)(ps.col)
  }

  class Basin(elev: Elevation) {

    val size = elev.size

    val empty: Int = -1
    val empty2 = Point(-1, -1)

    var basin: Array[Array[Int]] = Array.fill(size, size)(empty)
    // Should create a class with basinCount and basinNum in it, so they can't get out of sync
    var basinCount: mutable.MutableList[Int] = new mutable.MutableList()
    var basinNum = empty

    def set(p: Point): Int = {
      
      if (basin(p.row)(p.col) == empty) {
        val pn = lowestNeighbor(p)

        if (pn == empty2) {
          basinNum += 1
          basinCount += 1

          basin(p.row)(p.col) = basinNum
        } else {
          basin(p.row)(p.col) = this.set(pn)
          basinCount(basin(p.row)(p.col)) += 1
        }
      }

      return (basin(p.row)(p.col))
    }

    def inBounds(max: Int)(p: Point): Boolean = (p.row >= 0) & (p.col >= 0) & (p.row < max) & (p.col < max)

    def neighbors(p: Point): List[Point] = {
      
      var n = List(Point(p.row - 1, p.col), Point(p.row + 1, p.col), Point(p.row, p.col - 1), Point(p.row, p.col + 1))

      return (n.filter(inBounds(size)))
    }

    def lowestNeighbor(p: Point): Point = {
      
      val e = elev.height(p)
      val n = neighbors(p)

      val low = elev.heights(n).zip(n).minBy(_._1)

      if (low._1  _).toList
  }

  ////////// MAIN //////////

  override def main(args: Array[String]): Unit = {

    val elev = new Elevation("/Users/wfolta/Documents/Development/palantir/test3")

    val basin = new Basin(elev)

    for (row <- 0 until elev.size; col <- 0 until elev.size) {
      basin.set(Point(row, col))
    }

    println(basin.counts.mkString(" "))
  }
}
Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s