[随笔] 出几个小题,活跃下版面

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
Global site tag (gtag.js) - Google Analytics