S-99: Ninety-Nine Scala Problems(P21-P28)を解いてみた
S-99: Ninety-Nine Scala Problems(P11-P20)を解いてみたの続き。P21-P30ではなく、P21-P28になっているのは、P27とP28がそれぞれ二問ずつあり、P28で一端問題が区切られているため。今回のは、時間を測り忘れていたが、前回よりもややてこずった気がする。以下、回答のコード。
object P21toP28 { import P01toP10._ import P11toP20._ def mergeSort[T](list: List[T])(lt: (T, T) => Boolean): List[T] = { def merge(list1: List[T], list2: List[T]): List[T] = { (list1, list2) match { case (x::xs, y::ys) if lt(x, y) => x::merge(xs, list2) case (x::xs, y::ys) => y::merge(list1, ys) case (Nil, ys) => ys case (xs, Nil) => xs } } def mergeSort1(list: List[T], len: Int): List[T] = len match { case 0 => Nil case 1 => list case _ => val m = len / 2 val (fst, snd) = split(m, list) merge(mergeSort1(fst, m), mergeSort1(snd, len - m)) } mergeSort1(list, length(list)) } def insertAt[T](e: T, index: Int, list: List[T]): List[T] = list match { case x if index == 0 => e::x case x::xs if index > 0 => x::insertAt(e, index - 1, xs) case _ => error("") } def range(from: Int, to: Int): List[Int] = { if(from == to) List(to) else if(from < to) from::range(from + 1, to) else error("") } def randomSelect[T](n: Int, list: List[T]): List[T] = { def randomSelect1(n: Int, len: Int, list: List[T]): List[T] = { if(n == 0) List[T]() else if(n > 0) { val (rest, e) = removeAt((Math.random * len).toInt, list) e::randomSelect1(n - 1, len - 1, rest) } else error("") } val len = length(list) if(n <= len) randomSelect1(n, len, list) else error("") } def lotto(n: Int, m: Int): List[Int] = randomSelect(n, range(1, m)) def randomPermute[T](list: List[T]): List[T] = randomSelect(length(list), list) def groupInto[T](n: Int, k: Int, list: List[T]): List[(List[T], List[T])] = list match { case _ if k == n => List((list, Nil)) case _ if k == 0 => List((Nil, list)) case x::xs if k > 0 => append( map(groupInto(n - 1, k - 1, xs)){a => (x::a._1, a._2)}, map(groupInto(n - 1, k, xs)){a => (a._1, x::a._2)}) case _ => error("") } def combinations[T](k: Int, list: List[T]): List[List[T]] = { map(groupInto(length(list), k, list))(_._1) } def group3[T](list: List[T]): List[List[List[T]]] = { flatMap(groupInto(9, 2, list)){ case (s1, r) => flatMap(groupInto(7, 3, r)){ case (s2, r) => map(groupInto(4, 4, r)){ case (s3, r) => List(s1, s2, s3) }}} } def group[T](setting: List[Int], list: List[T]): List[List[List[T]]] = { def group_(setting: List[Int], n: Int, list: List[T]): List[List[List[T]]] = { setting match { case Nil => List(Nil) case x::xs => flatMap(groupInto(n, x, list)){ case (s, r) => map(group_(xs, n - x, r))(k => k.::(s)) } } } group_(setting, length(list), list) } def lsort[T](list: List[List[T]]): List[List[T]] = { map(mergeSort(map(list)(x => (x, length(x))))(_._2 < _._2))(_._1) } def lsortFreq[T](list: List[List[T]]): List[List[T]] = { val listl = map(list)(x => (x, length(x))) val freqs = foldLeft(listl, Map[Int, Int]()){ case (map, (lst, len)) => map(len) = map.getOrElse(len, 0) + 1 } map(mergeSort(map(listl)(x => (x._1, freqs(x._2))))(_._2 < _._2))(_._1) } }
実行例。
scala> import P21toP28._ import P21toP28._ scala> insertAt('new, 1, List('a, 'b, 'c, 'd)) res0: List[Symbol] = List('a, 'new, 'b, 'c, 'd) scala> range(4, 9) res1: List[Int] = List(4, 5, 6, 7, 8, 9) scala> randomSelect(3, List('a, 'b, 'c, 'd, 'f, 'g, 'h)) res2: List[Symbol] = List('d, 'b, 'c) scala> lotto(6, 49) res3: List[Int] = List(43, 7, 36, 25, 32, 34) scala> randomPermute(List('a, 'b, 'c, 'd, 'e, 'f)) res4: List[Symbol] = List('b, 'f, 'e, 'c, 'd, 'a) scala> combinations(3, List('a, 'b, 'c, 'd, 'e, 'f)) res5: List[List[Symbol]] = List(List('a, 'b, 'c), List('a, 'b, 'd), List('a, 'b, 'e), List('a, 'b, 'f), List('a, 'c, 'd), List('a, 'c, 'e), List('a, 'c, 'f), Li st('a, 'd, 'e), List('a, 'd, 'f), List('a, 'e, 'f), List('b, 'c, 'd), List('b, ' c, 'e), List('b, 'c, 'f), List('b, 'd, 'e), List('b, 'd, 'f), List('b, 'e, 'f), List('c, 'd, 'e), List('c, 'd, 'f), List('c, 'e, 'f), List('d, 'e, ... scala> group3(List("Aldo", "Beat", "Carla", "David", "Evi", "Flip", "Gary", "Hug o", "Ida")) res6: List[List[List[java.lang.String]]] = List(List(List(Aldo, Beat), List(Carl a, David, Evi), List(Flip, Gary, Hugo, Ida)), List(List(Aldo, Beat), List(Carla, David, Flip), List(Evi, Gary, Hugo, Ida)), List(List(Aldo, Beat), List(Carla, D avid, Gary), List(Evi, Flip, Hugo, Ida)), List(List(Aldo, Beat), List(Carla, Dav id, Hugo), List(Evi, Flip, Gary, Ida)), List(List(Aldo, Beat), List... scala> group(List(2, 2, 5), List("Aldo", "Beat", "Carla", "David", "Evi", "Flip" , "Gary", "Hugo", "Ida")) res7: List[List[List[java.lang.String]]] = List(List(List(Aldo, Beat), List(Carl a, David), List(Evi, Flip, Gary, Hugo, Ida)), List(List(Aldo, Beat), List(Carla, Evi), List(David, Flip, Gary, Hugo, Ida)), List(List(Aldo, Beat), List(Carla, F lip), List(David, Evi, Gary, Hugo, Ida)), List(List(Aldo, Beat), List(Carla, Gar y), List(David, Evi, Flip, Hugo, Ida)), List(List(Aldo, Beat), List... scala> lsort(List(List('a, 'b, 'c), List('d, 'e), List('f, 'g, 'h), List('d, 'e) , List('i, 'j, 'k, 'l), List('m, 'n), List('o))) res8: List[List[Symbol]] = List(List('o), List('m, 'n), List('d, 'e), List('d, ' e), List('f, 'g, 'h), List('a, 'b, 'c), List('i, 'j, 'k, 'l)) scala> lsortFreq(List(List('a, 'b, 'c), List('d, 'e), List('f, 'g, 'h), List('d, 'e), List('i, 'j, 'k, 'l), List('m, 'n), List('o))) res9: List[List[Symbol]] = List(List('o), List('i, 'j, 'k, 'l), List('f, 'g, 'h) , List('a, 'b, 'c), List('m, 'n), List('d, 'e), List('d, 'e))