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(" "))
}
}
Like this:
Like Loading...