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
型を定義して、Rect
にPoint
が含まれるかどうかを判定する関数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】Rect
とPoint
を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