LoginSignup
0
0

More than 5 years have passed since last update.

【解答例】Scala 代数的データ型 超入門

Posted at

Scala 代数的データ型 超入門の解答例です。

列挙型

【問1】光の三原色と、2つの色を混合する関数mixを定義してください。混ぜることによってできる色も定義の対象とします。ただし同じ成分同士は強め合わないものとします。

条件を列挙します。逆の組み合わせを一括処理しているのがポイントです。

mix.scala
object Color extends Enumeration {
  val Blue, Red, Magenta, Green, Cyan, Yellow, White = Value
}

object Main {
  import Color._

  def mix(a:Color.Value, b:Color.Value): Color.Value = {
    (a, b) match {
      case (Blue, Red)       => Magenta
      case (Blue, Magenta)   => Magenta
      case (Blue, Green)     => Cyan
      case (Blue, Cyan)      => Cyan
      case (Blue, Yellow)    => White
      case (Red, Magenta)    => Magenta
      case (Red, Green)      => Yellow
      case (Red, Cyan)       => White
      case (Red, Yellow)     => Yellow
      case (Magenta, Green)  => White
      case (Magenta, Cyan)   => White
      case (Magenta, Yellow) => White
      case (Green, Cyan)     => Cyan
      case (Green, Yellow)   => Yellow
      case (Cyan, Yellow)    => White
      case (White, _)        => White
      case (a, b) if a == b  => a
      case (a, b)            => mix(b, a)
    }
  }

  def main(args: Array[String]): Unit = {
    println(mix(Red, Red))
    println(mix(Red, Blue))
    println(mix(Blue, mix(Blue, Green)))
  }
}
実行結果
Red
Magenta
Cyan

直積型

【問2】x,y,w,hを表現したRect型を定義して、RectPointが含まれるかどうかを判定する関数containsを実装してください。

rect_answer.scala
sealed trait Coordinates
case class Point(x: Int, y: Int) extends Coordinates
case class Rect(x: Int, y: Int, w: Int, h: Int) extends Coordinates

def contains(r: Rect, p: Point): Boolean = {
  r.x <= p.x && p.x < r.x + r.w && r.y <= p.y && p.y < r.y + r.h
}

println(contains(new Rect(2, 2, 3, 3), new Point(1, 1)))
println(contains(new Rect(2, 2, 3, 3), new Point(2, 2)))
println(contains(new Rect(2, 2, 3, 3), new Point(3, 3)))
println(contains(new Rect(2, 2, 3, 3), new Point(4, 4)))
println(contains(new Rect(2, 2, 3, 3), new Point(5, 5)))

実行結果
false
true
true
true
false

直和型

【問3】RectPointを2次元と3次元の両方に対応させて、問2のcontainsも対応させてください。

rect3d_answer.scala
sealed trait Coordinates
case class Point(x: Int, y: Int) extends Coordinates
case class Point3D(x: Int, y: Int, z: Int) extends Coordinates
case class Rect(x: Int, y: Int, w: Int, h: Int) extends Coordinates
case class Rect3D(x: Int, y: Int, z: Int, w: Int, h: Int, d: Int) extends Coordinates

def contains(r: Rect, p: Point): Boolean = {
  r.x <= p.x && p.x < r.x + r.w && r.y <= p.y && p.y < r.y + r.h
}

def contains(r: Rect3D, p: Point3D): Boolean = {
  r.x <= p.x && p.x < r.x + r.w &&
  r.y <= p.y && p.y < r.y + r.h &&
  r.z <= p.z && p.z < r.z + r.d
}

println(contains(new Rect(2, 2, 3, 3), new Point(1, 1)))
println(contains(new Rect(2, 2, 3, 3), new Point(2, 2)))
println(contains(new Rect(2, 2, 3, 3), new Point(3, 3)))
println(contains(new Rect(2, 2, 3, 3), new Point(4, 4)))
println(contains(new Rect(2, 2, 3, 3), new Point(5, 5)))
println(contains(new Rect3D(2, 2, 2, 3, 3, 3), new Point3D(1, 1, 1)))
println(contains(new Rect3D(2, 2, 2, 3, 3, 3), new Point3D(2, 2, 2)))
println(contains(new Rect3D(2, 2, 2, 3, 3, 3), new Point3D(3, 3, 3)))
println(contains(new Rect3D(2, 2, 2, 3, 3, 3), new Point3D(4, 4, 4)))
println(contains(new Rect3D(2, 2, 2, 3, 3, 3), new Point3D(5, 5, 5)))
実行結果
false
true
true
true
false
false
true
true
true
false

レコード構文

【問4】問2の解答をレコード構文で書き直してください。

scala.rect_record_answer.scala
sealed trait Coordinates
case class Point(x: Int, y: Int) extends Coordinates
case class Rect(x: Int, y: Int, w: Int, h: Int) extends Coordinates

def contains(r: Rect, p: Point): Boolean = {
  r.x <= p.x && p.x < r.x + r.w && r.y <= p.y && p.y < r.y + r.h
}

println(contains(new Rect(x = 2, y = 2, w = 3, h = 3), new Point(x = 1, y = 1)))
println(contains(new Rect(x = 2, y = 2, w = 3, h = 3), new Point(x = 2, y = 2)))
println(contains(new Rect(x = 2, y = 2, w = 3, h = 3), new Point(x = 3, y = 3)))
println(contains(new Rect(x = 2, y = 2, w = 3, h = 3), new Point(x = 4, y = 4)))
println(contains(new Rect(x = 2, y = 2, w = 3, h = 3), new Point(x = 5, y = 5)))
実行結果
false
true
true
true
false
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0