[随笔] 出几个小题,活跃下版面
Eastsun
2009-10-08
规则:只须使用Scala标准API,可以使用任意版本(包括2.8.x),代码越短越好
1.实现方法: def group[T](ls: List[T]): List[List[T]] = {..} 其功能为:将ls中以连续相同元素为组分开,保持先后顺序;简单说就是实现haskell中List的group功能 e.g.: [1,2,2,1,1,1,2,2,2,1] => [[1],[2,2],[1,1,1],[2,2,2],[1]] 2.实现方法: def sizeOfGroup[T](ls: List[T]): Int = {..} 功能:就是group(ls).size,但不允许直接调用上面的方法 3.实现方法: def groupN[T](ls: List[T],n: Int): List[List[T]] = {..} 功能:将ls依次分段,每段n个,最后一段可以是不大于n的任意个数 4.来个好玩点的: def solve(ls: List[Int],n: Int): Unit 功能:使用ls中的数通过加减乘除以及括号运算得到n,打印出所有的解 其中1 <= ls.size <= 6,且ls中的值在区间[1,13] |
|
night_stalker
2009-10-08
先把容易的占领了 …… 最后一个根本不好玩,写过 Haskell 版本觉得很不爽 ……
def group[T](ls: List[T]): List[List[T]] = { var res = List[List[T]]() def f(ls: List[T]) { ls match { case Nil => () case x :: xs => res ++= List(ls takeWhile (_ == x)) f(xs dropWhile (_ == x)) } } f(ls) res } def groupN[T](ls: List[T], n: Int): List[List[T]] = ls match { case Nil => Nil case ls => (ls take n) :: groupN(ls drop n, n) } val l = List(1,2,2,1,1,1,2,2,2,1) Console println group(l) Console println groupN(l, 4) |
|
RednaxelaFX
2009-10-08
group的话要是不用takeWhile和dropWhile貌似也长不到哪里去……只需要cons然后叠一次就完事了:
def group[T](l: List[T]): List[List[T]] = l.foldRight(Nil: List[List[T]]) { (e, acc) => acc match { case x :: xs => x match { case xx :: _ if (xx == e) => (e :: x) :: xs case _ => List(e) :: acc } case _ => List(e) :: acc } } F#的话: let group l = List.foldBack (fun e acc -> match acc with | x :: xs -> match x with | xx :: _ when xx = e -> (e :: x) :: xs | _ -> [e] :: acc | _ -> [[e]]) l [] |
|
night_stalker
2009-10-08
话说我对各种 inject, foldr, foldRight, /:, foldBack …… 绝望了 …… 他们就不能统一一下意见么 ……
|
|
RednaxelaFX
2009-10-08
night_stalker 写道 话说我对各种 inject, foldr, foldRight, /:, foldBack …… 绝望了 ……
OCaml和老版本的F#是fold_right......绝望+1 话说还有些地方是重载了reduce的,不给seed的时候就是普通的reduce,给seed就变成了fold OTL LINQ里的Aggregate就是这种重载了的reduce…… |
|
night_stalker
2009-10-09
无它,唯 shorter 尔 …… (重构强迫症……)
def group[T](ls: List[T]) = (ls :\ List[List[T]]()) { case (e, x :: xs) if x contains e => (e :: x) :: xs case (e, acc) => List(e) :: acc } def sizeOfGroup[T](ls: List[T]) = ((0, None: Option[T]) /: ls) {(acc, e) => (acc._1 + (if(acc._2 == Some(e)) 0 else 1), Some(e)) } _1 // 模式匹配版 …… def sizeOfGroup2[T](ls: List[T]) = ((0, None: Option[T]) /: ls) { case ((n, Some(x)), e) if x == e => (n, Some(e)) case ((n, _), e) => (n + 1, Some(e)) } _1 |
|
RednaxelaFX
2009-10-09
hmm,contains么。那拆开来也可以:
def group[T](l: List[T]): List[List[T]] = (l :\ List[List[T]]()) { case (e, (xx :: xxs) :: xs) if xx == e => (e :: xx :: xxs) :: xs case (e, acc) => List(e) :: acc } 好吧我被说服用滑梯符号了 |
|
night_stalker
2009-10-09
姑且将右滑梯结构称为 "R 模式",那么
def R[V](init: V)(f: ((Any, V) =>V)) = new Object { def apply[T] (ls: List[T]) = (ls :\ init)(f.asInstanceOf[(T, V) => V]) } val group = R(List[List[Any]]()) { case (e, x :: xs) if x.first == e => (e :: x) :: xs case (e, acc) => List(e) :: acc } val sizeOfGroup_ = R((0, None: Option[Any])) { case (e, (n, Some(x))) if x == e => (n, Some(e)) case (e, (n, _)) => (n + 1, Some(e)) } val l = List(1,2,2,1,1,1,2,2,2,1) Console println group(l) Console println sizeOfGroup_(l)._1 -_- 不爽之处在于静态语言限制太多了…… |
|
Eastsun
2009-10-09
呵呵,我自己也来一个:
//Scala2.8.x def sizeOfGroup[T](ls: List[T]) = ls.zip(null::ls).count{case(x,y) => x != y} //Scala2.7.x scala> def sizeOfGroup[T](ls: List[T]) = ls.zip(null::ls).filter{case(x,y) => x != y}.size 好吧,我有吧代码写成一行的嗜好。。。 |
|
Eastsun
2009-10-09
Oops,上面的代码有问题,看来得多写几个字符才行:
def sizeOfGroup[T](ls: List[T]) = ls.zip(new Object::ls).filter{case(x,y) => y != x}.size |