Scala多维数据结构

时间:2015-06-01 20:31:49

标签: scala multidimensional-array

我是Scala的新手,我想问一下实现这个问题的最有效方法是什么。

想象一下,我们有一个体育场,它有X个扇区,每个扇区有Y行,每排有Z个座位。

想象一下,我们有随机数量的占用席位。

a)给定一排,返回占用席位数。

b)给定一个部门,返回占用席位数量。

c)给定一个扇区和一行,确保椅子是空的x(1 <= x <= n)。

d)给定一行,返回一个带有空椅位置的数组。

e)给定一个扇区,返回最多空置椅子的行。

f)返回占用体育场椅子的数量。

g)假设体育场入口有两个值:两个最接近场的行为75.00美元,其他行为50.00美元。写一个返回游戏收入的函数。

提前感谢您的解决方案

2 个答案:

答案 0 :(得分:0)

最有效率可能意味着您编写代码的努力或运行时速度方面。在前一种情况下,我会使用嵌套Vector之类的东西。在后一种情况下,平坦Array可能表现最佳。

val rows = 4
val cols = 3
val arr  = new Array[Boolean](rows * cols)

def get(row: Int, col: Int)                 = arr(row * cols + col)
def set(row: Int, col: Int, value: Boolean) = arr(row * cols + col) = value

def occupiedInRow(row: Int) = (0 until cols).count(get(row, _))

set(row = 1, col = 0, value = true)
set(row = 1, col = 2, value = true)
assert(occupiedInRow(1) == 2)

因此有三个或更多维度。

除非这是为了练习,否则我会使用现有的优化库,例如Breeze or Saddle

答案 1 :(得分:0)

我认为映射Boolean的最有效方式是BitSet,它有两种形式:mutableimmutable。不可变的效率稍高,但它的效率在任何并发\分布情况下都消失了。 这是你的作业的实现

object Stadium {
  def random(sectors: Int, rows: Int, seats: Int): Stadium = {
    val size = sectors * rows * seats
    new Stadium(sectors, rows, seats,
      BitSet fromBitMask Array.fill(size / 64 + 1)(Random.nextLong()) take size)
  }

  def apply(occupied: (Int, Int, Int)*): Stadium = {
    val sectors = occupied.map(_._1).max + 1
    val rows = occupied.map(_._2).max + 1
    val seats = occupied.map(_._3).max + 1
    val occNums = occupied map {
      case (sector, row, seat) => (sector * rows + row) * seats + seat
    }
    Stadium(sectors, rows, seats, BitSet(occNums: _*))
  }

  def income[N: Numeric](stadium: Stadium, standardPrice: N, premiumPrice: PartialFunction[Int, N] = PartialFunction.empty) = (
    for {
      sector <- 0 until stadium.sectors
      row <- 0 until stadium.rows
      price = premiumPrice.applyOrElse[Int, N](row, _ => standardPrice)
      occupied = implicitly[Numeric[N]].fromInt(stadium.occupiedInRow(sector, row))
    } yield price * occupied
    ).sum
}

case class Stadium(sectors: Int, rows: Int, seats: Int, occupied: BitSet) {
  @inline final def sectorSeats = rows * seats
  def rowRange(sector: Int, row: Int) = {
    val from = (sector * rows + row) * seats
    occupied.range(from, from + seats) map (_ - from)
  }
  def sectorRange(sector: Int) = {
    val from = sector * sectorSeats
    occupied.range(from, from + sectorSeats) map (_ - from)
  }
  lazy val wholeRow = BitSet(0 until seats: _*)
  def occupiedInRow(sector: Int, row: Int) = rowRange(sector, row).size
  def occupiedInSector(sector: Int) = sectorRange(sector).size
  def isOccupied(sector: Int, row: Int, seat: Int) = occupied(sector * sectorSeats + row * seats + seat)
  def isVacant(sector: Int, row: Int, seat: Int) = !isOccupied(sector, row, seat)
  def vacantInRow(sector: Int, row: Int) = wholeRow &~ rowRange(sector, row)
  def mostVacant(sector: Int) = 0 until rows maxBy (vacantInRow(sector, _).size)
  def occupiedSize = occupied.size
}

因此。如果你想定义你的体育场,如:

val st = Stadium((0,0,0),(0,0,1),(0,1,0),(0,2,2), (0,2,1))

标准价格50美元的收入将很容易计算

Stadium.income(st, 50.0) // res0: Double = 250.0

可以增加前两行

Stadium.income(st, 50.0, Seq.fill(2)(75.0))// res1: Double = 325.0