Scala ラムダ 超入門の解答例です。
階乗
【問1】次に示す関数fact
をラムダ式で書き換えてください。
val fact : Int => Int = n => {
n match {
case 0 => 1
case n if n > 0 => n * fact(n - 1)
}
}
println(fact(5))
println(fact(0))
120
1
複数の引数
【問2】次に示す関数add
をラムダ式で書き換えてください。
val add : (Int, Int) => Int = (x, y) => x + y
println(add(2, 3))
println(add(9, 3))
5
12
無名関数
【問3】次に示す関数add
を定義せずに、呼び出し側で無名関数にインライン展開してください。
println(((x: Int, y: Int) => x + y)(2, 3))
5
高階関数
引数
【問4】次に示す関数f
とadd
を定義せずに、呼び出し側で無名関数にインライン展開してください。
println(((g: (Int, Int) => Int) => g(1, 2))((x: Int, y:Int) => x + y))
3
戻り値
【問5】次に示す関数add
を定義せずに、呼び出し側で無名関数にインライン展開してください。
println(((x: Int) => (y: Int) => x + y)(1)(2))
3
カリー化
【問6】次に示す関数combine
を、引数1つずつに分割してネストさせたラムダ式で書き換えてください。
val combine = (a: Any) => (b: Any) => (c: Any) => a +: b +: List(c)
val a = combine(1)
val b = a(2)
val c = b(3)
println(c)
println(combine('a')('b')('c'))
List(1, 2, 3)
List(a, b, c)
部分適用
【問7】次のコードから関数double
を除去してください。ラムダ式は使わないでください。
def f(xs: List[Int], g: (Int) => Int) = for (x <- xs) yield g(x)
println(f(List(1,2,3,4,5), (2.*)))
List(2, 4, 6, 8, 10)
演算子
【問8】次のコードからラムダ式を排除してください。新しい関数を定義してはいけません。
def f1(g: (Int) => Int) = g(1)
def f2(g: (Int, Int) => Int) = g(2, 3)
// 新しい関数を定義してはいけない
// def sub1(x:Int) = x - 3
// def sub2(x:Int) = 3 - x
// def add(x:Int, y: Int) = x + y
println(f1(3-_))
println(f1(_-(3)))
println(f2(_+_))
2
-2
5
再実装
再帰
【問9】map
, filter
, flip
, foldl
, foldr
を再帰で再実装してください。関数名にはm
を付けてください。
def mmap(g: Int => Int, xs: Seq[Int]): Seq[Int] = {
xs match {
case m if m.isEmpty => Seq()
case xs: Seq[Int] => g(xs.head) +: mmap(g, xs.tail)
}
}
def mfilter(g: Int => Boolean, xs: Seq[Int]): Seq[Int] = {
xs match {
case xs if xs.isEmpty => Seq()
case xs if g(xs.head) == true => xs.head +: mfilter(g, xs.tail)
case xs if g(xs.head) == false => mfilter(g, xs.tail)
}
}
def mflip[A, B, C](f: (A, B) => C)(x: B)(y: A) = f(y, x)
def mfoldLeft(g: (Int, Int) => Int, z: Int, xs: Seq[Int]): Int = {
(g, z, xs) match {
case (g, z, xs) if xs.isEmpty => z
case (g, z, xs) => mfoldLeft(g, g(z, xs.head), xs.tail)
}
}
def mfoldRight(g: (Int, Int) => Int, z: Int, xs: Seq[Int]): Int = {
(g, z, xs) match {
case (g, z, xs) if xs.isEmpty => z
case (g, z, xs) => g(xs.head, mfoldRight(g, z, xs.tail))
}
}
println(mmap((_*2), (1 to 5)))
println(mfilter((x => x < 5), (1 to 9)))
println(mflip(mmap)(1 to 5)(_*2))
println(mfoldLeft((_+_), 0, (1 to 100)))
println(mfoldLeft((_-_), 0, (1 to 5)))
println(mfoldRight((_-_), 0, (1 to 5)))
List(2, 4, 6, 8, 10)
List(1, 2, 3, 4)
List(2, 4, 6, 8, 10)
5050
-15
3
foldLeft
【問10】foldLeft
でreverse
とmaximum
とminimum
を再実装してください。関数名にはm
を付けてください。
def mreverse(xs: Seq[Int]): Seq[Int] = {
xs.foldLeft(Seq[Int]())((z, n) => n +: z)
}
def maximum(xs: Seq[Int]): Int = {
xs.foldLeft(xs.head)((z, n) => if (z < n) n else z)
}
def minimum(xs: Seq[Int]): Int = {
xs.foldLeft(xs.head)((z, n) => if (z > n) n else z)
}
println(mreverse((-5 to 5)))
println(maximum((-5 to 5)))
println(minimum((-5 to 5)))
List(5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5)
5
-5
クイックソート
【問11】次に示す関数qsort
をfilter
で書き替えてください。引数にはList型のリストを使用してください。
def qsort(xs: List[Int]): List[Int] = {
if (xs.length <= 1) xs
else {
val pivot = xs(xs.length / 2)
qsort(xs.filter(pivot >)) ++
xs.filter(pivot ==) ++
qsort(xs.filter(pivot <))
}
}
println(qsort(List(4, 6, 9, 8, 3, 5, 1, 7, 2)))
List(1, 2, 3, 4, 5, 6, 7, 8, 9)
バブル
【問12】次に示すバブルソートの関数bswap
をfoldRight
で書き替えてください。
def bsort(list: List[Int]): List[Int] = {
def bswap(xs: List[Int]): List[Int] = {
xs.foldRight(List[Int]())((z, n) => {
n match {
case n if n.isEmpty => List(z)
case n => {
if (z > n.head) n.head :: z :: n.tail
else z :: n.head :: n.tail
}
}
})
}
val ys = bswap(list)
ys match {
case list if ys.isEmpty => List()
case list => ys.head :: bsort(ys.tail)
}
}
println(bsort(List(4,3,1,5,2)))
println(bsort(List(4,6,9,8,3,5,1,7,2)))
List(1, 2, 3, 4, 5)
List(1, 2, 3, 4, 5, 6, 7, 8, 9)
sum
【問13】Yコンビネータを使って関数sum
を再実装してください。
def Y[A,B]( f:((A => B), A ) => B, x:A ):B = f( ( y:A ) => Y( f,y ),x )
val y = Y( (f:Seq[Int] => Int , n:Seq[Int]) => n match {
case n if n.isEmpty => 0
case _ => n.head + f(n.tail)
}, (1 to 100))
println(y)
5050